最近在研究html5实时播放rtsp流的问题,目前来说h5原生不支持这种格式,网上查了很多教程,大概有以下几种思路。
rtsp转rtmp
rtmp需要falsh的支持,但是在chrome已经默认禁用、包括未来也会逐渐淘汰,所以最终没有采取。
rtsp转hls
这个研究不是太深入,很多东西也没搞明白,只找到了一些相简单的操作。这种方法需要借助第三方库ffmpeg,利用ffmpeg将mp4格式或者rtsp流进行切片,我们可以获得hls的m3u8索引文件以及大量ts文件,但是大多数浏览器不支持原生的hls这种方式。可能因为研究不够深入,最后并没有利用hls播放成功,若有成功的小伙伴欢迎来指导。
使用ffmpeg对MP4文件进行点播切片
segment模块来进行对source.mp4文件进行切片
segment_format 用来指定输出格式为mpegts
segment_list用来配置输出的列表文件名
segment_time则是切片的时长
ffmpeg -i source.mp4 -codec:v libx264 -codec:a mp3 -map 0 -f ssegment -segment_format mpegts -segment_list C:/Users/Administrator/Desktop/nginx-1.8.1/html/hls/playlist.m3u8 -segment_time 10 out%03d.ts
使用ffmpeg对MP4文件进行直播切片
-segment_list_flags +live 直播,并且加上了-re参数(该参数表示ffmpeg将会按照source.mp4的播放速率进行转码)
segment_list_size参数将列表数量控制在6个
ssegment模块有个缺点,虽然可以通过以上方式达到直播,但是生成的TS文件并不会循环,会一直被保留
ffmpeg -re -i source.mp4 -codec:v libx264 -codec:a mp3 -map 0 -f ssegment -segment_format mpegts -segment_list playlist.m3u8 -segment_list_flags +live -segment_list_size 6 -segment_time 10 out%03d.ts
使用HLS模块进行视频文件切片的指令如下:
hls_list_size即为HLS播放的列表
hls_wrap则表示为最大的TS循环数
也就是每10个一个循环
ffmpeg -re -i source.mp4 -codec:v libx264 -codec:a libfaac -map 0 -f hls -hls_list_size 6 -hls_wrap 10 -hls_time 10 playlist.m3u8
对rtsp流直接进行切片
ffmpeg -i "rtsp://" -fflags flush_packets -max_delay 1 -an -flags -global_header -hls_time 1 -hls_list_size 3 -hls_wrap 3 -vcodec copy -y C:/Users/Administrator/Desktop/videochannel101.m3u8
ffmpeg -y -i "rtsp:" -c:v copy -map 0:0 -flags -global_header -f segment -segment_list C:/Users/Administrator/Desktop/video/playlist.m3u8 -segment_time 10 -segment_format mpeg_ts -segment_list_type m3u8 segment%05d.ts
node.js播放rtsp
这种方式借助了一些现有的代码,最后简单的实现了。要运行程序需要node.js(参考菜鸟教程)和ffmpeg(添加环境变量)。
cmd到程序目录:node index.js
然后打开index.html,修改其中config中的url, video标签可添加多个也可以访问不同的rtsp的url。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>HTML5视频直播测试</title>
<script src="/socket.io/socket.io.js"></script>
</head>
<body>
<video id="mse" muted width="480" height="330" ></video>
<script>
var mime = 'video/mp4; codecs="avc1.64001E"';
var buffer;
var socket;
var video = document.getElementById('mse');
var mediaSource = new MediaSource();
video.src = URL.createObjectURL(mediaSource);
video.play();
mediaSource.addEventListener('sourceended', function (e) {
console.log('sourceended: ' + mediaSource.readyState);
});
mediaSource.addEventListener('sourceclose', function (e) {
console.log('sourceclose: ' + mediaSource.readyState);
});
mediaSource.addEventListener('error', function (e) {
console.log('error: ' + mediaSource.readyState);
});
mediaSource.addEventListener('sourceopen', function (e) {
buffer = mediaSource.addSourceBuffer(mime);
buffer.mode = 'sequence';
buffer.addEventListener('updateend', function (e) {
//hack to get safari on mac to start playing, video.currentTime gets stuck on 0
if (mediaSource.duration !== Number.POSITIVE_INFINITY && video.currentTime === 0 &&
mediaSource.duration > 0) {
video.currentTime = mediaSource.duration - 1;
mediaSource.duration = Number.POSITIVE_INFINITY;
}
});
socket = io(null, {
transports: ['websocket']
});
var config = {
channelid: '1',
channelname: '测试摄像头',
//rtsp://admin:root60161@192.168.60.161:554/cam/realmonitor?channel=1&subtype=1
url: 'rtsp://admin:root172@192.168.60.172:554/cam/realmonitor?channel=1&subtype=1'
};
socket.emit('start', JSON.stringify(config));
socket.on('segment', function (data) {
var data = new Uint8Array(data);
buffer.appendBuffer(data);
});
}, false);
</script>
</body>
</html>
修改完成后,可以在本地访问http://localhost:8080/就可以获取当前的视频。
出现的问题:
Error: Cannot find module ‘socket.io’
cmd进入程序父辈目录然后 输入npm install socket.io
html5播放rtsp视频流还有一些其他方法,后续会继续研究更新。