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

Android应用中如何将WAV音频文件转换为ByteBuffer以输入YAMNet TensorFlow Lite模型

Android应用中如何将WAV音频文件转换为ByteBuffer以输入YAMNet TensorFlow Lite模型

我来帮你搞定这个问题!要把WAV文件转换成YAMNet模型需要的ByteBuffer,核心是先把音频处理成模型要求的格式——16kHz采样率、单通道、32位浮点型PCM数据,而且必须是固定的15600个样本(对应0.975秒音频)。下面是具体的步骤和代码实现:

一、核心思路

YAMNet对输入有严格要求,所以我们需要先完成两个关键操作:

  1. 将原WAV文件转成16kHz单通道的浮点PCM数据;
  2. 把处理后的音频数据裁剪/补0到15600个样本,再转成符合要求的ByteBuffer。

二、完整代码实现

这里推荐用TarsosDSP库来简化音频格式转换(它是Android端处理音频重采样、格式转换的轻量工具),先在build.gradle里添加依赖:

implementation 'be.tarsos.dsp:TarsosDSP:2.4.0'

然后编写转换函数:

import android.os.Build
import java.io.File
import java.nio.ByteBuffer
import java.nio.ByteOrder
import be.tarsos.dsp.AudioEvent
import be.tarsos.dsp.AudioProcessor
import be.tarsos.dsp.io.android.AudioDispatcherFactory

fun convertWavToYamnetInput(wavFile: File): ByteBuffer {
    // 1. 初始化音频调度器,直接把WAV文件转成16kHz单通道的浮点数据
    // 参数:文件、目标采样率、单次读取样本数、偏移量
    val dispatcher = AudioDispatcherFactory.fromFile(wavFile, 16000, 15600, 0)
    val floatSamples = mutableListOf<Float>()

    // 2. 读取并收集音频样本,直到凑够15600个
    dispatcher.addAudioProcessor(object : AudioProcessor {
        override fun process(audioEvent: AudioEvent): Boolean {
            val buffer = audioEvent.floatBuffer
            floatSamples.addAll(buffer.toList())
            // 样本数够了就停止读取
            return floatSamples.size < 15600
        }

        override fun processingFinished() {}
    })
    dispatcher.run()

    // 3. 调整样本数到固定的15600:多了截断,少了补0
    val fixedSamples = FloatArray(15600)
    if (floatSamples.size >= 15600) {
        floatSamples.take(15600).toFloatArray().copyInto(fixedSamples)
    } else {
        floatSamples.toFloatArray().copyInto(fixedSamples)
    }

    // 4. 将浮点数组转成TensorFlow Lite需要的ByteBuffer
    val byteBuffer = ByteBuffer.allocateDirect(fixedSamples.size * 4) // 每个float占4字节
    byteBuffer.order(ByteOrder.nativeOrder()) // 对齐设备本地字节序
    byteBuffer.asFloatBuffer().put(fixedSamples)
    byteBuffer.rewind() // 重置指针到缓冲区开头

    return byteBuffer
}

三、使用示例

把转换后的ByteBuffer传入模型即可:

// 假设你已经获取到WAV文件的File实例
val wavFile = File(getExternalFilesDir(null), "cough.wav")
val byteBuffer = convertWavToYamnetInput(wavFile)

// 加载到TensorBuffer中
val audioClip = TensorBuffer.createFixedSize(intArrayOf(15600), DataType.FLOAT32)
audioClip.loadBuffer(byteBuffer)

// 运行模型推理
val model = YamnetClassification.newInstance(this)
val outputs = model.process(audioClip)
val scores = outputs.scoresAsTensorBuffer

// 处理结果:比如找到得分最高的类别(需要配合YAMNet的标签表映射)
val scoresArray = scores.floatArray
val topCategoryIndex = scoresArray.indices.maxByOrNull { scoresArray[it] }
// 这里可以用官方提供的标签列表,把索引转成具体类别名称(比如"cough")

四、注意事项

  1. 权限问题:如果读取外部存储的WAV文件,Android 10及以上需要申请READ_EXTERNAL_STORAGE权限,或者使用Scoped Storage访问文件;
  2. 无第三方库方案:如果不想依赖TarsosDSP,可以用Android原生的MediaCodec+AudioFormat手动解码和重采样,但代码会复杂很多;
  3. 标签映射:YAMNet的得分数组索引对应官方的标签列表,你需要把索引和具体类别名称(比如"speech"、"cough")做映射,标签表可以从YAMNet的官方文档获取。

备注:内容来源于stack exchange,提问作者M. K.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 10:18:07