使用 FFmpeg 在 iOS 上编写时将 fMP4 转码为 HLS
Posted
技术标签:
【中文标题】使用 FFmpeg 在 iOS 上编写时将 fMP4 转码为 HLS【英文标题】:Transcoding fMP4 to HLS while writing on iOS using FFmpeg 【发布时间】:2016-11-08 16:47:23 【问题描述】:TL;DR
我想将 fMP4 片段转换为 TS 片段(用于 HLS),因为片段是在 ios 设备上使用 FFmpeg 编写的。
为什么?
我正在尝试在 iOS 上实现实时上传,同时在本地保持无缝的高清副本。
我尝试过的
滚动AVAssetWriter
s,每个写入 8 秒,然后通过 FFmpeg 将 MP4 连接在一起。
出了什么问题 - 音频和视频有时会出现中断。我已经确定了 3 个原因。
1) AAC 编码器写入的音频启动帧会产生间隙。
2) 由于视频帧长为 33.33 毫秒,音频帧长为 0.022 毫秒,因此它们可能不会在文件末尾对齐。
3) Mac OS 上缺少帧精确编码,但不适用于 iOS Details Here
FFmpeg 将带有原始音频的大型纯视频 MP4 文件混合到 TS 段中。该作品基于Kickflip SDK
出了什么问题 - 每隔一段时间就会上传一个只有音频的文件,没有任何视频。永远无法在内部重现它,但是当我们的用户没有记录他们认为自己做了什么时,这让他们非常沮丧。最终片段的准确搜索也存在问题,几乎就像 TS 片段的时间戳不正确一样。
我现在在想什么
Apple 在今年(2016 年)的 WWDC 上推出了 fMP4,在此之前我根本没有仔细研究过它。由于可以读取 fMP4 文件并在写入时播放,因此我认为 FFmpeg 也可以在文件写入时对其进行转码,只要我们推迟发送字节到 FFmpeg,直到文件中的每个片段完成。
但是,我对 FFmpeg C API 不够熟悉,我只是在尝试 #2 中短暂使用过它。
我需要你什么
-
这是一个可行的解决方案吗?是否有人对 fMP4 足够熟悉,知道我是否真的可以做到这一点?
我怎么知道
AVFoundation
已在文件中完成了一个片段的写入,以便我可以将其通过管道传输到 FFmpeg?
如何从磁盘上的文件中获取数据,一次分块,将其传递到 FFmpeg 并让它输出 TS 段?
【问题讨论】:
这个问题应该有助于如何提问。写得很好的问题。 我已经放弃了这种方法,转而使用VideoToolbox
(文档记录很差)来转换内存中的帧,而不是使用AVAssetWriter
中间人。代码基于此示例 github.com/twinenginelabs/kickflip-ios-sdk
【参考方案1】:
如果fmp4包含h264+aac,严格来说不需要转码,只需将样本数据重新打包成TS即可。 (使用ffmpeg -codec copy
或gpac)
写。对齐 (1.2) 我想这一切都取决于您的编码器设置(帧速率、采样率和 GOP 大小)。当然可以确保音频和视频在片段边界处完全对齐(例如:this table)。如果您的目标是 iOS,我建议您使用 HLS protocol 版本 3(或 4),以便更准确地表示时间。这还允许您单独流式传输音频和视频(非多路复用)。
我相信 ffmpeg 应该能够推送实时 fmp4 流(即使用长时间运行的 HTTP POST),但播放需要 origin software 来做一些有意义的事情(即流到 HLS)。
【讨论】:
以上是关于使用 FFmpeg 在 iOS 上编写时将 fMP4 转码为 HLS的主要内容,如果未能解决你的问题,请参考以下文章