Android录制原始音频字节到变量供AudioTrack播放的实现稳定性咨询
针对Android音频录制writeAudioToLocalVariable方法的稳定性优化建议
现有实现的潜在问题
你的当前代码可以正常运行,但存在4个会影响多设备兼容性和稳定性的风险点:
- 未处理
AudioRecord.read()的返回值:该方法返回的是本次实际读取到的有效字节数,你当前不管返回值直接写满整个缓存数组到输出流,会导致末尾写入大量无效脏数据,出现杂音、音频长度不符的问题。 - 硬编码缓存大小:你虽然打印了系统返回的最小缓存值,但实际初始化和读取用的是固定的8192,如果某台设备的最小缓存要求大于8192,
AudioRecord会直接初始化失败,出现崩溃。 - 线程可见性问题:
isRecording变量没有加volatile修饰,主线程修改该变量后,录音子线程可能感知不到变量更新,导致录音无法停止、循环一直运行。 - 未处理读取错误:
read方法会返回负数代表出现异常(比如录音被抢占、硬件故障),你当前没有判断错误状态,出现问题后会继续循环写入无效数据。
优化后的实现方案
第一步:修改基础变量配置
// 给isRecording加volatile保证线程可见性 volatile boolean isRecording = false; // 删除硬编码的MY_CHOSEN_BUFFER_SIZE,改用动态计算的缓存大小 private int RECORD_BUFFER_SIZE;
第二步:onCreate里计算合适的缓存大小
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); int minBufferSize = AudioRecord.getMinBufferSize(SAMPLERATE, REC_CHANNELS, ENCODING); Log.i("ABC", "FYI, min buffer size for this device is : " + minBufferSize); // 取最小缓存的2倍,保证所有设备都不会出现缓存不足丢帧的问题 RECORD_BUFFER_SIZE = Math.max(minBufferSize * 2, 8192); }
第三步:重写writeAudioToLocalVariable方法
private void writeAudioToLocalVariable() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] temporaryChunkOfBytes = new byte[RECORD_BUFFER_SIZE]; while (isRecording) { int readResult = recorder.read(temporaryChunkOfBytes, 0, RECORD_BUFFER_SIZE); // 读取失败直接退出循环 if (readResult < 0) { Log.e("ABC", "Recording read error, code: " + readResult); break; } // 只写入实际读到的有效字节数 if (readResult > 0) { baos.write(temporaryChunkOfBytes, 0, readResult); } } recordedAudioAsBytes = baos.toByteArray(); try { baos.close(); } catch (Exception e) { e.printStackTrace(); } }
第四步:同步修改AudioRecord初始化、AudioTrack初始化的缓存参数为RECORD_BUFFER_SIZE即可。
额外优化建议
- 播放完成后记得调用
player.stop()、player.release()释放AudioTrack资源,避免出现内存泄露、音频设备被占用的问题。 - 短音频播放可以改用
AudioTrack.MODE_STATIC,你之前无法使用大概率是因为之前的音频数据末尾有脏数据,优化数据后即可正常使用,延迟更低。
内容的提问来源于stack exchange,提问作者Nerdy Bunz
相关产品推荐
相关产品推荐

