【问题标题】:HTML5 H264 video sometimes not displayingHTML5 H264 视频有时不显示
【发布时间】:2020-02-07 18:15:25
【问题描述】:

鉴于这个来自 RTSP 摄像机的流,它产生 H264 流:

Input #0, rtsp, from 'rtsp://admin:admin@192.168.0.15:554':
  Metadata:
    title           : LIVE555 Streaming Media v2017.10.28
    comment         : LIVE555 Streaming Media v2017.10.28
  Duration: N/A, start: 0.881956, bitrate: N/A
    Stream #0:0: Video: h264 (Main), yuv420p(progressive), 1600x900, 25 fps, 25 tbr, 90k tbn, 50 tbc

我想运行 ffmpeg 并将其输出通过 MSE 管道传输到 HTML5 视频组件。

只要我运行这个 ffmpeg 命令,一切都很好(管道被移除了!):

$ ffmpeg -i 'rtsp://admin:admin@192.168.0.15:554' -c:v copy -an -movflags frag_keyframe+empty_moov -f mp4

不过一开始需要一点时间。

我意识到avformat_find_stream_info 函数会在我的系统上造成大约 15-20 秒的延迟。 Here 是文档。

现在我也意识到,如果我添加-probesize 32,avformat_find_stream_info 几乎会立即返回,但会引起一些警告:

$ ffmpeg -probesize 32 -i 'rtsp://admin:admin@192.168.0.15:554' -c:v copy -an -movflags frag_keyframe+empty_moov -f mp4

[rtsp @ 0x1b2b300] Stream #0: not enough frames to estimate rate; consider increasing probesize
[rtsp @ 0x1b2b300] decoding for stream 0 failed
Input #0, rtsp, from 'rtsp://admin:admin@192.168.0.15:554':
  Metadata:
    title           : LIVE555 Streaming Media v2017.10.28
    comment         : LIVE555 Streaming Media v2017.10.28
  Duration: N/A, start: 0.000000, bitrate: N/A
    Stream #0:0: Video: h264 (Main), yuv420p(progressive), 1600x900, 25 tbr, 90k tbn, 50 tbc

如果我将此流转储(到文件 test.mp4 中),所有媒体播放器都可以完美播放。

但是,如果我使用 MSE 将此输出通过管道传输到 HTML5 视频中,则流有时会正确显示,有时却不能正确显示。 浏览器的控制台上不会打印任何警告或错误消息。

从第二个输出我可以看到 fps 丢失。我尝试手动设置,但没有成功(似乎无法手动更改)。

如果我事先知道流的所有内容,如何避免使用 avformat_find_stream_info 并播放 HTML5 MSE?

更新

根据@szatmary 的 cmets 和答案,我已经搜索了一个 h264 比特流解析器。

This 是我找到的。我还保存了 HTML5 视频无法播放的 mp4 文件,但 VLC 可以播放,然后我进入了这个分析器。

这是我的分析截图:

这里有一些事实:

  • 在 #66 之前,流中没有 type7 (SPS) 单元。
  • 62 是第一个 SPS 到达之前的最后一个 PPS。
  • 在 62 岁之前就有很多 PPS。
  • 比特流在 #103 结束。
  • 在 VLC 中播放流时长为 20 秒。

我有几件事要澄清:

  1. #62 和 #66 sps/pps 单元(或其他单元)只为接下来的帧保存元数据,或者它们甚至可以引用以前的帧?
  2. VLC 播放 20 秒,是否可以先扫描整个文件,然后根据 #62 和 #66 信息播放 #1 的帧? - 如果 VLC 将文件作为流获取,在这种情况下它可能只播放几秒钟 (#66 - #103)。
  3. 最重要的是:我应该如何使用比特流解析器来制作 HTML5 视频播放这些数据? #62 之前的所有单位要我放弃吗?还是在 #66 之前?

现在我真的迷失在这个话题上了。我用 FFMPEG 创建了一个视频,但这次我让它完成了它的 avformat_find_stream_info 函数。

使用与以前相同的方法保存视频。 VLC 现在播放 18 秒(这没关系,我在 ffmpeg 命令中有 1000 帧限制)。

不过现在让我们看看比特流信息:

现在 PPS 和 SPS 分别为 130 和 133。这导致流比以前短 2 秒。 (我猜)

现在我了解到,在正确解析的 h264 中,在第一个 SPS(/PPS) 之前仍然可以有很多单元。

所以我会微调我上面的问题:我应该如何使用比特流解析器来制作 HTML5 视频来播放这些数据?

我发现的比特流解析器也不好,因为它使用二进制包装器 => 它不能纯粹在客户端运行。

我现在在看mp4box

【问题讨论】:

    标签: ffmpeg html5-video media-source


    【解决方案1】:

    如果我事先知道流的所有内容,如何避免使用 avformat_find_stream_info 并播放 HTML5 MSE?

    您事先并不了解流的所有内容。您不知道分辨率、比特率、级别或配置文件或约束标志。你不知道缩放列表值,你不知道 VUI 数据,你不知道是否使用了 CABAC。

    播放器需要所有这些东西来播放视频,直到播放器或 ffmpeg 看到流中的第一个 sps/pps 才知道它们。通过限制分析持续时间,您告诉 ffmpeg 放弃寻找它,因此不能保证产生有效的流。它有时可能有效,有时可能无效,这在很大程度上取决于您从 rstp 流中的哪个帧开始。

    如果可以的话,一个可能的解决方案是向源视频添加更多关键帧,这将更频繁地发送 sps/pps。如果您不控制源流,则必须等到流中出现 sps/pps。

    【讨论】:

    • 感谢您的回复。流是用 live555 创建的,我可以重新配置它以发送更多关键帧。但是,如果我这样做,我会失去这个特定流的一些有价值的性能,因此该解决方案将无法使用我无法控制的流。有一件事让我很感兴趣:即使我使用带有分析持续时间的 ffmpeg,它产生的流仍然可以播放,比如在 VLC 中但不能在 html5 视频中播放。
    • 你写道:“播放器需要所有这些东西来播放视频,直到播放器......看到流中的第一个 sps/pps 才知道它们。”我可以往那个方向走吗?让我们将其留在播放器中以查找 sps/pps。你觉得呢?
    • 我在想 Broadway.js:github.com/mbebenita/Broadway。它是一个纯 js h264 解码器。显然不如原生 html5 视频有效,但由于它是开源的,我可以对其进行调整以帮助 html5 视频找到那些必要的 sps/pps。这有意义吗?
    • 在浏览器中等待 SPS/pps 不会使其更快。这将花费相同的时间。您也不需要完整的解码器,只需一个比特流解析器。
    • szatmary:我的首要任务是从服务器上卸载这个任务。服务器很慢,因此在调用 avformat_find_stream_info 时,它会消耗 20-30 秒的所有 cpu 资源。使用 med-power i7 服务器的相同流在 1 秒内完成,我什至看不到 cpu 使用情况。但是在这 20-30 秒内,流不断地推送数据,所以它也会弄乱我稍后需要更正的 sps/pps。在 i7 上,sps/pps 很好,没有搞砸。综上所述,最后我认为如果只有浏览器会等待 sps/pps,它可能会更快。
    猜你喜欢
    • 1970-01-01
    • 2015-03-26
    • 2015-08-27
    • 1970-01-01
    • 2023-03-05
    • 2011-03-12
    • 1970-01-01
    • 1970-01-01
    • 2014-04-27
    相关资源
    最近更新 更多