iOS 从录制开始更新录制时间的正确方法

iOS correct way for update recording time since beginning of the recording

如何在 AVFoundation 中使用此捕获管道在录制期间更新时间标签:

Mic -> AVCaptureDeviceInput -> AVCaptureSession -> AVCaptureAudioDataOutput

AVCaptureAudioDataOutput 具有将 sampleBuffers 写入输出文件的 Delegate 和 AVAssetWritter。在此解决方案中,我想更新录制时间。我可以记录用户点击 Record/Pause/Resume/Stop 按钮的时间,但是 Apple 是否有任何官方方式如何在开始时用 00:00:00 时间更新一些 UILabel。我知道我可以使用 NSTimer 但是当我使用 AVAudioRecorder 时我有 属性:

var currentTime: TimeInterval
// The time, in seconds, since the beginning of the recording.

上面的 属性 也适用于 pause/continue 按钮。

现在在这个新管道中我没有这个 属性 我想知道我是否遗漏了一些东西并且无法在任何地方找到它。我还注意到 AVCaptureSession 有一个名为 masterClock 的 CMClock 属性,但我不确定如何使用它来计算时间,从录制开始。

我不太了解时钟和方法,例如:

CMClockGetHostTimeClock()
CMSyncConvertTime

AVCaptureAudioDataOutputSampleBufferDelegate方法中如何根据sampleBuffer获取开始录音后的秒数?

更新

我发现了一个名为 CMTimebase 的 class,我认为这正是我要找的东西。目前我不知道如何使用它,但我在操场上做了一些实验后发现了什么。

import CoreMedia

let masterClock = CMClockGetHostTimeClock() // This masterclock should be from captureSession
var timebase: CMTimebase? = nil
CMTimebaseCreateWithMasterClock(kCFAllocatorDefault, masterClock, &timebase)

print(CMTimeGetSeconds(CMTimebaseGetTime(timebase!)))

CMTimebaseSetRate(timebase!, 1.0) // Start/Resume recording

sleep(1)
print(CMTimeGetSeconds(CMTimebaseGetTime(timebase!)))

sleep(1)
CMTimebaseSetRate(timebase!, 0.0) // Pause Recording
print(CMTimeGetSeconds(CMTimebaseGetTime(timebase!)))


sleep(1)
print(CMTimeGetSeconds(CMTimebaseGetTime(timebase!)))

所以这个对象真的很有用。当我将速率设置为 1.0 时,它开始与 masterClock 同步测量时间。当我将速率设置为 0.0 时,它会停止测量时间。我还注意到我可以将 Timer 附加到这个对象。不幸的是,根本没有关于这个 Core Media 东西的好教程,只有一些 api 苹果网站上的文档。有人知道 WWDC 是否有关于 CoreMedia Framework 相关主题的好文章 tutorial/video 吗?

当您处理 AVCaptureAudioOutput 时,您现在正在处理样本缓冲区。无论是视频还是音频,您都需要两个关键信息,样本数据和样本数据的记录时间。

这是"Clock"https://developer.apple.com/reference/coremedia/cmclock

A clock represents a source of time information: generally, a piece of hardware that measures the passage of time.

它非常准确,这才是重点。它是只读的,你只能从中获取一个引用而不能设置它。缓冲区可能会发生各种各样的事情,它们会排队,它们可以通过网络转发,但如果您有 CMTime 参考,它们可以重建为正确的顺序和正确的时间。

CMSync 是处理时钟漂移(在两个不同时钟之间报告略有不同的值)的函数子集。这些你完全不用担心。

其实做自己想做的事很简单。这是您可以剪切并粘贴到游乐场中的示例。

import AVFoundation

let masterClock : CMClock = CMClockGetHostTimeClock()
let startTime : CMTime = CMClockGetTime(masterClock)
sleep(1)
let endTime : CMTime = CMClockGetTime(masterClock)
let difference : CMTime = CMTimeSubtract(endTime, startTime)
let seconds = CMTimeGetSeconds(difference)

那应该给你一个略大于 1 的秒值。

当您单击应用程序中的记录按钮时,获取 AVCaptureSession 时钟并捕获开始时间。

当你想更新 UI 时,只需再次检查 AVCaptureSession 时钟,减去两个 CMTime 并转换为秒。

只要确保你没有在每个样本缓冲区上更新 UI ,那太频繁了,所以也许每 14,000 个样本左右才更新一次(或者任何适用于音频的东西)你正在使用)。还要确保将其卸载到单独的线程。

希望这对时钟有所帮助并能对其有所解释。祝你好运!