准备:
所有文件目录请不要中文命名,请使用英文

  1. nginx服务 官网下载
  2. niginx服务 视频推流版

在这里插入图片描述
3. 配置文件 nginx-rtmp-module
4. 推流文件 ffmpeg
5. 拉流工具 vlc

步骤:

一,下载好nginx视频版,解压,在nginx 1.7.11.3 Gryphon目录下新建三个文件夹:

  • m3u8File
  • rec
  • vod
    在这里插入图片描述
    二,将nginx-rtmp-module 下载好丢进去(上图有)

三,在conf目录下,新建一个文件“nginx.conf”

worker_processes  1;   #Nginx进程数,建议设置为等于CPU总核数
 
events {
    worker_connections  1024;  #工作模式与连接数上限
}
 
rtmp_auto_push on;
 
#RTMP服务
rtmp{
    server{
    	listen 1935;        #服务端口
	chunk_size 4096;    #数据传输块的大小	
	application vod{
	play ./vod;   #视频文件存放位置
	}
	application live{
    	live on;                     #   
	hls on;                      #开启hls直播。这个参数把直播服务器改造成实时回放服务器
	#wait_key on;                #对视频切片进行保护,这样就不会产生马赛克了
	hls_path ./html/hls;         #切片视频文件存放位置(HLS,m3u8文件存放位置)
	hls_fragment 2s;             #每个视频切片的时长
	hls_playlist_length 16s;
	recorder myRecord{
	record all manual;
	record_suffix _.flv;
	record_path ./rec;
	}
	#hls_continuous on;          #连续模式
	#hls_cleanup on;             #对多余的切片进行删除
	#hls_nested on;              #嵌套模式
	}
    }
}
 
#HTTP服务
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
 
    server {
        listen       80;
        server_name  localhost;
 
        location / {
            root   html;
            index  index.html index.htm;
        }
 
        location /live_hls{
		    types{
			    #m3u8 type设置
				application/vnd.apple.mpegurl m3u8;
				#ts分片文件设置
				video/mp2t ts;
			}
			#指向访问m3u8文件目录
			alias ./html/hls;
			    add_header Cache-Control no-cache; #禁止缓存
		}
 
        location /control{
		    rtmp_control all;
		}
		
		location /stat{
		    rtmp_stat all;
			rtmp_stat_stylesheet stat.xsl;
		}
		
		location /stat.xsl{
		    root ./nginx-rtmp-module-master;
		}
 
        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

此处主要注意

rtmp{
	listen 1935;        #(推流)服务端口
}

http {
	server {
        listen       80;#启动服务端口
    }
    location /stat.xsl{
		root ./nginx-rtmp-module-master;
	}
}

四,cmd在nginx.exe所在的目录启动nginx,输入命令: start nginx 在浏览器输入127.0.0.1或者localhost

在这里插入图片描述

说明成功了另外情况

在这里插入图片描述

在这里插入图片描述

可能遇到的bug,下篇文章细细道来

五,推流(推荐文章)

部署ffmpeg

解压下载好的ffmpeg,打开到bin,并复制路径准备配置环境变量
在这里插入图片描述

在这里插入图片描述

配置完:
当前使用的是本地视频推流:

  • movie.mp4: 文件路径,当前此文件在bin下面
  • 127.0.0.1: IP地址
  • rtmp: nginx.conf内配置的rtmp端口
  • 123: 自定义接口名
ffmpeg.exe -re -i  movie.mp4 -f flv rtmp://127.0.0.1:1935/live/123

当然,你也可以直接在视频文件的目录输入推流命令(配置好ffmpeg后,任何地方cmd,可以推流的)

在这里插入图片描述

六,拉流测试工具

mp4地址:

在这里插入图片描述
在这里插入图片描述

注意:推流和拉流要同时打开,才能看到视频

本地推流拉流就完成了

七,uniapp 推流/拉流

直接上代码吧

<template>
	<div>
		<live-pusher
			id="livePusher"
			ref="livePusher"
			class="livePusher"
			url="rtmp://192.168.2.96:1935/live/123"
			mode="SD"
			:muted="true"
			:enable-camera="true"
			:auto-focus="true"
			:beauty="1"
			whiteness="2"
			aspect="9:16"
			@statechange="statechange"
			@netstatus="netstatus"
			@error="error"
		></live-pusher>
		<button class="btn" @click="start">开始推流</button>
		<button class="btn" @click="pause">暂停推流</button>
		<button class="btn" @click="resume">resume</button>
		<button class="btn" @click="stop">停止推流</button>
		<button class="btn" @click="snapshot">快照</button>
		<button class="btn" @click="startPreview">开启摄像头预览</button>
		<button class="btn" @click="stopPreview">关闭摄像头预览</button>
		<button class="btn" @click="switchCamera">切换摄像头</button>
		<button class="btn" @click="bofang">去播放</button>
		<u-modal v-model="show" :content="content"></u-modal>
		<u-toast ref="uToast" />
	</div>
</template>

<script>
export default {
	data() {
		return {
			context: [],
			show: false,
			content: '成功'
		};
	},
	onReady() {
		// 注意:需要在onReady中 或 onLoad 延时
		this.context = uni.createLivePusherContext('livePusher', this);
	},
	methods: {
		statechange(e) {
			console.log('statechange:' + JSON.stringify(e));
			alert(1);
		},
		netstatus(e) {
			console.log('netstatus:' + JSON.stringify(e));
		},
		error(e) {
			console.log('error:' + JSON.stringify(e));
		},
		start() {
			this.context.start({
				success: a => {
					console.log('livePusher.start:' + JSON.stringify(a));
				},
				error: err => {
					console.log(err);
				}
			});
		},
		close() {
			this.context.close({
				success: a => {
					console.log('livePusher.close:' + JSON.stringify(a));
				}
			});
		},
		snapshot() {
			this.context.snapshot({
				success: e => {
					console.log(JSON.stringify(e));
				}
			});
		},
		resume() {
			this.context.resume({
				success: a => {
					console.log('livePusher.resume:' + JSON.stringify(a));
				}
			});
		},
		pause() {
			this.context.pause({
				success: a => {
					console.log('livePusher.pause:' + JSON.stringify(a));
				}
			});
		},
		stop() {
			this.context.stop({
				success: a => {
					console.log(JSON.stringify(a));
				}
			});
		},
		switchCamera() {
			this.context.switchCamera({
				success: a => {
					console.log('livePusher.switchCamera:' + JSON.stringify(a));
				}
			});
		},
		startPreview() {
			this.context.startPreview({
				success: a => {
					console.log('livePusher.startPreview:' + JSON.stringify(a));
				}
			});
		},
		stopPreview() {
			this.context.stopPreview({
				success: a => {
					console.log('livePusher.stopPreview:' + JSON.stringify(a));
				}
			});
		},
		bofang() {
			//跳转到video页面
			uni.navigateTo({
				url:'./video',
			})
		}
	}
};
</script>

<style></style>

video内的src 地址就是vlc内地址,此处 将其地址替换vlc就行

<template>
	<view style="height: 100vh;">
		<view class="uni-padding-wrap uni-common-mt">
			<view style="height: 30vh;">
				<video
					id="myVideo"
					src="https://img.cdn.aliyun.dcloud.net.cn/guide/uniapp/%E7%AC%AC1%E8%AE%B2%EF%BC%88uni-app%E4%BA%A7%E5%93%81%E4%BB%8B%E7%BB%8D%EF%BC%89-%20DCloud%E5%AE%98%E6%96%B9%E8%A7%86%E9%A2%91%E6%95%99%E7%A8%8B@20200317.mp4"
					style="width: 100%;"
					@error="videoErrorCallback"
					:danmu-list="danmuList"
					enable-danmu
					danmu-btn
					controls
					autoplay="true"
				></video>
			</view>
			<view>
				<scroll-view class="danmu-box" scroll-y="true"   :scroll-top="scrollTop" id="scrollview" >
					<view id="msglistview" class="scrollview">
						<view v-for="(item, index) in danmuList" :key="index" >
							<text>{{ item.text }}</text>
						</view>
					</view>
				</scroll-view>
			</view>
			<!-- #ifndef MP-ALIPAY -->
			<view class="uni-list uni-common-mt" style="height: 5vh;">
				<view class="uni-list-cell setpan-box">
					<view class="inputdm"><u-input v-model="danmuValue" placeholder="在此处输入弹幕内容" border="true" /></view>
					<view class="btn"><u-button type="primary" @click="sendDanmu" size="medium">发送弹幕</u-button></view>
				</view>
			</view>
			<!-- #endif -->
		</view>
	</view>
</template>

<script>
export default {
	data() {
		return {
			scrollTop:0,
			toView:'z',
			src: '',
			danmuList: [
				{
					text: '第一条弹幕',
					color: '#ff0000',
					time: 1
				},
			],
			danmuValue: ''
		};
	},
	onReady: function(res) {
		// #ifndef MP-ALIPAY
		this.videoContext = uni.createVideoContext('myVideo');
		// #endif
	},
	mounted() {
		this.scrollToBottom();
	},
	updated() {
		this.scrollToBottom();
	},
	methods: {
		/*
		 * 功能:发送弹幕
		 *
		 */
		sendDanmu: function() {
			let a = {};
			this.videoContext.sendDanmu({
				text: this.danmuValue,
				color: this.getRandomColor()
			});
			a.text = this.danmuValue;
			this.danmuList.push(a);
			this.danmuValue = '';
			
		},
		/*
		 * 功能:加载视频失败
		 *
		 */
		videoErrorCallback: function(e) {
			uni.showModal({
				content: e.target.errMsg,
				showCancel: false
			});
		},
		/*
		 * 功能:弹幕字体颜色
		 *
		 */
		getRandomColor: function() {
			const rgb = [];
			for (let i = 0; i < 3; ++i) {
				let color = Math.floor(Math.random() * 256).toString(16);
				color = color.length == 1 ? '0' + color : color;
				rgb.push(color);
			}
			return '#' + rgb.join('');
		},
		/*
		 * 功能:弹幕在页面底部
		 *
		 */
		scrollToBottom() {
			let _this = this;
			let query = uni.createSelectorQuery();
			query.select('#scrollview').boundingClientRect();
			query.select('#msglistview').boundingClientRect();
			query.exec(res => {
				console.log('res---------',res)
				if (res[1].height > res[0].height) {
					_this.scrollTop = res[1].height - res[0].height + 40;
					console.log('scrollheight',this.scrollTop)
				}
			});
		}
	}
};
</script>

<style scoped>
.danmu-box {
	width: 100%;
	height: 55vh;
	padding: 20px;
	overflow-y: scroll;
}
.scrollview{
}
.setpan-box {
	display: flex;
	margin: 10px;
	align-items: center;
}
.inputdm {
	margin-right: 10px;
	width: 70%;
}
text {
	font-size: 17px;
	margin-top: 5px;
}
</style>

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐