使用AudioTrack添加2秒播放延迟无效问题求助
问题分析与解决办法
你遇到的问题核心是:虽然代码里做了2秒延迟后才开始写入AudioTrack,但音频还是立即播放,这大概率是因为AudioTrack在延迟前就已经开始播放,并且有数据提前进入了播放缓冲区。
可能的原因:
- 你可能在调用
delayOutput()之前就已经调用了audioTrack.play(),此时AudioTrack处于播放状态,如果之前已经有数据写入(哪怕是在其他逻辑里),就会立即播放。 cachedBuffers中的数据可能在延迟启动前就已经被填充,并且有其他线程在延迟期间已经将数据写入了AudioTrack。WRITE_NON_BLOCKING模式下,只要AudioTrack的内部缓冲区有空闲,写入会立即完成,若AudioTrack已在播放,写入的数据会被马上调度播放。
修正方案:
延迟AudioTrack的启动时机
把audioTrack.play()放在延迟2秒之后,确保播放和数据写入同步延迟:private fun delayOutput() { CoroutineScope(Dispatchers.Default).launch { withContext(Dispatchers.IO) { delay(2000) // 延迟后再启动播放 audioTrack?.play() while (isRecording) { val item = cachedBuffers.firstOrNull() item?.let { buffer -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && buffer is ShortArray) { audioTrack?.write(buffer, 0, buffer.size, WRITE_NON_BLOCKING) } cachedBuffers.removeAt(0) } delay(100) } } } }确保数据只在延迟后才进入播放流程
检查你的缓存填充逻辑,保证cachedBuffers的数据是在delayOutput()启动后才开始填充,或者在延迟期间禁止其他线程操作AudioTrack的写入。如果有其他地方在写入AudioTrack,必须统一到这个延迟后的协程里处理。使用线程安全的缓存容器
把cachedBuffers换成线程安全的队列,比如ConcurrentLinkedQueue,避免多线程操作导致的数据提前写入:private val cachedBuffers = ConcurrentLinkedQueue<ShortArray>()读取和移除操作也对应调整:
val item = cachedBuffers.poll()
额外检查点:
- 确认
isRecording变量是线程安全的(比如用volatile修饰),避免协程逻辑提前退出或异常执行。 - 打印
audioTrack.play()的调用时机,以及缓存数据的填充时间,确认两者都在2秒延迟之后。
内容的提问来源于stack exchange,提问作者jianglei
相关产品推荐
相关产品推荐

