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

使用AudioRecord录制内部音频偶现杂音问题求助

解决AudioRecord后台录制内部音频偶发杂音问题

你的代码存在几个核心问题,这些正是导致偶发杂音的主要原因:

  • 循环内重复创建IO流与缓冲区:每次循环都新建FileOutputStream会覆盖已有录制数据,频繁分配ByteBuffer还会引发内存抖动,直接导致音频采样丢帧。
  • 忽略read()实际返回值:直接用AudioRecord.getMinBufferSize()作为写入长度,而read()可能因系统负载没读满缓冲区,写入空数据就会产生杂音。
  • 重复计算最小缓冲区大小:getMinBufferSize()应在初始化阶段计算一次,循环内重复调用可能导致数值不一致,引发录制异常。
  • 变量名拼写错误:代码中konfigurasyon是拼写错误,应使用之前创建的configuration,否则会导致AudioRecord初始化异常(若未编译报错大概率是笔误)。

修复步骤

  1. 提前初始化核心资源:录制线程启动前,计算好最小缓冲区大小,创建一次性的ByteBuffer和FileOutputStream,避免循环内频繁IO与内存操作。
  2. 用read()实际返回值写入文件:仅当read()返回有效长度(>0)时才写入,避免空数据混入。
  3. 统一资源释放逻辑:录制结束时集中关闭流、释放AudioRecord,避免资源泄漏。
  4. 优化线程优先级:给录制线程设置高优先级,降低被系统低优先级任务抢占的概率。

修正后的代码示例

初始化部分

// 提前计算最小缓冲区大小,避免循环内重复计算
int minBufferSize = AudioRecord.getMinBufferSize(44100, 
    AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT);
// 建议放大缓冲区,降低丢帧概率
int actualBufferSize = minBufferSize * 2;

AudioPlaybackCaptureConfiguration configuration = new AudioPlaybackCaptureConfiguration.Builder(mediaProjection)
        .addMatchingUsage(AudioAttributes.USAGE_MEDIA)
        .build();

AudioFormat audioFormat = new AudioFormat.Builder()
        .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
        .setSampleRate(44100)
        .setChannelMask(AudioFormat.CHANNEL_IN_STEREO)
        .build();

AudioRecord audioRecord = new AudioRecord.Builder()
        .setAudioFormat(audioFormat)
        .setAudioPlaybackCaptureConfig(configuration) // 修正变量名拼写错误
        .build();

// 提前创建缓冲区与输出流
ByteBuffer buffer = ByteBuffer.allocateDirect(actualBufferSize);
FileOutputStream os = null;
try {
    File audioFile = new File(context.getExternalFilesDir(Environment.DIRECTORY_MUSIC), "tempAudio.pcm");
    os = new FileOutputStream(audioFile, true); // 追加模式写入,避免覆盖已有数据
} catch (IOException e) {
    e.printStackTrace();
    audioRecord.release();
    return;
}

audioRecord.startRecording();

录制线程部分

Thread recordingThread = new Thread(() -> {
    while (recordAudio) {
        try {
            // 获取实际读取的音频数据长度
            int readSize = audioRecord.read(buffer.array(), 0, actualBufferSize);
            
            if (readSize > 0) {
                // 仅写入有效数据
                os.write(buffer.array(), 0, readSize);
                buffer.clear();
            } else if (readSize <= AudioRecord.ERROR_BAD_VALUE) {
                // 读取错误,终止录制
                recordAudio = false;
                Log.e("Recording", "AudioRecord read error: " + readSize);
            }

        } catch (Exception e) {
            e.printStackTrace();
            break;
        }
    }

    // 录制结束统一释放资源
    try {
        if (audioRecord.getState() == AudioRecord.STATE_INITIALIZED) {
            audioRecord.stop();
            audioRecord.release();
        }
        if (os != null) {
            os.flush();
            os.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    // 按需清理临时文件(比如录制失败时删除)
    if (!recordAudio) {
        new File(context.getExternalFilesDir(Environment.DIRECTORY_MUSIC) + "/tempAudio.pcm").delete();
    }

    showNotification(context);
});
// 设置线程高优先级,减少被抢占概率
recordingThread.setPriority(Thread.MAX_PRIORITY);
recordingThread.start();

额外注意事项

  • 避免录制时同时进行高CPU/IO占用的后台任务(如文件下载、大内存计算)。
  • 若杂音仍存在,可尝试调整采样率(如48000Hz)或单声道录制,部分设备对特定格式兼容性更好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 16:48:20