Przewodnik po klasyfikacji audio w Androidzie

Zadanie MediaPipe Audio Classifier umożliwia klasyfikację danych audio. Możesz użyć tego zadania do identyfikowania zdarzeń dźwiękowych z zestawu nauczonych kategorii. Z tych instrukcji dowiesz się, jak używać Klasyfikatora dźwięku w aplikacjach na Androida.

Więcej informacji o możliwościach, modelach i opcjach konfiguracji tego zadania znajdziesz w sekcji Omówienie.

Przykładowy kod

Przykładowy kod zadań MediaPipe Tasks to prosta implementacja aplikacji Audio Classifier na Androida. W przykładzie użyto mikrofonu w fizycznym urządzeniu z Androidem, żeby stale klasyfikować dźwięki, a także uruchomić klasyfikator na plikach dźwiękowych przechowywanych na urządzeniu.

Możesz użyć aplikacji jako punktu wyjścia dla własnej aplikacji na Androida lub skorzystać z niej podczas modyfikowania istniejącej aplikacji. Przykładowy kod Klasyfikatora dźwięku jest hostowany na GitHub.

Pobieranie kodu

Z instrukcji poniżej dowiesz się, jak utworzyć lokalną kopię przykładowego kodu za pomocą narzędzia wiersza poleceń git.

Aby pobrać przykładowy kod:

  1. Sklonuj repozytorium git za pomocą tego polecenia:
    git clone https://github.com/google-ai-edge/mediapipe-samples
    
  2. Opcjonalnie skonfiguruj instancję git tak, aby używała rozproszonego procesu płatności, aby mieć tylko pliki dla przykładowej aplikacji Audio Classifier:
    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/audio_classifier/android
    

Po utworzeniu lokalnej wersji przykładowego kodu możesz zaimportować projekt do Android Studio i uruchomić aplikację. Instrukcje znajdziesz w przewodniku konfiguracji na Androida.

Kluczowe elementy

Te pliki zawierają kluczowy kod tej przykładowej aplikacji do klasyfikacji audio:

Konfiguracja

W tej sekcji znajdziesz opis kluczowych kroków, które należy wykonać, aby skonfigurować środowisko programistyczne i projektować kodowanie na potrzeby Klasyfikatora audio. Ogólne informacje o konfigurowaniu środowiska programistycznego na potrzeby zadań MediaPipe, w tym o wymaganiach dotyczących wersji platformy, znajdziesz w przewodniku konfiguracji na Androida.

Zależności

Klasyfikator audio korzysta z biblioteki com.google.mediapipe:tasks-audio. Dodaj tę zależność do pliku build.gradle swojego projektu na Androida. Zaimportuj wymagane zależności za pomocą tego kodu:

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

Model

Zadanie MediaPipe Audio Classifier wymaga wytrenowanego modelu zgodnego z tym zadaniem. Więcej informacji o dostępnych wytrenowanych modelach Klasyfikatora dźwięku znajdziesz w sekcji poświęconej modelom na temat zadań.

Wybierz i pobierz model, a następnie zapisz go w katalogu projektu:

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

Aby określić ścieżkę używaną przez model, użyj metody BaseOptions.Builder.setModelAssetPath(). Tę metodę omówimy w przykładowym kodzie w następnej sekcji.

W przykładowym kodzie Klasyfikatora dźwięku model jest zdefiniowany w pliku AudioClassifierHelper.kt.

Tworzenie zadania

Aby utworzyć zadanie, możesz użyć funkcji createFromOptions. Funkcja createFromOptions akceptuje opcje konfiguracji, w tym tryb działania, język wyświetlanych nazw, maksymalną liczbę wyników, próg ufności oraz listę dozwolonych kategorii lub listę odrzuconych. Więcej informacji o opcjach konfiguracji znajdziesz w artykule Omówienie konfiguracji.

Zadanie Klasyfikator dźwięku obsługuje te typy danych wejściowych: klipy audio i strumienie audio. Przy tworzeniu zadania musisz określić tryb działania odpowiadający danemu wejściowemu. Wybierz kartę odpowiadającą typowi danych wejściowych, aby zobaczyć, jak utworzyć zadanie i uruchomić wnioskowanie.

Klipy audio

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

Strumień audio

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

Implementacja przykładowego kodu Klasyfikatora dźwięku pozwala użytkownikowi przełączać się między trybami przetwarzania. Takie podejście zwiększa złożoność kodu tworzenia zadania i może nie być odpowiednie w Twoim przypadku. Kod przełączania trybu znajdziesz w funkcji initClassifier() w AudioClassifierHelper.

Opcje konfiguracji

To zadanie ma te opcje konfiguracji aplikacji na Androida:

Nazwa opcji Opis Zakres wartości Wartość domyślna
runningMode Ustawia tryb działania zadania. Klasyfikator dźwięku ma 2 tryby:

AUDIO_CLIPS: tryb uruchamiania zadania dotyczącego dźwięku w niezależnych klipach audio.

AUDIO_STREAM: tryb uruchamiania zadania audio w strumieniu audio, np. z mikrofonu. W tym trybie należy wywołać funkcję resultListener, aby skonfigurować detektor umożliwiający asynchroniczne otrzymywanie wyników klasyfikacji.
{AUDIO_CLIPS, AUDIO_STREAM} AUDIO_CLIPS
displayNamesLocale Ustawia język etykiet, które mają być używane w przypadku nazw wyświetlanych w metadanych modelu zadania (jeśli są dostępne). Wartość domyślna w języku angielskim to en. Za pomocą TensorFlow Lite MetadataWriter API możesz dodawać zlokalizowane etykiety do metadanych modelu niestandardowego. Kod języka en
maxResults Określa opcjonalną maksymalną liczbę zwracanych wyników klasyfikacji o najwyższych wynikach. Jeśli wartość jest mniejsza niż 0, zostaną zwrócone wszystkie dostępne wyniki. Dowolne liczby dodatnie -1
scoreThreshold Ustawia próg wyniku prognozy, który zastępuje próg podany w metadanych modelu (jeśli istnieją). Wyniki poniżej tej wartości zostały odrzucone. [0,0; 1,0] Nie ustawiono
categoryAllowlist Ustawia opcjonalną listę dozwolonych nazw kategorii. Jeśli nie będzie pusty, wyniki klasyfikacji, których nazwy kategorii nie ma w tym zbiorze, zostaną odfiltrowane. Zduplikowane i nieznane nazwy kategorii są ignorowane. Ta opcja wzajemnie się wyklucza, categoryDenylist i ich użycie kończy się błędem. Dowolne ciągi Nie ustawiono
categoryDenylist Ustawia opcjonalną listę niedozwolonych nazw kategorii. Jeśli pole nie jest puste, wyniki klasyfikacji, których nazwa kategorii znajduje się w tym zbiorze, zostaną odfiltrowane. Zduplikowane i nieznane nazwy kategorii są ignorowane. Ta opcja wzajemnie się wyklucza z categoryAllowlist, a korzystanie z obu daje błąd. Dowolne ciągi Nie ustawiono
resultListener Ustawia detektor wyników, aby asynchronicznie otrzymywać wyniki klasyfikacji, gdy Klasyfikator dźwięku działa w trybie strumienia audio. Tego ustawienia można używać tylko wtedy, gdy tryb biegowy jest ustawiony na AUDIO_STREAM Nie dotyczy Nie ustawiono
errorListener Ustawia opcjonalny detektor błędów. Nie dotyczy Nie ustawiono

Przygotuj dane

Klasyfikator audio obsługuje klipy audio i strumienie audio. To zadanie obsługuje wstępne przetwarzanie danych wejściowych, w tym ponowne próbkowanie, buforowanie i kadrowanie. Musisz jednak przekonwertować wejściowe dane audio na obiekt com.google.mediapipe.tasks.components.containers.AudioData przed przekazaniem ich do zadania Klasyfikatora dźwięku.

Klipy audio

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

Strumień audio

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)
    

Uruchamianie zadania

Możesz wywołać funkcję classify odpowiadającą Twojemu trybowi biegowemu, aby aktywować wnioskowania. Interfejs Audio Classifier API zwraca możliwe kategorie zdarzeń audio rozpoznanych w wejściowych danych audio.

Klipy audio

AudioClassifierResult classifierResult = audioClassifier.classify(audioData);
    

Strumień audio

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

Uwaga:

  • Gdy działasz w trybie strumienia audio, musisz też podać dla zadania Klasyfikator dźwięku sygnaturę czasową służącą do śledzenia, jakie dane dźwiękowe w strumieniu zostały użyte do wnioskowania.
  • Gdy działa w modelu klipów audio, zadanie Klasyfikator dźwięku blokuje bieżący wątek, dopóki nie zakończy przetwarzania wejściowego dźwięku. Aby uniknąć blokowania odpowiedzi interfejsu, wykonaj przetwarzanie w wątku w tle.

Przykład uruchamiania Klasyfikatora dźwięku z klipami audio znajdziesz w klasie AudioClassifierHelper w przykładowym kodzie.

Obsługa i wyświetlanie wyników

Po uruchomieniu wnioskowania zadanie Klasyfikatora dźwięku zwraca listę możliwych kategorii zdarzeń audio w wejściowej ścieżce dźwiękowej. Na liście poniżej znajdziesz przykładowe dane wyjściowe z tego zadania:

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

W aplikacji na Androida zadanie zwraca wartość ClassificationResult, która zawiera listę obiektów AudioClassifierResult reprezentujących prognozy dotyczące zdarzenia audio, w tym etykietę kategorii i poziom ufności.

Klipy audio

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

Strumień audio

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

Przykład wyświetlania wyników klasyfikacji zwróconych przez to zadanie znajdziesz w klasie ProbabilitiesAdapter przykładowego kodu.