简介: CSDN博客专家、《Android系统多媒体进阶实战》作者
博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏地址: Audio工程师进阶系列【原创干货持续更新中……】🚀
Android多媒体专栏地址: 多媒体系统工程师系列【原创干货持续更新中……】🚀
推荐1:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀
推荐2:Android14 Binder之HIDL与AIDL通信实战课 🚀
推荐3:Android15快速自定义与集成音效实战课 🚀
推荐4:Android15音频策略实战课 🚀
人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
🍉🍉🍉文章目录🍉🍉🍉
Android16进阶之获取录音Metrics AudioRecord.getMetrics:用法实例
🌻1. 前言
本篇目的:Android16进阶之获取录音Metrics参数AudioRecord.getMetrics:用法实例
🌻2. Android16进阶之获取录音Metrics参数AudioRecord.getMetrics介绍
-
基本概念
getMetrics 返回 PersistableBundle,内含缓冲区溢出次数、硬件延迟、实际采样率等关键指标,用于性能分析与质量监控。 -
功能
运行期随时查询;与底层 HAL 联动;可用于日志上报、异常预警;无阻塞。 -
使用限制
仅在 RECORDSTATE_RECORDING 时数据有效;返回空包表示未支持;API 31 及以上。 -
性能特性
原子读,毫秒级;无额外内存分配;与硬件计数器同步。 -
使用场景
质量监控、异常预警、性能调优、自动化测试、运营统计。
🌻3. 代码实例
🌻3.1 直播质量实时看板
AudioRecord record = new AudioRecord.Builder()
.setAudioSource(MediaRecorder.AudioSource.MIC)
.setAudioFormat(new AudioFormat.Builder()
.setSampleRate(48000)
.setChannelMask(AudioFormat.CHANNEL_IN_STEREO)
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
.build())
.setBufferSizeInBytes(32768)
.build();
record.startRecording();
FileOutputStream fos = new FileOutputStream("/sdcard/live48k.raw");
byte[] buf = new byte[8192];
while (streaming) {
int read = record.read(buf, 0, buf.length);
if (read > 0) fos.write(buf, 0, read);
PersistableBundle m = record.getMetrics();
if (m != null) {
long over = m.getLong(AudioRecord.METRICS_BUFFER_OVERFLOW);
if (over > 0) postToDashboard("溢出次数", over);
}
}
fos.close();
record.stop();
record.release();
代码功能:循环读取Metrics,缓冲区溢出立即上报看板,主播可实时调整码率。
🌻3.2 车载通话硬件延迟预警
AudioRecord record = new AudioRecord.Builder()
.setAudioSource(MediaRecorder.AudioSource.VOICE_COMMUNICATION)
.setAudioFormat(new AudioFormat.Builder()
.setSampleRate(16000)
.setChannelMask(AudioFormat.CHANNEL_IN_MONO)
.setEncoding(AudioFormat.ENCODING_PCM_16BIT)
.build())
.setBufferSizeInBytes(6400)
.build();
record.startRecording();
DatagramSocket socket = new DatagramSocket();
InetAddress addr = InetAddress.getByName("10.0.0.88");
byte[] pkt = new byte[320];
while (calling) {
int read = record.read(pkt, 0, pkt.length);
if (read > 0) socket.send(new DatagramPacket(pkt, read, addr, 5004));
PersistableBundle m = record.getMetrics();
if (m != null) {
int latency = m.getInt(AudioRecord.METRICS_LATENCY_MS);
if (latency > 50) toast("延迟过高,请检查蓝牙");
}
}
socket.close();
record.stop();
record.release();
代码功能:获取延迟指标,超过50 ms立即提示司机,保障免提通话体验。
🌻3.3 识别实际采样率校验
AudioRecord record = new AudioRecord.Builder()
.setAudioSource(MediaRecorder.AudioSource.VOICE_RECOGNITION)
.setAudioFormat(new AudioFormat.Builder()
.setSampleRate(16000)
.setChannelMask(AudioFormat.CHANNEL_IN_MONO)
.setEncoding(AudioFormat.ENCODING_PCM_FLOAT)
.build())
.setBufferSizeInBytes(1280)
.build();
record.startRecording();
float[] frame = new float[320];
while (recognizing) {
int read = record.read(frame, 0, frame.length);
if (read > 0) {
float[] mel = computeMel(frame);
model.input(mel);
}
PersistableBundle m = record.getMetrics();
if (m != null) {
int actualRate = m.getInt(AudioRecord.METRICS_SAMPLE_RATE);
if (actualRate != 16000) Log.e(TAG, "采样率漂移 " + actualRate);
}
}
record.stop();
record.release();
代码功能:读取实际采样率,发现漂移立即上报,确保梅尔滤波器频率网格精准。
🌻3.4 用法总结
| 代码关键字 | 功能描述 | 典型应用 |
|---|---|---|
| getMetrics | 指标读取 | 溢出实时看板 |
| getMetrics | 指标读取 | 延迟预警 |
| getMetrics | 指标读取 | 采样率校验 |