【问题标题】:iOS correct way for update recording time since beginning of the recordingiOS自录制开始以来更新录制时间的正确方法
【发布时间】:2016-11-02 16:17:31
【问题描述】:

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

Mic -> AVCaptureDeviceInput -> AVCaptureSession -> AVCaptureAudioDataOutput

AVCaptureAudioDataOutput 具有将 sampleBuffers 写入输出文件的 Delegate 和 AVAssetWritter。在这个解决方案中,我想更新录制时间。当用户点击记录/暂停/恢复/停止按钮时,我可以记录时间,但是苹果有什么官方方法可以在开始时以 00:00:00 时间更新一些 UILabel。我知道我可以使用 NSTimer,但是当我使用 AVAudioRecorder 时,我有财产:

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

上述属性也适用于暂停/继续按钮。

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

我不明白时钟和方法的全部概念,例如:

CMClockGetHostTimeClock()
CMSyncConvertTime

如何在基于sampleBuffer的AVCaptureAudioDataOutputSampleBufferDelegate方法中获取录音开始的秒数?

更新

我发现了一个名为 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 网站上根本没有关于这个 Core Media 东西的好的教程,只有一些 api 文档。有人知道 WWDC 是否有关于 CoreMedia 框架相关主题的优秀教程/视频?

【问题讨论】:

  • 我之前没用过CMTimebase,但是你应该也可以用它来做你想做的事。只需在开始录制时将其附加到 AVCaptureSession 时钟,并在要更新时间时读取 CMTimebase。不过,您仍然需要一个计时器或触发器“经常”缓冲区来获取显示更新。不幸的是,我不熟悉任何文档,快速谷歌也没有显示任何文档。祝你好运!

标签: ios iphone avfoundation avcapturesession avassetwriter


【解决方案1】:

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

这是“时钟”https://developer.apple.com/reference/coremedia/cmclock

时钟代表时间信息的来源:通常是测量时间流逝的硬件。

它非常准确,这才是重点。它是只读的,你只能从中获取参考,你不能设置它。各种事情都可能发生在缓冲区上,它们被排队,它们可以通过网络转发,但是如果你有那个 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 个样本左右更新一次(或任何适用于您正在使用的音频频率的方法)。还要确保将其卸载到单独的线程。

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

【讨论】:

  • 很好很好的回答,信息量很大。我会尝试在操场上玩这个。我知道当我只有 60fps 的显示速度时,尝试每秒更新 UILabel 44100 次(使用音频采样率频率)是没有意义的。我明天会谈到这个。非常感谢!
  • 很高兴这很有用,一旦你测试了它并且你很高兴,请随时接受并投票给答案。
  • Tim 你可以看看我对问题的更新并查看我的发现。也许你知道一些关于 CoreMedia 框架的好教程/资料?
  • 各位好心人知道是否可以使用这种技术将视频与捕获会话同步?所以说我想录制一个视频,在另一个视频播放的顶部,我想将结果同步在一起,这样它们的时间就完全正确了。我可以使用这些主时钟这样做吗?多年来,我一直在寻找一种准确的方式来同步两个这样的视频!谢谢
  • 如果我想说“记录在这个时刻开始”,我如何获得绝对系统时间?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-01
  • 2013-10-21
  • 1970-01-01
  • 1970-01-01
  • 2017-02-07
  • 1970-01-01
相关资源
最近更新 更多