Android 向け音声分類ガイド

MediaPipe 音声分類タスクを使用すると、音声データの分類を行うことができます。このタスクを使用して、一連のトレーニング済みカテゴリからサウンドに関するイベントを特定できます。ここでは、Android アプリで音声分類を使用する方法について説明します。

このタスクの機能、モデル、構成オプションの詳細については、概要をご覧ください。

サンプルコード

MediaPipe Tasks のサンプルコードは、Android 用オーディオ分類アプリの簡単な実装です。この例では、物理的な Android デバイスのマイクを使用して、音声を継続的に分類します。また、デバイスに保存されている音声ファイルに対しても分類器を実行できます。

アプリは、独自の Android アプリの出発点として使用できます。または、既存のアプリを変更するときにアプリを参照できます。音声分類器のサンプルコードは GitHub でホストされています。

コードをダウンロードする

次の手順では、git コマンドライン ツールを使用してサンプルコードのローカルコピーを作成する方法を示します。

サンプルコードをダウンロードするには:

  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 の設定ガイドをご覧ください。

主要コンポーネント

次のファイルには、この音声分類サンプル アプリケーションの重要なコードが含まれています。

  • AudioClassifierHelper.kt - 音声分類を初期化し、モデルとデリゲートの選択を処理します。
  • RecorderFragment.kt - ライブ音声録音のユーザー インターフェースと制御コードを作成します。
  • LibraryFragment.kt - 音声ファイルを選択するためのユーザー インターフェースと制御コードを作成します。
  • ProbabilitiesAdapter.kt - 分類器の予測結果を処理し、フォーマットします。

セットアップ

このセクションでは、音声分類器を使用するための開発環境とコード プロジェクトをセットアップする主な手順について説明します。プラットフォームのバージョン要件など、MediaPipe タスクを使用するための開発環境の設定に関する一般的な情報については、Android の設定ガイドをご覧ください。

依存関係

音声分類は com.google.mediapipe:tasks-audio ライブラリを使用します。この依存関係を Android アプリ開発プロジェクトの build.gradle ファイルに追加します。次のコードを使用して、必要な依存関係をインポートします。

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);
    

音声分類サンプルコードを実装すると、ユーザーは処理モードを切り替えることができます。このアプローチでは、タスク作成コードが複雑になり、実際のユースケースには適さない可能性があります。モード切り替えのコードは、AudioClassifierHelperinitClassifier() 関数で確認できます。

構成オプション

このタスクには、Android アプリ用に次の構成オプションがあります。

オプション名 説明 値の範囲 デフォルト値
runningMode タスクの実行モードを設定します。音声分類には 2 つのモードがあります。

AUDIO_CLIPS: 独立した音声クリップに対して音声タスクを実行するモード。

AUDIO_STREAM: マイクからなど、音声ストリームで音声タスクを実行するモード。このモードでは、resultListener を呼び出してリスナーを設定し、分類結果を非同期で受信する必要があります。
{AUDIO_CLIPS, AUDIO_STREAM} AUDIO_CLIPS
displayNamesLocale タスクのモデルのメタデータで提供される表示名に使用するラベルの言語を設定します(利用可能な場合)。英語の場合、デフォルトは en です。TensorFlow Lite Metadata Writer API を使用して、カスタムモデルのメタデータにローカライズされたラベルを追加できます。言語 / 地域コード en
maxResults 返されるトップスコアの分類結果の最大数を設定します(省略可)。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 アプリでは、このタスクは、カテゴリラベルと信頼スコアを含むオーディオ イベントの予測を表す AudioClassifierResult オブジェクトのリストを含む ClassificationResult を返します。

音声クリップ

// 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();
    

このタスクから返された分類結果を表示する方法の例については、コードサンプルProbabilitiesAdapter クラスをご覧ください。