คำแนะนำในการแยกประเภทเสียงสำหรับ Android

งาน MediaPipe Audio Classifier ช่วยคุณแยกประเภทข้อมูลเสียงได้ คุณสามารถใช้งานนี้เพื่อระบุกิจกรรมที่มีเสียงจากชุดหมวดหมู่ที่ฝึกแล้ว วิธีการเหล่านี้จะแสดงวิธีใช้ตัวแยกประเภทเสียงกับแอป 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 เพิ่มการอ้างอิงนี้ลงในไฟล์ build.gradle ของโปรเจ็กต์การพัฒนาแอป Android นำเข้าทรัพยากร Dependency ที่ต้องการด้วยโค้ดต่อไปนี้

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

รุ่น

งาน MediaPipe Audio Classifier ต้องใช้โมเดลที่ผ่านการฝึกซึ่งเข้ากันได้กับงานนี้ ดูข้อมูลเพิ่มเติมเกี่ยวกับโมเดลที่ผ่านการฝึกที่พร้อมใช้งานสำหรับตัวแยกประเภทเสียงได้ที่ภาพรวมงานส่วนโมเดล

เลือกและดาวน์โหลดโมเดล แล้วจัดเก็บไว้ในไดเรกทอรีโปรเจ็กต์ โดยทำดังนี้

<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 ตั้งค่าโหมดการทำงาน ตัวแยกประเภทเสียงมี 2 โหมด ดังนี้

AUDIO_CLIPS: โหมดสำหรับเรียกใช้งานเสียงในคลิปเสียงที่อิสระ

AUDIO_Stream: โหมดสำหรับการเรียกใช้งานเสียงในสตรีมเสียง เช่น จากไมโครโฟน ในโหมดนี้ ต้องมีการเรียกใช้ resultsListener เพื่อตั้งค่า Listener เพื่อรับผลการจัดประเภทแบบไม่พร้อมกัน
{AUDIO_CLIPS, AUDIO_STREAM} AUDIO_CLIPS
displayNamesLocale ตั้งค่าภาษาของป้ายกำกับที่จะใช้กับชื่อที่แสดงซึ่งระบุไว้ในข้อมูลเมตาของโมเดลของงาน หากมี ค่าเริ่มต้นคือ en สำหรับภาษาอังกฤษ คุณเพิ่มป้ายกำกับที่แปลเป็นภาษาท้องถิ่นลงในข้อมูลเมตาของโมเดลที่กำหนดเองได้โดยใช้ TensorFlow Lite Metadata Writer API รหัสภาษา en
maxResults ตั้งค่าจำนวนสูงสุดของผลลัพธ์การจัดประเภทที่มีคะแนนสูงสุด หากต้องการแสดงผล หาก < 0 ระบบจะแสดงผลทั้งหมดที่มี ตัวเลขจำนวนบวกใดก็ได้ -1
scoreThreshold ตั้งค่าเกณฑ์คะแนนการคาดการณ์ที่จะลบล้างเกณฑ์ที่ระบุไว้ในข้อมูลเมตาของโมเดล (หากมี) ผลลัพธ์ที่ต่ำกว่าค่านี้ถูกปฏิเสธ [0.0, 1.0] ไม่ได้ตั้งค่า
categoryAllowlist ตั้งค่ารายการตัวเลือกของชื่อหมวดหมู่ที่อนุญาต หากไม่ว่างเปล่า ผลลัพธ์การจัดประเภทที่ไม่มีชื่อหมวดหมู่ในชุดนี้จะถูกกรองออก ระบบจะไม่สนใจชื่อหมวดหมู่ที่ซ้ำกันหรือไม่รู้จัก ตัวเลือกนี้ใช้ด้วยกันกับ categoryDenylist ไม่ได้ และการใช้ทั้ง 2 รายการจะทำให้เกิดข้อผิดพลาด สตริงใดก็ได้ ไม่ได้ตั้งค่า
categoryDenylist ตั้งค่ารายการตัวเลือกของชื่อหมวดหมู่ที่ไม่ได้รับอนุญาต หากไม่ว่างเปล่า ผลลัพธ์การจัดประเภทซึ่งมีชื่อหมวดหมู่อยู่ในชุดนี้จะถูกกรองออก ระบบจะไม่สนใจชื่อหมวดหมู่ที่ซ้ำกันหรือไม่รู้จัก ตัวเลือกนี้ใช้ด้วยกันกับ categoryAllowlist ไม่ได้เลย และใช้ทั้ง 2 ผลลัพธ์เกิดข้อผิดพลาด สตริงใดก็ได้ ไม่ได้ตั้งค่า
resultListener ตั้งค่า Listener ผลลัพธ์เพื่อรับผลการจัดประเภทแบบไม่พร้อมกันเมื่อตัวแยกประเภทเสียงอยู่ในโหมดสตรีมเสียง ใช้ได้เมื่อตั้งค่าโหมดการทำงานเป็น AUDIO_STREAM เท่านั้น ไม่มีข้อมูล ไม่ได้ตั้งค่า
errorListener ตั้งค่า Listener ข้อผิดพลาดที่ไม่บังคับ ไม่มีข้อมูล ไม่ได้ตั้งค่า

เตรียมข้อมูล

ตัวแยกประเภทเสียงใช้ได้กับคลิปเสียงและสตรีมเสียง โดยงานนี้จะจัดการกับการประมวลผลอินพุตข้อมูลล่วงหน้า ซึ่งรวมถึงการสุ่มตัวอย่างใหม่ การบัฟเฟอร์ และการจัดเฟรม อย่างไรก็ตาม คุณต้องแปลงข้อมูลเสียงที่ป้อนเป็นออบเจ็กต์ 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();
    

คุณดูตัวอย่างวิธีแสดงผลการจัดประเภทที่ได้จากงานนี้ได้ในคลาส ProbabilitiesAdapter ของตัวอย่างโค้ด