Android16音频之获取录音Metrics参数AudioRecord.getMetrics:用法实例(二百)

Source

简介: CSDN博客专家、《Android系统多媒体进阶实战》作者

博主新书推荐:《Android系统多媒体进阶实战》🚀
Android Audio工程师专栏地址: Audio工程师进阶系列原创干货持续更新中……】🚀
Android多媒体专栏地址: 多媒体系统工程师系列原创干货持续更新中……】🚀
推荐1:AAOS车载系统+AOSP14系统攻城狮入门视频实战课 🚀
推荐2:Android14 Binder之HIDL与AIDL通信实战课 🚀
推荐3:Android15快速自定义与集成音效实战课 🚀
推荐4:Android15音频策略实战课 🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮


Android16进阶之获取录音Metrics AudioRecord.getMetrics:用法实例

🌻1. 前言

本篇目的:Android16进阶之获取录音Metrics参数AudioRecord.getMetrics:用法实例

🌻2. Android16进阶之获取录音Metrics参数AudioRecord.getMetrics介绍

  1. 基本概念
    getMetrics 返回 PersistableBundle,内含缓冲区溢出次数、硬件延迟、实际采样率等关键指标,用于性能分析与质量监控。

  2. 功能
    运行期随时查询;与底层 HAL 联动;可用于日志上报、异常预警;无阻塞。

  3. 使用限制
    仅在 RECORDSTATE_RECORDING 时数据有效;返回空包表示未支持;API 31 及以上。

  4. 性能特性
    原子读,毫秒级;无额外内存分配;与硬件计数器同步。

  5. 使用场景
    质量监控、异常预警、性能调优、自动化测试、运营统计。

🌻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 指标读取 采样率校验