网上关于直播相关的文章很多,但是讲解还是不够系统,对于刚刚接触直播开发的朋友实施起来会浪费不少时间。下面结合我自己的经验,
介绍一下直播方面的实战经验。
分成两个部分
第一部分是标题中介绍的基于RTMP推送文件流与视频流,PC端拉流RTMP,移动端拉流m3u8也就是hls
下一篇介绍基于websocket+canvas,进行拉流播放。
一 准备工作
1.准备RTMP服务器,我是在win10下开发,我是安装了docker for windows,然后下载镜像nginx-rtmp-server,(使用linux的朋友就更方便了,docker pull antongulenko/rtmp-nginx-server),点击Create后自动安装
安装完成后,保存当前的端口号,为了防止每次重启容器端口号自动分配,点击保存按钮 如图:
1935是本机RTMP对应的端口,外部映射的是 32781,稍候我们会用到这个端口号进行推流。
此时nginx还没有进行配置,我们需要配置,首先找到nginx.conf,
首先进入容器,具体的操作我只记录docker for windows的,linux就更简洁了,docker exec 容器id。
可以查看容器的目录结构
nginx的路径是etc/nginx/nginx.conf
首先拷贝下来,修改后,再覆盖回去,覆盖后要重启nginx,才能生效。
下面的指令是分别从容器上把配置文件拷贝到D盘,修改后 将文件覆盖回容器内
具体conf内容如下:
worker_processes auto;
rtmp_auto_push on;
events {} rtmp {
server {
listen 1935;
listen [::]:1935 ipv6only=on; application vod {
play /opt/rtmp/vod;
}
application mirror_cache {
play /opt/rtmp/vod_mirror;
} application live{
# enable live streaming
live on; max_connections 1024; } application hls{
live on;
hls on;
hls_path /usr/local/hls;
hls_fragment 5s;
} # Application names cannot contain patterns, and play_local_path fails for cached files
# that contain slashes (error dir not found). Therefore, list every path of interest as a separate
# application, so that only files without directory prefix are cached.
application mirror/720 {
play /opt/rtmp/vod_mirror http://www.sample-videos.com/video/flv/720/;
play_local_path /opt/rtmp/vod_mirror;
}
application mirror/480 {
play /opt/rtmp/vod_mirror http://www.sample-videos.com/video/flv/480/;
play_local_path /opt/rtmp/vod_mirror;
}
application mirror/360 {
play /opt/rtmp/vod_mirror http://www.sample-videos.com/video/flv/360/;
play_local_path /opt/rtmp/vod_mirror;
}
application mirror/240 {
play /opt/rtmp/vod_mirror http://www.sample-videos.com/video/flv/240/;
play_local_path /opt/rtmp/vod_mirror;
} }
} http {
server {
listen 8080; # This URL provides RTMP statistics in XML
location /stat {
rtmp_stat all;
rtmp_stat_stylesheet stat.xsl;
} location /stat.xsl {
root /opt/rtmp/http/;
} location /hls{
types{
application/vnd.apple.mpegurl m3u8;
video/mp2t ts;
}
alias /usr/local/hls;
add_header Cache-Control no-cache;
} location /vod {
autoindex on;
alias /opt/rtmp/vod;
} location /mirror_cache {
autoindex on;
alias /opt/rtmp/vod_mirror;
} location /mirror/ {
proxy_pass http://www.sample-videos.com/video/;
}
}
}
配置文件中的 application live 与 application hls就是分别推送rtmp与hls协议的路由地址
而http节点就是用于手机端使用m3u8播放的时候(http://ip+port/hls/秘钥.m3u8)的配置。
然后重启容器就可以了。 2.github下载https://github.com/BoonyaCSharp-ASP/VedioFFmpegPushRTMP
基于c#封装的FFMPEG的推流方法,使用的时候需要下载FFMPEG的相关文件,
我这里提供一下连接,直接解压覆盖,注意link类型为shared
https://ffmpeg.zeranoe.com/builds/
这个c#工程可以直接运行,配置使用也是很难得,不过我为了测试方便还是直接用命令行的方式进行推流
命令行进入x64文件夹下,直接使用ffmpeg.exe进行推流,ffplay.exe以直接进行播放。
下面开始推流:
1.推送文件流,我在x64下面放置了1.MP4的文件
推流指令如下
ffmpeg.exe -re -i 1.mp4 -f flv rtmp://192.168.1.253:32781/rtmp/test
192.168.1.253是我的rtmp服务器ip 32781是docker中rtmp的外部端口 (如果不使用docker自然就是1935了)
rtmp 是nginx.conf 配置的rtmp的路由节点名称 test类似于房间号的概念,拉流的时候也指定这个房间号,就可以对应到自己要看的直播流
推流如下:
如果有异常信息就是相关参数的配置,具体问题留言讨论。
拉取文件流
可以下载vlc播放器,然后配置拉流地址 rtmp://192.168.1.253:32781/rtmp/test 就可以点击播放
PC端播放rtmp代码如下,建议使用Chrome,并且设置flash允许
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>使用video.js实现rtmp流的直播播放</title>
<!--引入播放器样式-->
<link href="http://vjs.zencdn.net/5.19/video-js.min.css" rel="stylesheet">
<!--引入播放器js-->
<script src="http://vjs.zencdn.net/5.19/video.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/videojs-flash@2/dist/videojs- flash.min.js"></script>
</head>
<body> <!--vjs-big-play-centered 播放按钮居中-->
<!--poster默认的显示界面,就是还没点播放,给你显示的界面-->
<!--controls 规定浏览器应该为视频提供播放控件-->
<!--preload="auto" 是否提前加载-->
<!--autoplay 自动播放-->
<!--loop=true 自动循环-->
<!--data-setup='{"example_option":true}' 可以把一些属性写到这个里面来,如data-setup= {"autoplay":true}--> <video id="my-player" class="video-js vjs-default-skin vjs-big-play-centered" controls preload="auto" autoplay="autoplay"
poster="//vjs.zencdn.net/v/oceans.png" width="500" height="400" data- setup='{}'>
<!--src: 规定媒体文件的 URL type:规定媒体资源的类型-->
<source src='rtmp://192.168.1.253:32781/live/test' type='rtmp/flv'/>
</video>
<script type="text/javascript">
// 设置flash路径,用于在videojs发现浏览器不支持HTML5播放器的时候自动唤起flash播放器
videojs.options.flash.swf = 'https://cdn.bootcss.com/videojs-swf/5.4.1/video- js.swf';
var player = videojs('my-player'); //my-player为页面video元素的id
player.play(); //播放
// 1. 播放 player.play()
// 2. 停止 player.pause()
// 3. 暂停 player.pause()
</script>
</body>
</html>
2.推送视频流
如果直接按照如下命令推送
ffmpeg -f dshow -i video="Integrated Camera" -vcodec libx264 -acodec aac -f flv rtmp://192.168.1.253:32781/live/test
很有可能vlc ffplay可以正常拉流播放,但是网页播放不了,推荐一个网址测试对应的rtmp协议流是否能通过flash播放
https://blog.csdn.net/liuzehn/article/details/81036195
可用的RTMP源:http://www.mamicode.com/info-detail-2539819.html
如果测试过程中能够接受到流,但是不能播放就是视频格式的问题,
这时候使用如下的指令进行播放:
ffmpeg.exe -f dshow -i video="Integrated Camera" -vcodec libx264 -pix_fmt yuv420p -f flv rtmp://192.168.1.253:32781/live/test
其中 Integrated Camera 是摄像头的名字,如果是USB的则填写对应的名字
具体的获得摄像头名称的操作方式参考:
https://www.jianshu.com/p/c141fc7881e7
3.推送视频流,hls播放
推流指令如下:
ffmpeg.exe -f dshow -i video="Integrated Camera" -vcodec libx264 -pix_fmt yuv420p -f flv rtmp://192.168.1.253:32781/hls/test
移动端拉流代码:
<!DOCTYPE html>
<html lang="en">
<head> <title>Video.js | HTML5 Video Player</title>
<!-- <link href="video-js-6.2.0/video-js.css" rel="stylesheet">
<script src="video-js-6.2.0/videojs-ie8.min.js"></script> --> <link href="http://vjs.zencdn.net/5.20.1/video-js.css" rel="stylesheet">
<script src="http://vjs.zencdn.net/5.20.1/videojs-ie8.min.js"></script> </head>
<body> <video id="example_video_1" class="video-js vjs-default-skin" controls preload="auto" width="1280" height="720" poster="http://vjs.zencdn.net/v/oceans.png" data-setup="{}">
<!-- <source src="1.mp4" type="video/mp4"> rtmp://192.168.1.253:32781/live/test -->
<source src="http://192.168.1.253:32780/hls/test.m3u8" type="application/x- mpegURL" > <p class="vjs-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that <a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a></p>
</video>
<object height="900px" width="100%" classid="clsid:D27CDB6E-AE6D-11cf-96B8- 444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#versio n=9,0,28,0" id="abcdef">
<param value="index.swf(flash路径)" name="movie">
<param value="high" name="quality">
<param value="transparent" name="wmode">
<embed height="900px" width="100%" name="abcdef" wmode="transparent" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/shockwave/download/download.cgi? P1_Prod_Version=ShockwaveFlash" quality="high" src="rtmp://192.168.1.253:32781/live/test">
</object>
<script src="http://vjs.zencdn.net/5.20.1/video.js"></script>
</body> </html>
rtmp如果有vlc会有延迟,是vlc本身的缓存原因,ffplay几乎0延迟,PC版本的一秒左右延迟,m3u8分片的方式处理,所以延迟会比较明显。
flv的直播 可参考连接https://hub.docker.com/r/mugennsou/nginx-http-flv ,但是需要注意的是
如果要推送摄像头到服务器并在手机端显示,要参考下面的指令和代码:
推送指令:
<!DOCTYPE html>
<html lang="en"> <head>
<title>video</title>
<!-- Video.js -->
<link href="https://unpkg.com/video.js/dist/video-js.css" rel="stylesheet">
<script src="https://unpkg.com/video.js/dist/video.min.js"></script>
<script src="https://unpkg.com/flv.js/dist/flv.min.js"></script>
<script src="https://unpkg.com/videojs-flvjs/dist/videojs-flvjs.min.js"></script>
</head> <body>qwer
<div>
<video id="videojs-flvjs-player" class="video-js vjs-default-skin vjs-big-play-centered" width="1024" height="768"> </video>
</div>
</body> </html>
<script>
var flvUrl = "http://192.168.1.253:32783/live?app=demo&stream=stream-1";
//flvUrl="https://mister-ben.github.io/videojs-flvjs/bbb.flv"
var player = videojs('videojs-flvjs-player', {
techOrder: ['html5', 'flvjs'],
flvjs: {
mediaDataSource: {
isLive: true,
cors: true,
withCredentials: false,
},
},
sources: [{
src: flvUrl,
type: 'video/mp4'
}],
controls: true,
preload: "none"
}, function onPlayerReady() {
console.log('player ready') player.on('error', (err) => {
console.log('first source load fail') player.src({
src: flvUrl,
type: 'video/x-flv'
}); player.ready(function() {
console.log('player ready')
player.load();
player.play();
});
})
});
</script>
html文件最好是放到服务器中运行,本地打开的html页可能无法正常显示。
下一篇再介绍基于websocket的移动端直播