Rob*_*Rob 5 ffmpeg video-streaming http-live-streaming video.js hls.js
.ts段ffmpeg,并将新.ts段自动添加到 HLS 流(例如.m3u8文件)中。.m3u8更新时,我想正在观看的视频流,以简单的“继续”,在那里新的点推进.ts段已被添加。为了生成流的“前”几段,我正在尝试以下操作(现在只是命令行以使 ffmpeg 正常工作,但最终将通过 Python 脚本自动化):
作为参考,我使用的是 ffmpeg版本 3.4.6-0ubuntu0.18.04.1。
ffmpeg -y -framerate 2 -i /frames/batch1/frame_%d.jpg \
       -c:v libx264 -crf 21 -preset veryfast -g 2 \
       -f hls -hls_time 4 -hls_list_size 4 -segment_wrap 4 -segment_list_flags +live video/stream.m3u8
其中/frames/batch1/文件夹包含帧序列(例如 frame_01.jpg、frame_02.jpg 等...)。这似乎已经无法正常工作,因为它不断添加#EXT-X-ENDLIST到.m3u8文件的末尾,据我所知,这对于实时 HLS 流来说是不正确的 - 这是生成的内容:  
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:4.000000,
stream0.ts
#EXTINF:4.000000,
stream1.ts
#EXTINF:2.000000,
stream2.ts
#EXT-X-ENDLIST
我不知道如何在#EXT-X-ENDLIST这里抑制- 这是问题 #1。   
然后,为了生成后续段(例如,当新帧可用时),我正在尝试:
ffmpeg -y -framerate 2 -start_number 20 -i /frames/batch2/frame_%d.jpg \
       -c:v libx264 -crf 21 -preset veryfast -g 2 \
       -f hls -hls_time 4 -hls_list_size 4 -segment_wrap 4 -segment_list_flags +live video/stream.m3u8
不幸的是,这并不像我想要的那样工作。它只是覆盖stream.m3u8、执行和不推进#EXT-X-MEDIA-SEQUENCE,它没有.ts正确索引新文件,并且还包括不需要的#EXT-X-ENDLIST- 这是该命令的输出:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:4.000000,
stream0.ts
#EXTINF:4.000000,
stream1.ts
#EXTINF:3.000000,
stream2.ts
#EXT-X-ENDLIST
从根本上说,我无法弄清楚如何以.m3u8对 HLS 直播流有意义的方式“附加”到现有内容。这本质上是问题 #2。
为了托管流,我使用了一个简单的 Flask 应用程序 - 它似乎按照我的预期工作 - 这是我正在做的参考:
@app.route('/video/<string:file_name>')
def stream(file_name):
    video_dir = './video'
    return send_from_directory(directory=video_dir, filename=file_name)
我正在 Chrome 中尝试 HLS.js - 基本上归结为:
<video id="video1"></video>
...
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script>
   var video = document.getElementById('video1');
   if (Hls.isSupported()) {
     var hls = new Hls();
     hls.loadSource('/video/stream.m3u8');
     hls.attachMedia(video);
     hls.on(Hls.Events.MANIFEST_PARSED, function() {
       video.play();
     });
   }
   else if (video.canPlayType('application/vnd.apple.mpegurl')) {
     video.src = '/video/stream.m3u8';
     video.addEventListener('loadedmetadata', function() {
       video.play();
     });
   }
</script>   
我想认为我想要做的不需要比我上面尝试的更复杂的方法,但是由于我尝试的方法肯定行不通,我开始我想我需要从不同的角度来看待这个问题。关于我缺少什么的任何想法?
我也尝试了相同的(再次在 Chrome 中)video.js,并且我看到了类似的行为 - 特别是,当我手动更新支持stream.m3u8(没有#EXT-X-ENDLIST标签)时,videojs从不接受实时流的新更改,而只是缓冲/无限期挂起。
<video id="video1" class="video-js vjs-default-skin" muted="muted" controls>
    <source type="application/x-mpegURL" src="/video/stream.m3u8">
</video>
...
<script>
    var player = videojs('video1');
    player.play();
</script>
例如,如果我从这个初始版本开始stream.m3u8:
#EXTM3U
#EXT-X-PLAYLIST-TYPE:EVENT
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:8
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:4.000000,
stream0.ts
#EXTINF:4.000000,
stream1.ts
#EXTINF:2.000000,
stream2.ts
然后在服务器端手动更新它:
#EXTM3U
#EXT-X-PLAYLIST-TYPE:EVENT
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:8
#EXT-X-MEDIA-SEQUENCE:3
#EXTINF:4.000000,
stream3.ts
#EXTINF:4.000000,
stream4.ts
#EXTINF:3.000000,
stream5.ts
video.js 控件仅在播放前 3 个片段(stream*.ts 0-2)后无限期地缓冲,这不是我期望发生的(我希望它继续播放 stream*.ts 3 -5 一次stream.m3u8更新并video.js请求播放列表的最新版本)。