17

我正在尝试开发一个 iPhone 应用程序,该应用程序将使用相机仅记录最后几分钟/秒。例如,您录制了 5 分钟的电影,点击“保存”,只会保存最后 30 秒。我不想实际录制五分钟,然后砍掉最后 30 秒(这对我不起作用)。这个想法被称为“循环录音”

这会导致无休止的视频录制,但您只记得最后一部分。Precorder 应用程序做我想做的事。(我想在其他情况下使用此功能)我认为这应该很容易用Circular buffer模拟。我用 AVFoundation 开始了一个项目。如果我能以某种方式将视频数据重定向到循环缓冲区(我将实现),那就太棒了。我仅找到有关如何将其写入文件的信息。

我知道我可以将视频分割成间隔并保存它们,但是保存它并重新启动相机以录制另一部分需要时间,并且可能会丢失电影中的一些重要时刻。

任何如何从相机重定向数据的线索将不胜感激。

4

1 回答 1

10

重要的! 从 iOS 8 开始,您可以使用 VTCompressionSession 并直接访问 NAL 单元,而不必挖掘容器。


幸运的是你可以做到这一点,我会告诉你怎么做,但你将不得不用 MP4 或 MOV 容器弄脏你的手。一个有用的资源(虽然,更特定于 MOV)是 Apple 的 Quicktime 文件格式介绍手册 http://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFPreface/qtffPreface.html#//apple_ref /doc/uid/TP40000939-CH202-TPXREF101

首先,您将无法在录制结束前 30 秒从任意点开始保存的电影,您必须在大约 30 秒时使用一些 I-Frame。根据您的关键帧间隔,它可能在 30 秒标记之前或之后几秒钟。您可以使用所有 I 帧并从任意点开始,但之后您可能需要重新编码视频,因为它会非常大。

所以知道这一点,让我们继续前进。

第一步是设置 AVAssetWriter 时,您需要将其 AVAssetWriterInput 的 expectsMediaDataInRealTime 属性设置为 YES。

在 captureOutput 回调中,您将能够从您正在写入的文件中执行 fread。第一个 fread 将为您提供一点 MP4/MOV(无论您使用什么格式)标题(即“ftyp”原子、“wide”原子和“mdat”原子的开头)。您想要“mdat”部分中的内容。因此,您将开始保存数据的偏移量将是 36 左右。

每次读取都会获得 0 个或更多 AVC NAL 单元。您可以从 ISO/IEC 14496-10 表 7-1 中找到 NAL 单元类型列表。它们的格式与附件 B 中指定的格式略有不同,但没关系。此外,MP4/MOV 文件中只有 IDR 切片和非 IDR 切片。IDR 将是您想要使用的 I-Frame。

MP4/MOV容器中的NAL单元格式如下:

4 bytes - Size
[Size] bytes - NALU Data
data[0] & 0x1F - NALU Type

所以现在你有了你正在寻找的数据。当你去保存这个文件时,你必须用正确的长度、样本数更新 MPV/MOV 容器,你必须用每个样本的正确大小更新“stsz”原子,以及更新具有正确电影持续时间的媒体标题和轨道标题等。我可能会建议做的是在第一次运行时创建一个示例容器,您可以或多或少地使用该特定电影的适当数据覆盖/增强它。您需要这样做,因为各种 iDevice 上的编码器并不都具有相同的设置,并且“avcC”原子包含编码器信息。

在这种情况下,您实际上并不需要对 AVC 流有太多了解,因此您可能希望将您的试验集中在更新您正确选择的容器格式上。祝你好运。

于 2012-08-05T18:22:26.117 回答