AI音声認識をUnityで

UnityでAI音声認識

はじめに

このチュートリアルでは、Hugging Face Unity APIを使用してUnityゲームに最先端の音声認識を実装する方法を案内します。この機能は、コマンドの実行、NPCへの話しかけ、アクセシビリティの向上、音声をテキストに変換する必要がある他の機能など、さまざまな用途で使用することができます。

自分自身でUnityで音声認識を試してみるには、itch.ioでライブデモをチェックしてください。

前提条件

このチュートリアルでは、Unityの基本的な知識があることを前提としています。また、Hugging Face Unity APIをインストールしている必要があります。APIの設定手順については、以前のブログ記事を参照してください。

手順

1. シーンの設定

このチュートリアルでは、プレイヤーが録音を開始および停止でき、その結果がテキストに変換される非常にシンプルなシーンを設定します。

まず、Unityプロジェクトを作成し、次の4つのUI要素を持つキャンバスを作成します。

  1. 開始ボタン:録音を開始します。
  2. 停止ボタン:録音を停止します。
  3. テキスト(TextMeshPro):音声認識の結果が表示される場所です。

2. スクリプトの設定

SpeechRecognitionTestという名前のスクリプトを作成し、空のGameObjectにアタッチします。

スクリプト内で、UIコンポーネントへの参照を定義します。

[SerializeField] private Button startButton;
[SerializeField] private Button stopButton;
[SerializeField] private TextMeshProUGUI text;

インスペクターでそれらを割り当てます。

次に、Start()メソッドを使用して開始ボタンと停止ボタンのリスナーを設定します。

private void Start() {
    startButton.onClick.AddListener(StartRecording);
    stopButton.onClick.AddListener(StopRecording);
}

この時点で、スクリプトは次のようになります:

using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class SpeechRecognitionTest : MonoBehaviour {
    [SerializeField] private Button startButton;
    [SerializeField] private Button stopButton;
    [SerializeField] private TextMeshProUGUI text;

    private void Start() {
        startButton.onClick.AddListener(StartRecording);
        stopButton.onClick.AddListener(StopRecording);
    }

    private void StartRecording() {

    }

    private void StopRecording() {

    }
}

3. マイクの入力を録音する

さて、マイクの入力を録音し、WAV形式でエンコードしましょう。まず、メンバ変数を定義します:

private AudioClip clip;
private byte[] bytes;
private bool recording;

次に、StartRecording()内で、Microphone.Start()メソッドを使用して録音を開始します:

private void StartRecording() {
    clip = Microphone.Start(null, false, 10, 44100);
    recording = true;
}

これにより、44100 Hzで最大10秒間のオーディオが録音されます。

録音が最大長さの10秒に達した場合、録音を自動的に停止する必要があります。そのために、Update()メソッドに以下のコードを記述します:

private void Update() {
    if (recording && Microphone.GetPosition(null) >= clip.samples) {
        StopRecording();
    }
}

次に、StopRecording()内で、録音を切り詰めてWAV形式でエンコードします:

private void StopRecording() {
    var position = Microphone.GetPosition(null);
    Microphone.End(null);
    var samples = new float[position * clip.channels];
    clip.GetData(samples, 0);
    bytes = EncodeAsWAV(samples, clip.frequency, clip.channels);
    recording = false;
}

最後に、Hugging Face APIにオーディオデータを準備するために、EncodeAsWAV()メソッドを実装する必要があります:

private byte[] EncodeAsWAV(float[] samples, int frequency, int channels) {
    using (var memoryStream = new MemoryStream(44 + samples.Length * 2)) {
        using (var writer = new BinaryWriter(memoryStream)) {
            writer.Write("RIFF".ToCharArray());
            writer.Write(36 + samples.Length * 2);
            writer.Write("WAVE".ToCharArray());
            writer.Write("fmt ".ToCharArray());
            writer.Write(16);
            writer.Write((ushort)1);
            writer.Write((ushort)channels);
            writer.Write(frequency);
            writer.Write(frequency * channels * 2);
            writer.Write((ushort)(channels * 2));
            writer.Write((ushort)16);
            writer.Write("data".ToCharArray());
            writer.Write(samples.Length * 2);

            foreach (var sample in samples) {
                writer.Write((short)(sample * short.MaxValue));
            }
        }
        return memoryStream.ToArray();
    }
}

フルスクリプトは以下のようになるはずです:

using System.IO;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class SpeechRecognitionTest : MonoBehaviour {
    [SerializeField] private Button startButton;
    [SerializeField] private Button stopButton;
    [SerializeField] private TextMeshProUGUI text;

    private AudioClip clip;
    private byte[] bytes;
    private bool recording;

    private void Start() {
        startButton.onClick.AddListener(StartRecording);
        stopButton.onClick.AddListener(StopRecording);
    }

    private void Update() {
        if (recording && Microphone.GetPosition(null) >= clip.samples) {
            StopRecording();
        }
    }

    private void StartRecording() {
        clip = Microphone.Start(null, false, 10, 44100);
        recording = true;
    }

    private void StopRecording() {
        var position = Microphone.GetPosition(null);
        Microphone.End(null);
        var samples = new float[position * clip.channels];
        clip.GetData(samples, 0);
        bytes = EncodeAsWAV(samples, clip.frequency, clip.channels);
        recording = false;
    }

    private byte[] EncodeAsWAV(float[] samples, int frequency, int channels) {
        using (var memoryStream = new MemoryStream(44 + samples.Length * 2)) {
            using (var writer = new BinaryWriter(memoryStream)) {
                writer.Write("RIFF".ToCharArray());
                writer.Write(36 + samples.Length * 2);
                writer.Write("WAVE".ToCharArray());
                writer.Write("fmt ".ToCharArray());
                writer.Write(16);
                writer.Write((ushort)1);
                writer.Write((ushort)channels);
                writer.Write(frequency);
                writer.Write(frequency * channels * 2);
                writer.Write((ushort)(channels * 2));
                writer.Write((ushort)16);
                writer.Write("data".ToCharArray());
                writer.Write(samples.Length * 2);

                foreach (var sample in samples) {
                    writer.Write((short)(sample * short.MaxValue));
                }
            }
            return memoryStream.ToArray();
        }
    }
}

このコードが正しく動作しているかテストするために、StopRecording() メソッドの最後に以下の行を追加してください:

File.WriteAllBytes(Application.dataPath + "/test.wav", bytes);

これで、Start ボタンをクリックし、マイクに話しかけ、Stop ボタンをクリックすると、録音したオーディオが Unity Assets フォルダに test.wav というファイル名で保存されるはずです。

4.音声認識

次に、Hugging Face Unity API を使用してエンコードされたオーディオ上で音声認識を実行したいと思います。それには、SendRecording() メソッドを作成します:

using HuggingFace.API;

private void SendRecording() {
    HuggingFaceAPI.AutomaticSpeechRecognition(bytes, response => {
        text.color = Color.white;
        text.text = response;
    }, error => {
        text.color = Color.red;
        text.text = error;
    });
}

これにより、エンコードされたオーディオが API に送信され、成功した場合は白で応答が表示され、それ以外の場合は赤でエラーメッセージが表示されます。

StopRecording() メソッドの最後で SendRecording() を呼び出すことを忘れないでください:

private void StopRecording() {
    /* 他のコード */
    SendRecording();
}

5.最終的な修正

最後に、ボタンのインタラクティビティとステータスメッセージを使用して、このデモの UX を改善しましょう。

録音が開始/停止可能な場合、つまり録音の準備ができている場合にのみ、Start ボタンと Stop ボタンをインタラクティブにする必要があります。

次に、録音中または API の応答を待っている間に、レスポンステキストをシンプルなステータスメッセージに設定します。

完成したスクリプトは以下のようになります:

using System.IO;
using HuggingFace.API;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

public class SpeechRecognitionTest : MonoBehaviour {
    [SerializeField] private Button startButton;
    [SerializeField] private Button stopButton;
    [SerializeField] private TextMeshProUGUI text;

    private AudioClip clip;
    private byte[] bytes;
    private bool recording;

    private void Start() {
        startButton.onClick.AddListener(StartRecording);
        stopButton.onClick.AddListener(StopRecording);
        stopButton.interactable = false;
    }

    private void Update() {
        if (recording && Microphone.GetPosition(null) >= clip.samples) {
            StopRecording();
        }
    }

    private void StartRecording() {
        text.color = Color.white;
        text.text = "録音中...";
        startButton.interactable = false;
        stopButton.interactable = true;
        clip = Microphone.Start(null, false, 10, 44100);
        recording = true;
    }

    private void StopRecording() {
        var position = Microphone.GetPosition(null);
        Microphone.End(null);
        var samples = new float[position * clip.channels];
        clip.GetData(samples, 0);
        bytes = EncodeAsWAV(samples, clip.frequency, clip.channels);
        recording = false;
        SendRecording();
    }

    private void SendRecording() {
        text.color = Color.yellow;
        text.text = "送信中...";
        stopButton.interactable = false;
        HuggingFaceAPI.AutomaticSpeechRecognition(bytes, response => {
            text.color = Color.white;
            text.text = response;
            startButton.interactable = true;
        }, error => {
            text.color = Color.red;
            text.text = error;
            startButton.interactable = true;
        });
    }

    private byte[] EncodeAsWAV(float[] samples, int frequency, int channels) {
        using (var memoryStream = new MemoryStream(44 + samples.Length * 2)) {
            using (var writer = new BinaryWriter(memoryStream)) {
                writer.Write("RIFF".ToCharArray());
                writer.Write(36 + samples.Length * 2);
                writer.Write("WAVE".ToCharArray());
                writer.Write("fmt ".ToCharArray());
                writer.Write(16);
                writer.Write((ushort)1);
                writer.Write((ushort)channels);
                writer.Write(frequency);
                writer.Write(frequency * channels * 2);
                writer.Write((ushort)(channels * 2));
                writer.Write((ushort)16);
                writer.Write("data".ToCharArray());
                writer.Write(samples.Length * 2);

                foreach (var sample in samples) {
                    writer.Write((short)(sample * short.MaxValue));
                }
            }
            return memoryStream.ToArray();
        }
    }
}

おめでとうございます!Unityで最新の音声認識を使用できるようになりました!

質問がある場合やHugging Face for Gamesの利用に更に関わりたい場合は、Hugging Face Discordに参加してください!

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

人工知能

「UVeyeの共同設立者兼CEO、アミール・ヘヴェルについてのインタビューシリーズ」

アミール・ヘヴァーは、UVeyeのCEO兼共同創設者であり、高速かつ正確な異常検出により、自動車およびセキュリティ産業に直面...

人工知能

「マーク・A・レムリー教授による生成AIと法律について」

データサイエンス内で新しい分野が現れ、研究内容が理解しにくい場合は、専門家やパイオニアと話すことが最善です最近、私た...

人工知能

「LeanTaaSの創設者兼CEO、モハン・ギリダラダスによるインタビューシリーズ」

モーハン・ギリダラダスは、AIを活用したSaaSベースのキャパシティ管理、スタッフ配置、患者フローのソフトウェアを提供する...

人工知能

「マーシャンの共同創設者であるイータン・ギンスバーグについてのインタビューシリーズ」

エタン・ギンズバーグは、マーシャンの共同創業者であり、すべてのプロンプトを最適なLLMに動的にルーティングするプラットフ...

人工知能

Aaron Lee、Smith.aiの共同設立者兼CEO - インタビューシリーズ

アーロン・リーさんは、Smith.aiの共同創業者兼CEOであり、AIと人間の知性を組み合わせて、24時間365日の顧客エンゲージメン...

人工知能

『ジュリエット・パウエル&アート・クライナー、The AI Dilemma – インタビューシリーズの著者』

『AIのジレンマ』は、ジュリエット・パウエルとアート・クライナーによって書かれましたジュリエット・パウエルは、著者であ...