Windows nginx + rtmp 流媒体服务器搭建(uniapp可用)
准备:所有文件目录请不要中文命名,请使用英文nginx服务官网下载niginx服务视频推流版3.配置文件nginx-rtmp-module4.推流文件ffmpeg5.拉流工具vlc步骤:一,下载好nginx视频版,解压,在nginx 1.7.11.3 Gryphon目录下新建三个文件夹:m3u8Filerecvod二,将nginx-rtmp-module 下载好丢进去(上图有)三,在conf目录下
·
准备:
所有文件目录请不要中文命名,请使用英文
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,可以推流的)
六,拉流测试工具
注意:推流和拉流要同时打开,才能看到视频
本地推流拉流就完成了
七,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>
更多推荐
已为社区贡献1条内容
所有评论(0)