如何使用 ffmpeg 对批量传入的单个帧进行 HLS 直播,实时“附加”到 m3u8 播放列表?

问题描述 投票:0回答:1

我的总体目标:

服务器端:

  • 我不时收到一批连续的 JPEG 编码帧 (8-16),以大约 2 FPS 生成。
  • 我想托管一个 HLS 直播流,当一批新帧到达时,我将这些新帧编码为带有
    .ts
    的 h264
    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

从根本上讲,我不知道如何以对 HLS 直播有意义的方式“附加”到现有的

.m3u8
。这本质上是问题#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>   

我想我正在尝试做的事情并不需要比我上面尝试的更复杂的方法,但由于我正在尝试的方法肯定行不通,所以我开始我认为我需要从不同的角度来看待这个问题。对我缺少的东西有什么想法吗?

编辑:

我也尝试过使用

video.js
进行相同的操作(再次在 Chrome 中),并且看到类似的行为 - 特别是当我手动更新支持
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
请求最新版本的播放列表)。

ffmpeg video-streaming http-live-streaming video.js hls.js
1个回答
0
投票

关于你的问题#1:你在hls_flags中使用omit_endlist,这样它就不会将end_list放在列表的末尾,从而使传输连续。但是,我建议将它与 independent_segments 一起使用,因为从你所说的来看,框架似乎是断开连接的。如果没有,您可以直接不使用它。

关于你的问题#2你在hls_flags中使用append_list,它总是将帧添加到列表中,而不会丢失前一个列表中的信息。

另外:如果你想使用删除不属于列表的段的问题,可以将hls_flags中的delete_segments与hls_delete_threshold一起使用。

如何表达的一个例子是这样的:

    -segment_list_type hls \
    -segment_list_flags +live \
    -hls_flags delete_segments+append_list+omit_endlist \
    -hls_delete_threshold 5 \
    -hls_list_size 10 \
    -hls_time 6 \

有关更多信息,请参阅更详细地解释 ffmpge 中 hls 实现的部分:https://ffmpeg.org/ffmpeg-formats.html#hls-2

© www.soinside.com 2019 - 2024. All rights reserved.