You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用AudioTrack添加2秒播放延迟无效问题求助

问题分析与解决办法

你遇到的问题核心是:虽然代码里做了2秒延迟后才开始写入AudioTrack,但音频还是立即播放,这大概率是因为AudioTrack在延迟前就已经开始播放,并且有数据提前进入了播放缓冲区。

可能的原因:

  • 你可能在调用delayOutput()之前就已经调用了audioTrack.play(),此时AudioTrack处于播放状态,如果之前已经有数据写入(哪怕是在其他逻辑里),就会立即播放。
  • cachedBuffers中的数据可能在延迟启动前就已经被填充,并且有其他线程在延迟期间已经将数据写入了AudioTrack。
  • WRITE_NON_BLOCKING模式下,只要AudioTrack的内部缓冲区有空闲,写入会立即完成,若AudioTrack已在播放,写入的数据会被马上调度播放。

修正方案:

  1. 延迟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)
                }
            }
        }
    }
    
  2. 确保数据只在延迟后才进入播放流程
    检查你的缓存填充逻辑,保证cachedBuffers的数据是在delayOutput()启动后才开始填充,或者在延迟期间禁止其他线程操作AudioTrack的写入。如果有其他地方在写入AudioTrack,必须统一到这个延迟后的协程里处理。

  3. 使用线程安全的缓存容器
    把cachedBuffers换成线程安全的队列,比如ConcurrentLinkedQueue,避免多线程操作导致的数据提前写入:

    private val cachedBuffers = ConcurrentLinkedQueue<ShortArray>()
    

    读取和移除操作也对应调整:

    val item = cachedBuffers.poll()
    

额外检查点:

  • 确认isRecording变量是线程安全的(比如用volatile修饰),避免协程逻辑提前退出或异常执行。
  • 打印audioTrack.play()的调用时机,以及缓存数据的填充时间,确认两者都在2秒延迟之后。

内容的提问来源于stack exchange,提问作者jianglei

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 09:26:12