36

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

我决定使用 MP4,因为大多数 HTML5 浏览器和 Flash(作为后备)都支持它。这些视频由 FFMpeg 在服务器上从 ASF 转码。

但是,我发现 MP4 不能实时流式传输,因为它有一个 moov atom 用于必须指定长度的元数据。FFMpeg 不能直接将 mp4 流式传输到标准输出,因为它将 moov 放在文件末尾。(MP4 的实时转码和流式传输在 Android 中有效,但在 Flash 播放器中失败并出现 NetStream.Play.FileStructureInvalid 错误

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

我想到的是一种将流实时转码为 MP4 的方法,并且在每个新的 HTTP 请求上,首先发送一个 moov 指定一个非常长的视频长度数字,然后开始发送其余的MP4 文件。

是否可以以这种方式使用 MP4 进行流式传输?

经过一些研究和av501的回答,我明白必须知道框架的大小才能工作。

可以将 mp4 文件分割成更小的部分以便进行流式传输吗?

当然,切换到另一种容器/格式是一种选择,但与 Flash 和 HTML5 兼容的唯一格式是 mp4/h264,所以如果我必须同时支持两者,我必须转码两次。

4

4 回答 4

21

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

moov [moof mdat]+

然后 moov 框仅包含有关轨道的基本信息(有多少、它们的类型、编解码器初始化等),但不包含有关轨道中样本的信息。关于样本位置和样本大小的信息在 moof 框中,每个 moof 框后面都有一个 mdat,其中包含前面 moof 框中所述的样本。通常人们会选择 (moof, mdat)-pair 的长度在 2,4 或 8 秒左右(没有关于此的规范,但这些值对于大多数用例来说似乎是合理的)。

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

于 2013-01-28T08:37:18.620 回答
4

这是我的想法,伙计们,其中一些可能在其他人的路上是正确的。我恳求无知,因为没有人真正完整地记录了这个过程,这都是有根据的猜测。

AvAssetWriter 仅编码为文件,似乎没有办法将编码的视频存储到内存中。在从后台线程写入文件时读取文件以说套接字会产生一个基本流,这本质上是一个 m4v,它是一个带有 h264/acc mdata 的容器,但没有 moov 原子。(换句话说,没有标题)没有苹果提供的播放器可以播放此流,但基于 ffplay 的修改后的播放器应该能够解码和播放流。这应该可行,因为 ffplay 使用可以解码基本流的 libavformat,一个警告,因为没有文件长度信息,有些事情必须由播放、DTS 和 PTS 确定,而且播放器也无法在文件中查找。

或者,m4v 流中的原始 naul 可用于构建 rtmp 流。

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

你如何获得数据。

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

于 2012-12-10T19:42:56.390 回答
2

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

于 2012-10-23T09:11:14.970 回答
0

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

使用 qt-faststart 或 MP4Box 将 MOOV atom 放在文件的开头。(您还要确保使用 H264 视频和 AAC 音频编解码器来获得普遍支持)

希望这对您有所帮助。

于 2013-01-02T11:00:00.463 回答