借助 MediaPipe 音频分类器任务,您可以对音频数据进行分类。您可以 使用此任务从一组经过训练的类别中识别声音事件。这些 说明了如何在 Android 应用中使用音频分类器。
如需详细了解功能、模型和配置选项 部分,请参阅概览。
代码示例
MediaPipe Tasks 示例代码是音频分类器的简单实现 Android 版应用。本示例使用实体 Android 设备上的麦克风 持续对声音进行分类,还可以对声音文件运行分类器 存储在设备上的数据
您可以用该应用作为基础来开发自己的 Android 应用,也可以指代该应用 对现有应用进行了修改。音频分类器示例代码托管在 GitHub
下载代码
以下说明介绍了如何创建示例的本地副本 使用 git 命令行工具运行 git 代码库。
<ph type="x-smartling-placeholder">如需下载示例代码,请执行以下操作:
- 使用以下命令克隆 git 代码库:
git clone https://github.com/google-ai-edge/mediapipe-samples
- (可选)将您的 Git 实例配置为使用稀疏检出,
因此您只有音频分类器示例应用的文件:
cd mediapipe git sparse-checkout init --cone git sparse-checkout set examples/audio_classifier/android
创建示例代码的本地版本后,您可以导入项目 进入 Android Studio 并运行应用。有关说明,请参阅 Android 版设置指南。
关键组件
以下文件包含此音频的关键代码 分类示例应用:
- AudioClassifierHelper.kt - 初始化音频分类器并处理模型和委托 选择。
- RecorderFragment.kt - 为实时录音创建界面和控制代码。
- LibraryFragment.kt: 创建用于选择音频文件的界面和控制代码。
- ProbabilitiesAdapter.kt - 处理分类器的预测结果并为其设置格式。
设置
本部分介绍了设置开发环境和 专门用于音频分类器的代码项目。有关 设置开发环境以使用 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 user’s device as a float array. // Convert a float array to a MediaPipe’s 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
类中从此任务返回的结果
代码示例。