AVAudioRecorder currentTime 给出错误值
Posted
技术标签:
【中文标题】AVAudioRecorder currentTime 给出错误值【英文标题】:AVAudioRecorder currentTime giving bad values 【发布时间】:2017-04-11 16:50:23 【问题描述】:我有如下设置,在装有 ios 10.3 的 iPhone 5s 上进行测试,包括调试内外。
AVAudioRecorder
触发 record(forDuration: 5.0)
CADisplayLink
监视记录器的级别(记录器是 meteringEnabled
),同步动画,并跟踪 recorder.currentTime
(但可以通过在显示链接中最小限度地跟踪时间来重现问题)
recorder.currentTime
的报告始终达到 > 5 的值(通常为 5.2 到 5.5)。结果与recorder.deviceTime
和CFAbsoluteTimeGetCurrent
的值基本一致
我初始化了一个AVAudioPlayer
并验证了声音资产的持续时间是否正好为 5.0 秒。
据我了解,录音机的currentTime
以秒为单位,当recorder.isRecording 恢复为false 时会重置为0.0,这会在录音机停止时立即发生(这与我在audioRecorderDidFinishRecording
中看到的一致)。 .. 所以用CADisplayLink
观察应该产生的 currentTime 值严格小于 5.0?
问题是:这里可能出了什么问题?记录器在 5 秒后按原样停止,但在内部它认为它记录了超过 5 秒?我正在听我所有的录音,它们听起来不错。
我不确定它是否相关,但我的AVAudioSession
是AVAudioSessionCategoryPlayAndRecord
类型,我的音频设置如下(除采样率之外的所有这些都是以后分析所必需的):
audioSettings = [
AVFormatIDKey: Int(kAudioFormatLinearPCM),
AVSampleRateKey: 44100,
AVNumberOfChannelsKey: 2,
AVLinearPCMIsBigEndianKey: 0,
AVLinearPCMIsFloatKey: 0,
AVLinearPCMBitDepthKey: 16,
AVLinearPCMIsNonInterleaved: 0
]
我已经尝试摆弄所有这些,但没有看到任何更改行为。
CADisplayLink
是通过主线程添加的
recorderDisplayLink?.add(to: RunLoop.current, forMode: RunLoopMode.commonModes)
我可以在堆栈交换中找到的唯一类似问题是 this,但该问题未详细说明,答案也无济于事(至少对我而言)。 起初我认为问题可能在于主队列超载,因此记录器的时间感不知何故变得臃肿(我认为 仍然会构成不良行为),但是在禁用动画后(并且还尝试使用 Timer 而不是 CADisplayLink),问题仍然存在!!!也许它仍然是一个线程问题,但我不明白为什么会这样。如果我确实需要多线程,我可以在理解和实现方面使用一些帮助:) 任何想法表示赞赏。
【问题讨论】:
那么问题来了,为什么您比recordForDuration:
请求的持续时间多出 0.2 到 0.5 秒?
问题是,以下两个语句如何同时兼容: (1) record(forDuration: 5.0) 产生正好 5.0 秒的有效记录 (2) 观察记录器的 currentTime 属性的计时器在行动报告值显着 > 5.0
TL;DR AVAudioRecorder
不是很好,更换它。请参阅我的答案以获得更细致入微的版本。
您不能拥有装有 iOS 10.3 的 iphone 4,此设备上最后支持的版本是 iOS 7.1.2。即使您的意思是 4s 仍然会将最高版本设置为 iOS 9.3.5
哈哈谢谢!你是对的。更正了问题。
【参考方案1】:
在我使用AVAudioRecorder
的所有时间中,我最终不得不更换它。 AVAudioRecorder
是一个通用的录音类,所以一旦你的要求变得有点专业,它会让你失望。
但是,它确实可以计量,这也是吸引很多人的原因。所以也许情况可以挽救。
可能性:
一个。如果currentTime
不可信,请不要观察!您已经获得了 5 秒的文件,因此也许可以找到其他方式在您的应用中标记该时间的流逝。
b.属性currentTime
,头文件说:
only valid while recording
您是否仅在录制时对currentTime
进行采样?如果是这样,那可能就是问题所在。在这种情况下,您可以使用始终有效的deviceCurrentTime
属性,尽管您必须减去初始的deviceCurrentTime
。
如果情况无法挽救,您可以很快将AVAudioRecorder
替换为AVAudioEngine
和AVAudioFile
,但这是另一天的问题。
【讨论】:
是的,我正在考虑更换它,但如果可能的话,我不想这样做......吸引我的是计量。基本上,我正在观察记录器的平均功率来提供动画和测量静音。这是我需要currentTime
属性的第二部分。但我需要这些时间与AVAudioPlayer
和AVReader
对时间的感知保持一致。
哦,我还要澄清一下:当isRecording
为真时,我只报告currentTime
的值。这意味着当currentTime
超过实际音频持续时间时,录音机仍在录音,或者isRecording
实际上并未指示录音机正在做什么。但也许标题说明了一切。 "Only valid while recording (but don't bet on it)
"
我确实尝试使用记录器的deviceCurrentTime
属性,但发现它的行为同样奇怪。也许我应该在记录器之外使用不同的设备时间度量?
是的,其他一些标记时间的方式不是AVAudioRecorder
。
实际上我尝试用CFAbsoluteTimeGetCurrent
标记时间,我也看到了同样的问题。 isRecording
标志读取为 true 的系统时间量确实比 duration
长【参考方案2】:
我在 Timer 上更新 UILabel 时遇到了同样的问题,但能够通过检查计时器触发器之间的间隙是否太大并将增量记忆为 currentRecordTimeOffset 来解决该问题。
if ( self.recorder.recording )
float adjustedRecordTime = self.recorder.currentTime;
if(self.currentRecordTimeOffset == 0)
if(self.recorder.currentTime - self.lastRecordedTime > 1.0) // current time should be updated every 0.1 so a 1 Sec delta indicates offset needed
self.currentRecordTimeOffset = self.recorder.currentTime;
adjustedRecordTime = self.recorder.currentTime - self.currentRecordTimeOffset;
else
adjustedRecordTime = self.recorder.currentTime - self.currentRecordTimeOffset; // get rid of the unusual offset
self.lastRecordedTime = self.recorder.currentTime;
self.durationLabel.text = [NSString stringWithFormat:@"%.2f", adjustedRecordTime];
【讨论】:
以上是关于AVAudioRecorder currentTime 给出错误值的主要内容,如果未能解决你的问题,请参考以下文章