2012-10-22 136 views
33

我正在从事在线电视服务。其中一个目标是在没有任何其他浏览器插件的情况下播放视频(Flash除外)。通过MP4实时流式传输

我决定使用MP4,因为它受到大多数HTML5浏览器和Flash(用于回退)的支持。视频由FFMpeg从服务器上的ASF转码。

但是,我发现MP4无法实时流式传输,因为它具有用于指定长度的元数据的moov原子。 FFMpeg不能直接将mp4传输到标准输出,因为它将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,所以如果我必须同时支持这两种格式,我必须进行两次转码。

回答

5

这里是我的想法,大家可能会在其他方式的一些方式。我恳求无知,因为没有人真正记录了这个过程,其全部都是有教养的猜测。

AvAssetWriter只对一个文件进行编码,似乎没有办法将编码的视频存储到内存中。在从后台线程写入文件的时候读取文件来表示一个套接字导致基本流,这基本上是一个m4v,它是一个带有h264/acc mdata但没有moov原子的容器。 (换句话说,没有标题) 没有苹果提供的播放器可以播放此流,但基于ffplay的经过修改的播放器应该能够解码和播放流。这应该是有效的,因为ffplay使用可以解码基本流的libavformat,因为没有文件长度信息,有些事情必须由播放,DTS和PTS以及播放器无法在文件内搜索来确定。

或者,可以使用来自m4v流的原始naul来构造rtmp流。

如果您想进一步讨论,可以直接与我联系。

如何获取数据。

因为无论如何你都必须在接收端重建文件,我猜你可能会对它进行细分,Steve Mcfarin在他的github页面上写了一个小小的appleSegmentedEcorder,这可以解决一些问题moov原子,因为你拥有所有的文件信息。

+1

这里有一个很好的解释,开始听起来像rtmp或一些自定义协议的路要走http://fabiensanglard.net/mobile_progressive_playback/index.php –

+0

你的答案有告诫,它已经写在上面。时间就是流媒体和播放的问题。所以-1 – agfe2

2

不,它不仅仅是很长的长度..你需要知道每个帧的确切大小才能在mp4中创建标题。 [这就是为什么它最终由各种编码器创建的原因]。

+0

不能将该信息留空吗?经过一些调整后,我设法创建了一个没有moov原子的m4v文件(基本上是MP4),它在Totem中播放,没有显示关于视频长度的任何信息。 – Ivo

+0

你的m4v是一个包含基本文件还是基本文件的mp4(容器)?没有标题,它不再符合标准。所以无论玩还是不玩取决于玩家的智慧。有些玩家可能会努力工作并尝试修复该文件。但大多数人不会玩它。 – av501

+0

是的,似乎m4v可以只是一个mp4文件或原始h264流。在浏览器中工作的是mp4,而ffmpeg生成的是原始流。 所以看来,它毕竟不能完成。 – Ivo

0

只是看你的问题的第二段(“视频是由ffmpeg在服务器上从ASF转码的。”),你提到你使用ffmpeg在服务器上转码视频。

使用qt-faststart或MP4Box将MOOV原子放置在文件的开头。 (也请确保使用H264 Video & AAC Audio编解码器进行通用支持)

希望这对您有所帮助。

+2

它没有。经过多次谷歌搜索之后,我发现qt-faststart被提及了很多 - 但它不适用于直播,因为流是连续的 - 从开始就无法知道帧/长度,因此无法创建MOOV原子。 qt-faststart将帮助如果我需要伪流(连续下载)。 – Ivo

17

您可以使用分段MP4。支离破碎的MP4文件是建立在如下:然后

moov [moof mdat]+ 

影片包只包含了轨道的基本信息(多少,它们的类型,编解码器的初始化等),但没有对在轨道的样本信息。有关样本位置和样本大小的信息位于moof框中,每个moof框后跟一个包含上述moof框中所述样本的mdat。通常情况下,人们会选择(moof,mdat)对的长度大约为2,4或8秒(没有关于此的规范,但对于大多数使用情况,这些值似乎是合理的)。

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

+0

看看这里:https://groups.google.com/forum/?fromgroups=#!topic/mp4parser-discussion/e7yg6clATHc这家伙似乎有一个非常类似的问题。 –

+3

最终碎片化的mp4就像苹果HTTP实时流媒体并且做得很好。我一开始就忽视了这一点,因为我认为碎片似乎是一个不必要的复杂因素,但现在我发现它是唯一的选择。 – Ivo

+0

@SebastianAnnies然而,这似乎起作用,但(至少)Safari似乎要求每个片段都有一个单独的Range GET请求(从片段开始到EOF,但过早终止),使整个流处理更加麻烦。你有相同的经历吗? –