The MediaPipe Audio Classifier task lets you classify audio clips into a set of defined categories, such as guitar music, a train whistle, or a bird's song. The categories are defined during the training of the model. This task operates on audio data with a machine learning (ML) model as independent audio clips or a continuous stream and outputs a list of potential categories ranked by descending probability score.
Quickstart
Install the SDK for your platform, prepare audio input data, choose an audio running mode, and run inference.
Web
Audio clips
import { AudioClassifier, FilesetResolver } from "@mediapipe/tasks-audio"; const MODEL_URL = "https://storage.googleapis.com/mediapipe-models/audio_classifier/yamnet/float32/latest/yamnet.tflite"; const audio = await FilesetResolver.forAudioTasks( "https://cdn.jsdelivr.net/npm/@mediapipe/tasks-audio@latest/wasm" ); const audioClassifier = await AudioClassifier.createFromOptions(audio, { baseOptions: { modelAssetPath: MODEL_URL }, maxResults: 5, }); // Synchronous classification across every window of a complete decoded clip const audioCtx = new AudioContext({ sampleRate: 16000 }); const response = await fetch("audio_clip.wav"); const audioBuffer = await audioCtx.decodeAudioData(await response.arrayBuffer()); const results = audioClassifier.classify(audioBuffer.getChannelData(0), audioBuffer.sampleRate);
Audio stream
import { AudioClassifier, FilesetResolver } from "@mediapipe/tasks-audio"; const MODEL_URL = "https://storage.googleapis.com/mediapipe-models/audio_classifier/yamnet/float32/latest/yamnet.tflite"; const audio = await FilesetResolver.forAudioTasks( "https://cdn.jsdelivr.net/npm/@mediapipe/tasks-audio@latest/wasm" ); const audioClassifier = await AudioClassifier.createFromOptions(audio, { baseOptions: { modelAssetPath: MODEL_URL }, maxResults: 5, }); // Live microphone stream: classify contiguous PCM windows posted by a 15-line // AudioWorklet processor (pcm-chunk-processor.js) — see the Prepare input data guide. const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); const audioCtx = new AudioContext({ sampleRate: 16000 }); await audioCtx.audioWorklet.addModule("pcm-chunk-processor.js"); const source = audioCtx.createMediaStreamSource(stream); const worklet = new AudioWorkletNode(audioCtx, "pcm-chunk-processor"); worklet.port.onmessage = ({ data: pcmSamples }) => { const results = audioClassifier.classify(pcmSamples, audioCtx.sampleRate); console.log(results[0]?.classifications[0]?.categories); }; source.connect(worklet);
Android (Kotlin)
Audio clips
import com.google.mediapipe.tasks.audio.audioclassifier.AudioClassifier import com.google.mediapipe.tasks.audio.audioclassifier.AudioClassifier.AudioClassifierOptions import com.google.mediapipe.tasks.audio.core.RunningMode import com.google.mediapipe.tasks.components.containers.AudioData import com.google.mediapipe.tasks.components.containers.AudioData.AudioDataFormat import com.google.mediapipe.tasks.core.BaseOptions val baseOptions = BaseOptions.builder() .setModelAssetPath("yamnet.tflite") .build() val options = AudioClassifierOptions.builder() .setBaseOptions(baseOptions) .setRunningMode(RunningMode.AUDIO_CLIPS) .setMaxResults(5) .build() val audioClassifier = AudioClassifier.createFromOptions(context, options) // Synchronous classification over a complete prerecorded AudioData clip val format = AudioDataFormat.builder().setSampleRate(16000f).build() val audioData = AudioData.create(format, clipSamples.size) audioData.load(clipSamples) val result = audioClassifier.classify(audioData)
Audio stream
import android.os.SystemClock import android.util.Log import com.google.mediapipe.tasks.audio.audioclassifier.AudioClassifier import com.google.mediapipe.tasks.audio.audioclassifier.AudioClassifier.AudioClassifierOptions import com.google.mediapipe.tasks.audio.core.RunningMode import com.google.mediapipe.tasks.components.containers.AudioData import com.google.mediapipe.tasks.core.BaseOptions val baseOptions = BaseOptions.builder() .setModelAssetPath("yamnet.tflite") .build() val options = AudioClassifierOptions.builder() .setBaseOptions(baseOptions) .setRunningMode(RunningMode.AUDIO_STREAM) .setMaxResults(5) .setResultListener { result -> val categories = result.classificationResults().firstOrNull()?.classifications()?.firstOrNull()?.categories() } .setErrorListener { error -> Log.e("MediaPipe", error.message.orEmpty()) } .build() val audioClassifier = AudioClassifier.createFromOptions(context, options) // Async: accumulates contiguous microphone PCM chunks into spectrogram windows if (audioData.load(audioRecord) > 0) { audioClassifier.classifyAsync(audioData, SystemClock.uptimeMillis()) }
Android (Java)
Audio clips
import com.google.mediapipe.tasks.audio.audioclassifier.AudioClassifier; import com.google.mediapipe.tasks.audio.audioclassifier.AudioClassifier.AudioClassifierOptions; import com.google.mediapipe.tasks.audio.audioclassifier.AudioClassifierResult; import com.google.mediapipe.tasks.audio.core.RunningMode; import com.google.mediapipe.tasks.components.containers.AudioData; import com.google.mediapipe.tasks.components.containers.AudioData.AudioDataFormat; import com.google.mediapipe.tasks.core.BaseOptions; BaseOptions baseOptions = BaseOptions.builder() .setModelAssetPath("yamnet.tflite") .build(); AudioClassifierOptions options = AudioClassifierOptions.builder() .setBaseOptions(baseOptions) .setRunningMode(RunningMode.AUDIO_CLIPS) .setMaxResults(5) .build(); AudioClassifier audioClassifier = AudioClassifier.createFromOptions(context, options); // Synchronous classification over a complete prerecorded AudioData clip AudioDataFormat format = AudioDataFormat.builder().setSampleRate(16000f).build(); AudioData audioData = AudioData.create(format, clipSamples.length); audioData.load(clipSamples); AudioClassifierResult result = audioClassifier.classify(audioData);
Audio stream
import android.os.SystemClock; import android.util.Log; import com.google.mediapipe.tasks.audio.audioclassifier.AudioClassifier; import com.google.mediapipe.tasks.audio.audioclassifier.AudioClassifier.AudioClassifierOptions; import com.google.mediapipe.tasks.audio.core.RunningMode; import com.google.mediapipe.tasks.components.containers.AudioData; import com.google.mediapipe.tasks.core.BaseOptions; BaseOptions baseOptions = BaseOptions.builder() .setModelAssetPath("yamnet.tflite") .build(); AudioClassifierOptions options = AudioClassifierOptions.builder() .setBaseOptions(baseOptions) .setRunningMode(RunningMode.AUDIO_STREAM) .setMaxResults(5) .setResultListener(result -> { var results = result.classificationResults(); }) .setErrorListener(error -> Log.e("MediaPipe", String.valueOf(error.getMessage()))) .build(); AudioClassifier audioClassifier = AudioClassifier.createFromOptions(context, options); // Async: accumulates contiguous microphone PCM chunks into spectrogram windows if (audioData.load(audioRecord) > 0) { audioClassifier.classifyAsync(audioData, SystemClock.uptimeMillis()); }
iOS
Audio clips
import Foundation import MediaPipeTasksAudio guard let modelPath = Bundle.main.path(forResource: "yamnet", ofType: "tflite") else { return } let options = AudioClassifierOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .audioClips options.maxResults = 5 let audioClassifier = try AudioClassifier(options: options) // Synchronous classification across every window of a complete audio clip let result = try audioClassifier.classify(audioClip: audioData)
Audio stream
import Foundation import MediaPipeTasksAudio final class AudioClassifierStreamService: NSObject { private var audioClassifier: AudioClassifier? func setUp() throws { guard let modelPath = Bundle.main.path(forResource: "yamnet", ofType: "tflite") else { return } let options = AudioClassifierOptions() options.baseOptions.modelAssetPath = modelPath options.runningMode = .audioStream options.maxResults = 5 options.audioClassifierStreamDelegate = self audioClassifier = try AudioClassifier(options: options) } func classifyAsync(audioData: AudioData, timestampMs: Int) throws { // Async: accumulates contiguous microphone PCM blocks into spectrogram windows try audioClassifier?.classifyAsync(audioBlock: audioData, timestampInMilliseconds: timestampMs) } } extension AudioClassifierStreamService: AudioClassifierStreamDelegate { func audioClassifier( _ audioClassifier: AudioClassifier, didFinishClassification result: AudioClassifierResult?, timestampInMilliseconds: Int, error: (any Error)? ) { guard let result else { return } DispatchQueue.main.async { let categories = result.classificationResult.classifications.first?.categories } } }
Python
Audio clips
import mediapipe as mp BaseOptions = mp.tasks.BaseOptions AudioClassifier = mp.tasks.audio.AudioClassifier AudioClassifierOptions = mp.tasks.audio.AudioClassifierOptions AudioRunningMode = mp.tasks.audio.RunningMode AudioData = mp.tasks.components.containers.AudioData options = AudioClassifierOptions( base_options=BaseOptions(model_asset_path="yamnet.tflite"), running_mode=AudioRunningMode.AUDIO_CLIPS, max_results=5, ) audio_data = AudioData.create_from_array(clip_samples, sample_rate=16000) with AudioClassifier.create_from_options(options) as classifier: # Synchronous: returns timestamped results for every window across the clip result_list = classifier.classify(audio_data)
Audio stream
import mediapipe as mp BaseOptions = mp.tasks.BaseOptions AudioClassifier = mp.tasks.audio.AudioClassifier AudioClassifierOptions = mp.tasks.audio.AudioClassifierOptions AudioRunningMode = mp.tasks.audio.RunningMode AudioData = mp.tasks.components.containers.AudioData def on_result(result, timestamp_ms: int): print(result.classifications[0].categories) options = AudioClassifierOptions( base_options=BaseOptions(model_asset_path="yamnet.tflite"), running_mode=AudioRunningMode.AUDIO_STREAM, max_results=5, result_callback=on_result, ) with AudioClassifier.create_from_options(options) as classifier: # Async: accumulates contiguous PCM blocks into spectrogram windows audio_data = AudioData.create_from_array(pcm_chunk, sample_rate=16000) classifier.classify_async(audio_data, timestamp_ms)
Task details
This section describes the capabilities, inputs, outputs, and configuration options of this task.
Features
- Input audio processing - Processing includes audio resampling, buffering, framing, and fourier transform.
- Label map locale - Set the language used for display names
- Score threshold - Filter results based on prediction scores.
- Top-k classification - Limit the number of classification results.
- Label allowlist and denylist - Specify the categories detected.
- Audio clips
- Audio stream
See Prepare audio input data for AudioData, AudioRecord, and PCM buffer examples.
- Category index: the index of the category in the model outputs
- Score: the confidence score for this category, usually a probability in [0,1]
- Category name (optional): the name of the category as specified in the LiteRT model metadata, if available
- Category display name (optional): a display name for the category as specified in the LiteRT model metadata, in the language specified through display names locale options, if available
Configuration options
This task has the following configuration options:
Web
| Option Name | Description | Value Range | Default Value |
|---|---|---|---|
runningMode |
Sets the running mode for the task:AUDIO_CLIPS: Independent audio clips.AUDIO_STREAM: Continuous audio stream. |
{AUDIO_CLIPS, AUDIO_STREAM} |
AUDIO_CLIPS |
displayNamesLocale |
Locale code for display names provided in the model metadata, if available. You can add localized labels to custom models with the LiteRT Metadata Writer API. | Locale code | "en" |
maxResults |
Maximum number of top-scored classification results to return (-1 returns all results). |
Integer | -1 |
scoreThreshold |
Prediction score threshold overriding the model metadata default. Classifications lower than this score are rejected. | Float [0.0, 1.0] |
Not set |
categoryAllowlist |
Optional list of allowed category names. Mutually exclusive with categoryDenylist. |
List of strings | Not set |
categoryDenylist |
Optional list of excluded category names. Mutually exclusive with categoryAllowlist. |
List of strings | Not set |
Android
| Option Name | Description | Value Range | Default Value |
|---|---|---|---|
runningMode |
Sets the running mode for the task:AUDIO_CLIPS: Independent audio clips.AUDIO_STREAM: Continuous audio livestream with asynchronous callback/delegate. |
{AUDIO_CLIPS, AUDIO_STREAM} |
AUDIO_CLIPS |
displayNamesLocale |
Locale code for display names provided in the model metadata, if available. You can add localized labels to custom models with the LiteRT Metadata Writer API. | Locale code | "en" |
maxResults |
Maximum number of top-scored classification results to return (-1 returns all results). |
Integer | -1 |
scoreThreshold |
Prediction score threshold overriding the model metadata default. Classifications lower than this score are rejected. | Float [0.0, 1.0] |
Not set |
categoryAllowlist |
Optional list of allowed category names. Mutually exclusive with categoryDenylist. |
List of strings | Not set |
categoryDenylist |
Optional list of excluded category names. Mutually exclusive with categoryAllowlist. |
List of strings | Not set |
resultListener |
Asynchronous callback for AUDIO_STREAM mode results. |
OutputHandler.ResultListener<AudioClassifierResult, Long> |
Not set |
errorListener |
Optional error listener for AUDIO_STREAM mode. |
ErrorListener |
Not set |
iOS
| Option Name | Description | Value Range | Default Value |
|---|---|---|---|
runningMode |
Sets the running mode for the task:AUDIO_CLIPS: Independent audio clips.AUDIO_STREAM: Continuous audio livestream with asynchronous callback/delegate. |
{AUDIO_CLIPS, AUDIO_STREAM} |
AUDIO_CLIPS |
displayNamesLocale |
Locale code for display names provided in the model metadata, if available. You can add localized labels to custom models with the LiteRT Metadata Writer API. | Locale code | "en" |
maxResults |
Maximum number of top-scored classification results to return (-1 returns all results). |
Integer | -1 |
scoreThreshold |
Prediction score threshold overriding the model metadata default. Classifications lower than this score are rejected. | Float [0.0, 1.0] |
Not set |
categoryAllowlist |
Optional list of allowed category names. Mutually exclusive with categoryDenylist. |
List of strings | Not set |
categoryDenylist |
Optional list of excluded category names. Mutually exclusive with categoryAllowlist. |
List of strings | Not set |
audioClassifierStreamDelegate |
Asynchronous delegate for AUDIO_STREAM mode results (invoked on a serial background queue). |
AudioClassifierStreamDelegate |
Not set |
Python
| Option Name | Description | Value Range | Default Value |
|---|---|---|---|
running_mode |
Sets the running mode for the task:AUDIO_CLIPS: Independent audio clips.AUDIO_STREAM: Continuous audio livestream with result_callback. |
{AUDIO_CLIPS, AUDIO_STREAM} |
AUDIO_CLIPS |
display_names_locale |
Locale code for display names provided in the model metadata, if available. You can add localized labels to custom models with the LiteRT Metadata Writer API. | Locale code | "en" |
max_results |
Maximum number of top-scored classification results to return (-1 returns all results). |
Integer | -1 |
score_threshold |
Prediction score threshold overriding the model metadata default. Classifications lower than this score are rejected. | Float [0.0, 1.0] |
Not set |
category_allowlist |
Optional list of allowed category names. Mutually exclusive with category_denylist. |
List of strings | Not set |
category_denylist |
Optional list of excluded category names. Mutually exclusive with category_allowlist. |
List of strings | Not set |
result_callback |
Asynchronous callback function for AUDIO_STREAM mode results. |
Callable |
Not set |
Task output
Each AudioClassifierResult returns timestamped classification windows (for example, 975 ms YAMNet windows across an audio clip or stream):
| Field | Type / Range | Description |
|---|---|---|
timestampMs |
number (milliseconds) |
Start timestamp of the classified audio window (timestamp_ms in Python). |
classifications |
Classifications[] |
Per-head classification results (headIndex, headName, categories). |
categories |
Category[] (score in [0.0, 1.0]) |
Ranked acoustic event classes (categoryName, displayName, index, score). |
Example AudioClassifierResult payload
The following example shows the top acoustic event predictions for the first audio window (timestampMs: 0):
[
{
timestampMs: 0,
classifications: [
{
headIndex: 0,
categories: [
{ index: 0, score: 0.6000, categoryName: "Speech" },
{ index: 137, score: 0.2000, categoryName: "Music" }
]
}
]
}
]
Models
The Audio Classifier requires an audio classification model to be downloaded and stored in your project directory. Start with the default, recommended model for your target platform when you start developing with this task. The other available models typically make trade-offs between performance, accuracy, resolution, and resource requirements, and in some cases, include additional features.
Yamnet model (recommended)
The Yamnet model is an audio event classifier trained on the AudioSet dataset to predict audio events defined in the AudioSet data. For information on the audio events recognized by this model, see the model labels list.
| Model name | Input shape | Quantization type | Versions |
|---|---|---|---|
| YamNet | 1 x 15600 | None (float32) | Latest |
Task benchmarks
Here are the task benchmarks for the whole pipeline based on the preceding pre-trained models. The latency result is the average latency on Pixel 6 using CPU / GPU.
| Model name | Device | CPU latency | GPU latency |
|---|---|---|---|
| YamNet | Pixel 6 | 12.29ms | - |