我正在设计一个服务器应用程序,它将实时 H.264 视频流存储为 MP4 供浏览器以后使用。由于服务器需要处理尽可能多的同时流,我相信 I/O 将成为自然的瓶颈,我希望将 I/O 保持在最低限度。我遇到了经典的 MP4 moov/mdat 排序问题:MP4 生成器更喜欢先写 mdat 框(包含实际的媒体帧),然后再写 moov 框(包含文件偏移量和其他结构信息),在它实际之后知道 mdat 文件的偏移量是多少。MP4 消费者喜欢相反的渐进式流媒体——首先读取 moov 框,因此 mdat 结构是已知的,视频可以快速开始播放,而无需下载整个文件。
通常的解决方案是对 MP4 文件进行后处理以将 moov 框移动到 mdat 框之前,并相应地重写文件偏移量。但是,对于大容量应用程序,我想避免将传入的视频数据写入磁盘、将其全部读回并以新的安排再次写入的 I/O 损失。
想到了几种方法:
- 像往常一样对 MP4 进行后处理,这会导致 I/O 损失并可能会延迟视频的可用性。(不好。)
- 使用分段 MP4 和适合内存的小片段大小。(我认为这可能会对整个文件的可搜索性产生负面影响。)
- 如果文件系统提供了一个快速的“前置”选项来将新块添加到文件块链的开头,那就太棒了。(我认为这还没有被发明出来。)
- 将 MP4 生成为两个文件——一个“mdat”文件(包含实际的媒体帧)和一个“moov”文件(包含 ftyp 标头和 moov 数据)。如果将这两个文件连接起来,将产生一个有效的 moov-first MP4 文件。一个简单的 Web 服务器模块可以向用户呈现一个虚拟的 .mp4 文件,但在后台读取 .moov 和 .mdat 文件。
我现在倾向于#4。有没有更实用的方法来解决这个问题?