适用于 Android 的音频分类指南

借助 MediaPipe 音频分类器任务,您可以对音频数据进行分类。您可以 使用此任务从一组经过训练的类别中识别声音事件。这些 说明了如何在 Android 应用中使用音频分类器。

如需详细了解功能、模型和配置选项 部分,请参阅概览

代码示例

MediaPipe Tasks 示例代码是音频分类器的简单实现 Android 版应用。本示例使用实体 Android 设备上的麦克风 持续对声音进行分类,还可以对声音文件运行分类器 存储在设备上的数据

您可以用该应用作为基础来开发自己的 Android 应用,也可以指代该应用 对现有应用进行了修改。音频分类器示例代码托管在 GitHub

下载代码

以下说明介绍了如何创建示例的本地副本 使用 git 命令行工具运行 git 代码库。

<ph type="x-smartling-placeholder">

如需下载示例代码,请执行以下操作:

  1. 使用以下命令克隆 git 代码库:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. (可选)将您的 Git 实例配置为使用稀疏检出, 因此您只有音频分类器示例应用的文件:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/audio_classifier/android
    

创建示例代码的本地版本后,您可以导入项目 进入 Android Studio 并运行应用。有关说明,请参阅 Android 版设置指南

关键组件

以下文件包含此音频的关键代码 分类示例应用:

设置

本部分介绍了设置开发环境和 专门用于音频分类器的代码项目。有关 设置开发环境以使用 MediaPipe 任务,包括 平台版本要求,请参阅 Android 版设置指南

<ph type="x-smartling-placeholder">

依赖项

音频分类器使用 com.google.mediapipe:tasks-audio 库。添加此项 依赖项的 build.gradle 文件 Android 应用开发项目。使用以下代码导入所需的依赖项: 以下代码:

dependencies {
    ...
    implementation 'com.google.mediapipe:tasks-audio:latest.release'
}

型号

MediaPipe 音频分类器任务需要一个与此分类兼容的经过训练的模型 任务。如需详细了解可供音频分类器训练的可用模型,请参阅 任务概览的“模型”部分

选择并下载模型,然后将其存储在项目目录中:

<dev-project-root>/src/main/assets

使用 BaseOptions.Builder.setModelAssetPath() 方法指定路径 模型所用的指标。下一部分的代码示例将引用此方法 部分。

在 音频分类器示例代码, 该模型在 AudioClassifierHelper.kt 中定义, 文件。

创建任务

您可以使用 createFromOptions 函数创建任务。通过 “createFromOptions”函数接受配置选项,包括正在运行的 模式、显示名称语言区域、结果数上限、置信度阈值 以及类别许可名单或拒绝名单如需详细了解配置 选项,请参阅配置概览

音频分类器任务支持以下输入数据类型:音频剪辑 和音频流。您需要指定与 输入数据类型。选择与 输入数据类型,了解如何创建任务并运行推理。

音频片段

AudioClassifierOptions options =
    AudioClassifierOptions.builder()
        .setBaseOptions(
            BaseOptions.builder().setModelAssetPath("model.tflite").build())
        .setRunningMode(RunningMode.AUDIO_CLIPS)
        .setMaxResults(5)
        .build();
audioClassifier = AudioClassifier.createFromOptions(context, options);
    

音频流

AudioClassifierOptions options =
    AudioClassifierOptions.builder()
        .setBaseOptions(
            BaseOptions.builder().setModelAssetPath("model.tflite").build())
        .setRunningMode(RunningMode.AUDIO_STREAM)
        .setMaxResults(5)
        .setResultListener(audioClassifierResult -> {
             // Process the classification result here.
        })
        .build();
audioClassifier = AudioClassifier.createFromOptions(context, options);
    

音频分类器示例代码实现允许用户在 处理模式这种方法使得任务创建代码更加复杂, 可能不适合您的用例。您可以看到模式切换代码 函数的 initClassifier() 函数中, AudioClassifierHelper

配置选项

此任务具有以下适用于 Android 应用的配置选项:

选项名称 说明 值范围 默认值
runningMode 设置任务的运行模式。音频分类器有两种模式:

AUDIO_CLIPS:在独立的音频片段上运行音频任务的模式。

AUDIO_STREAM:对音频流(例如通过麦克风)运行音频任务的模式。在此模式下,resultListener 必须为 调用以设置监听器来接收分类结果 异步执行。
{AUDIO_CLIPS, AUDIO_STREAM} AUDIO_CLIPS
displayNamesLocale 设置要用于 任务模型的元数据(如果有)。默认值为 en, 英语。您可以向自定义模型的元数据中添加本地化标签 使用 TensorFlow Lite Metadata Writer API 语言区域代码 en
maxResults 将评分最高的分类结果的可选数量上限设置为 return。如果 <0,则返回所有可用的结果。 任何正数 -1
scoreThreshold 设置预测分数阈值,以替换 模型元数据(如果有)。低于此值的结果将被拒绝。 [0.0, 1.0] 未设置
categoryAllowlist 设置允许的类别名称的可选列表。如果不为空, 类别名称未包含在此集合中的分类结果 已滤除。重复或未知的类别名称会被忽略。 此选项与 categoryDenylist 互斥,使用 都会导致错误。 任何字符串 未设置
categoryDenylist 设置不允许使用的类别名称的可选列表。如果 非空,类别名称在此集中的分类结果将被滤除 。重复或未知的类别名称会被忽略。这个选项 categoryAllowlist 不包含,同时使用这两个元素会导致错误。 任何字符串 未设置
resultListener 设置结果监听器以接收分类结果 当音频分类器在音频流中时异步播放 模式。仅在跑步模式设为“AUDIO_STREAM”时才能使用 不适用 未设置
errorListener 设置一个可选的错误监听器。 不适用 未设置

准备数据

音频分类器支持音频片段和音频流。任务 负责处理数据输入预处理,包括重新采样、缓冲和分帧。 但是,您必须将输入音频数据转换为 com.google.mediapipe.tasks.components.containers.AudioData 对象,然后再将其传递给音频分类器任务。

音频片段

import com.google.mediapipe.tasks.components.containers.AudioData;

// Load an audio on the users device as a float array.

// Convert a float array to a MediaPipes AudioData object.
AudioData audioData =
    AudioData.create(
        AudioData.AudioDataFormat.builder()
            .setNumOfChannels(numOfChannels)
            .setSampleRate(sampleRate)
            .build(),
        floatData.length);
audioData.load(floatData);
    

音频流

import android.media.AudioRecord;
import com.google.mediapipe.tasks.components.containers.AudioData;

AudioRecord audioRecord =
    audioClassifier.createAudioRecord(/* numChannels= */ 1, /* sampleRate= */ 16000);
audioRecord.startRecording();

...

// To get a one second clip from the AudioRecord object:
AudioData audioData =
    AudioData.create(
        16000 /*sample counts per second*/);
        AudioData.AudioDataFormat.create(audioRecord.getFormat()),
audioData.load(audioRecord)
    

运行任务

您可以调用与跑步模式对应的 classify 函数, 可以触发推理。Audio Classifier API 会返回 在输入音频数据中识别出的音频事件。

音频片段

AudioClassifierResult classifierResult = audioClassifier.classify(audioData);
    

音频流

// Run inference on the audio block. The classifications results will be available
// via the `resultListener` provided in the `AudioClassifierOptions` when
// the audio classifier was created.
audioClassifier.classifyAsync(audioBlock, timestampMs);
    

请注意以下几点:

  • 在音频流模式下运行时,还必须提供 包含时间戳的音频分类器任务,用于跟踪哪些音频数据 流被用于推理。
  • 在音频剪辑模型中运行时,音频分类器任务会阻塞 当前线程,直到处理完输入音频为止。 为避免阻塞用户界面响应,请在 后台线程。

您可以查看使用音频片段运行音频分类器的示例,请参阅 AudioClassifierHelper 类中的 代码示例

处理和显示结果

运行推理后,音频分类器任务会返回 输入音频中音频事件的类别。以下列表 展示了此任务的输出数据示例:

AudioClassifierResult:
  Timestamp in microseconds: 100
  ClassificationResult #0:
    Timestamp in microseconds: 100  
    Classifications #0 (single classification head):
      head index: 0
      category #0:
        category name: "Speech"
        score: 0.6
        index: 0
      category #1:
        category name: "Music"
        score: 0.2
        index: 1

在 Android 应用中,该任务会返回 ClassificationResult,其中包含 AudioClassifierResult 对象的列表,表示针对某个 音频事件,包括类别标签和置信度分数。

音频片段

// In the audio clips mode, the classification results are for the entire audio
// clip. The results are timestamped AudioClassifierResult objects, each
// classifying an interval of the entire audio clip that starts at
// ClassificationResult.timestampMs().get().

for (ClassificationResult result : audioClassifierResult.classificationResults()) {
  // Audio interval start timestamp:
  result.timestampMs().get();
  // Classification result of the audio interval.
  result.classifications();
}
    

音频流

// In the audio stream mode, the classification results list only contains one
// element, representing the classification result of the audio block that
// starts at ClassificationResult.timestampMs in the audio stream.

ClassificationResult result = audioClassifierResult.classificationResults().get(0);
// The audio block start timestamp
audioClassifierResult.timestampMs();
// Alternatively, the same timestamp can be retrieved from
// result.timestampMs().get();

// Classification result.
result.classifications();
    

您可以通过一个示例 在 API 的 ProbabilitiesAdapter 类中从此任务返回的结果 代码示例