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

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

Mic -> AVCaptureDeviceInput -> AVCaptureSession -> AVCaptureAudioDataOutput

AVCaptureAudioDataOutput具有Delegate和AVAssetWritter,它将sampleBuffers写入输出文件.在这个解决方案中,我想更新录制时间.我可以记录用户点击录制/暂停/恢复/停止按钮的时间,但有没有官方的方式从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

如何在基于sampleBuffer的AVCaptureAudioDataOutputSampleBufferDelegate方法中获取自录制开始以来的秒数?

UPDATE

我发现了一个名为CMTimebase的类,我认为这是我正在寻找的.目前我不知道如何使用它,但我在游乐场进行一些实验后发现了.

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连接到这个对象.不幸的是,在Apple网站上的一些api文档中没有关于这个Core Media的好教程.有没有人知道WWDC是否有与CoreMedia Framework相关主题的优秀教程/视频?

最佳答案 当您处理AVCaptureAudioOutput时,您现在正在使用Sample Buffers.无论是视频还是音频,您都需要两条关键信息,样本数据和记录样本数据的时间.

这是“时钟”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时钟并捕获startTime.

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

只是确保你没有更新每个样本缓冲区上的UI,这太频繁了,所以也许每隔14,000个样本(或任何适用于您正在使用的音频)都可以这样做.还要确保将其卸载到单独的线程中.

希望这有助于并解释一下时钟.祝好运!

点赞