通过MP4进行直播流传输

37

我正在开发一个在线电视服务。其中一个目标是视频可以在没有任何浏览器插件的情况下播放(除了Flash)。

我决定使用MP4,因为它受到大多数HTML5浏览器和Flash(备选方案)的支持。视频是由服务器上的FFMpeg从ASF转码而来。

然而,我发现MP4不能进行实时流传输,因为它具有用于指定长度的元数据moov原子。 FFMpeg无法直接将mp4流式传输给stdout,因为它将moov放置在文件末尾。(Live transcoding and streaming of MP4 works in Android but fails in Flash player with NetStream.Play.FileStructureInvalid error

当然,MPEG-TS存在,但HTML5<video>不支持它。

我的想法是实时转码流至MP4,并在每次对其进行新的HTTP请求时,先发送一个指定视频长度非常长的moov,然后开始发送MP4文件的其余部分。

能否以这种方式使用MP4进行流传输?经过一些研究和av501的回答,我理解必须知道帧的大小才能使其正常工作。

MP4文件是否可以分段为较小的部分以进行流传输?当然,切换到另一个容器/格式是一种选择,但唯一与Flash和HTML5兼容的格式是mp4 / h264,因此如果我必须支持两者,则必须进行两次转码。

4个回答

23

您可以使用分段MP4。 分段MP4文件的构建如下:

moov [moof mdat]+

moov box仅包含有关音轨的基本信息(数量、类型、编解码器初始化等),但不包含有关音轨中样本的信息。样本位置和样本大小的信息在moof box中,每个moof box后面都跟着一个mdat,其中包含如前面moof box所述的样本。通常情况下,(moof, mdat)对的长度选择为大约2、4或8秒(没有规定,但这些值似乎对于大多数用例来说是合理的)。

这是构建永无止境的MP4流的一种方法。


看这里:https://groups.google.com/forum/?fromgroups=#!topic/mp4parser-discussion/e7yg6clATHc 这个人似乎有非常相似的问题。 - Sebastian Annies
4
最终分段的mp4就像苹果的HTTP直播流一样,表现得很好。起初我忽略了它,因为我认为分段似乎是一种不必要的复杂化,但现在我看到它是唯一的选择。 - Ivo
@SebastianAnnies 这似乎可以工作,但是(至少)Safari似乎会使用单独的Range GET请求请求每个片段(从片段开始到EOF,但会过早终止),使得整个流处理变得更加麻烦。你有同样的经验吗? - Jaka Jančar

4
这是我的想法,可能有些正确,其他的可能完全错误。我很抱歉因为没有人真正完整记录这个过程,所以我对此一无所知。
AvAssetWriter只能将视频编码到文件中,似乎没有办法将编码后的视频保存在内存中。在后台线程写入文件的同时从文件中读取数据,会得到一个基本流,其实就是一个m4v容器,其中含有h264/acc元数据,但没有moov原子(换句话说,没有头)。 Apple提供的播放器都无法播放这种流,但基于ffplay的修改播放器应该可以解码和播放这种流。这应该可行,因为ffplay使用libavformat可以解码基本流,但有一个限制:由于没有文件长度信息,播放器必须确定DTS和PTS,而且无法在文件中进行跳转。
或者可以使用m4v流中的原始纳尔数据构建一个RTMP流。
如果您想进一步讨论,请直接联系我。
如何获取数据。
由于在接收端必须重新构建文件,我认为您可以将其轻微分割。 Steve Mcfarin 在他的GitHub页面上写了一个小的appleSegmentedEcorder,这解决了 moov 原子的一些问题,因为您拥有所有文件信息。

1
这里有一个很好的解释,开始听起来像是使用RTMP或一些自定义协议才是正确的方法:http://fabiensanglard.net/mobile_progressive_playback/index.php - Michelle Cannon
你的回答有一个限制,它已经在上面写明了。时间对于流媒体和播放非常重要。所以-1。 - agfe2

2
不,这不仅仅是长度很长的问题...你需要知道每个帧的确切大小,才能创建mp4中的头文件。[这也是为什么它会在各种编码器最后被创建的原因]。

那些信息不能留空吗?经过一些调整,我成功创建了一个没有moov原子的m4v文件(基本上就是MP4),并且在Totem中播放时,没有显示任何有关视频长度的信息。 - Ivo
你的m4v文件是包含基本文件的mp4(容器)还是只有基本文件?没有头文件,它就不再符合标准。因此,它能否播放取决于播放器的智能程度。一些播放器可能会努力尝试修复文件。但大多数播放器都无法播放它。 - av501
是的,看起来m4v文件既可以是mp4文件,也可以是原始的h264流。在浏览器中工作的那些是mp4格式,而由ffmpeg生成的那个则是原始流。所以看来这是不可能完成的。 - Ivo

0

仅看您问题的第二段(“视频是在服务器上通过ffmpeg从ASF转码而来。”),您提到正在使用ffmpeg在服务器上转码视频。

请使用qt-faststart或MP4Box将MOOV原子放置在文件开头。(同时确保使用H264视频和AAC音频编解码器以获得通用支持)

希望这可以帮助您。


2
它不行。经过多次谷歌搜索,我发现qt-faststart被频繁提到 - 但是对于直播流来说它不起作用,因为流是连续的 - 帧/长度无法从一开始就知道,因此无法创建MOOV原子。 如果我需要的是伪流式传输(连续下载),那么qt-faststart会有所帮助。 - Ivo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接