6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

音声認識APIを使ってみよう!

青魔法を詠唱して青魔法を詠唱してみた!

Last updated at Posted at 2024-05-12

音声認識キャンペーンに参加!

音声認識エンジンを使って何かやってみませんか?みたいなキャンペーンをQiitaで開催されていて、AmiVoice APIという音声認識APIサービスの無料利用クーポンも振る舞われるとか。
面白そうなキャンペーンだけど、音声認識できたとして、さて何に使えば面白いかなー?

大好きなFF14の青魔法を詠唱してみよう!

身振り手振りで遊ぶゲームがあるんだから、声を出してもいいだろう。
大好きなFF14の青魔道士で、ボタンぽちーではなく、かっこ良く青魔法を詠唱し、その魔法でモンスターをやっつけたらカッコいいのではないか!

流れはこんな感じか?
青魔法をマイクでしゃべる > AmiVoice APIに送信 > 認識した文字を貼り付け

うむ、ゲームプレイ的には全く効率的とは思えないが、魔法詠唱できるのだから小さいことには目をつむろう

早速作ってみる!

言語:Python3.11
音声認識:AmiVoice API
音声入力:pyaudio
キーボード操作:pyautogui
特に問題なくpipでインストールできました。

300秒間待っていて、キーボードのEnterキーの入力をトリガーにマイクの録音を開始、
3秒間録音し、AmiVoice APIに送信して音声認識してもらう、
音声認識の結果テキストの前に、/blueaction をつけて、貼り付けて、Enterを入力。
(結果テキストが青魔法だったら、ゲーム内で青魔法の詠唱が始まる)

ちょうど私のゲーム設定で、Enterキーを押すと、チャット入力できるようになるので、そこに青魔法を実行するコードを貼り付ける、という形にしました。

恥ずかしながら、参考にさせていただいた記事を丸っとパクッてます・・・
記事にもありましたが、マイクがindex何番かが結構曲者ですね。(地味にはまります)

コードはこちら(折り畳み)
bluespell.py
from send_voice import send_voice
from input_key import input_blue_spell
from mic_audio import wait_key,record_and_save

def main():
    while 1:
        wait_key()
        record_and_save()
        spell=send_voice()
        input_blue_spell(str(spell))


if __name__ == '__main__':
    main()
mic_audio.py
import wave
import time

import pyaudio
import keyboard
import atexit
import sys

FORMAT        = pyaudio.paInt16
TIME          = 3           # 録音時間[s]
SAMPLE_RATE   = 44100        # サンプリングレート
FRAME_SIZE    = 1024         # フレームサイズ
CHANNELS      = 1            # モノラルかバイラルか
INPUT_DEVICE_INDEX = 1       # マイクのチャンネル
NUM_OF_LOOP   = int(SAMPLE_RATE / FRAME_SIZE * TIME)

WAV_FILE = "./output.wav"


def cleanup():
    print('cleanup')

atexit.register(cleanup)

def wait_key():
    waittime = 300
    endtime = time.time() + waittime
    zt = endtime - time.time()

    while zt > 0:
        zt = endtime - time.time()
        print(f"waittime={int(zt)}",end="\r")
        if keyboard.is_pressed('enter'):
            print("Enterキーが押されました")
            break
        if keyboard.is_pressed('q'):
            print("qキーが押されましたq")
            sys.exit()

def record_and_save():
    """
    デバイスから出力される音声の録音をする
    """
    pa = pyaudio.PyAudio()

    stream = pa.open(format   = FORMAT,
                     channels = CHANNELS,
                     rate     = SAMPLE_RATE,
                     input    = True,
                     input_device_index = INPUT_DEVICE_INDEX,
                     frames_per_buffer  = FRAME_SIZE)

    print("RECORDING...")

    list_frame = []


    for i in range(NUM_OF_LOOP):
        data = stream.read(FRAME_SIZE)
        list_frame.append(data)

    print("RECORDING DONE!")

    stream.stop_stream()
    stream.close()
    pa.terminate()


    wf = wave.open(WAV_FILE, 'wb')
    wf.setnchannels(CHANNELS)
    wf.setsampwidth(pa.get_sample_size(FORMAT))
    wf.setframerate(SAMPLE_RATE)
    wf.writeframes(b''.join(list_frame))
    wf.close()

send_voice.py
import requests

def send_voice():
    # AmiVoiceのAPIキーを設定(マイページで確認できます)
    APP_KEY = "*****"

    # 認識対象の音声ファイルパス
    AUDIO_FILE = "output.wav"

    # エンドポイントのURL
    URL = "https://acp-api.amivoice.com/v1/recognize"

    # 音声ファイルを開く
    with open(AUDIO_FILE, "rb") as f:
        audio_data = f.read()

    # リクエストのパラメータを設定
    params = {
        "d": "-a-general"
    }
    files = {
        "u": (None, APP_KEY),
        "a": (AUDIO_FILE, audio_data)
    }

    # POSTリクエストを送信
    response = requests.post(URL, params=params, files=files)

    # レスポンスを処理
    if response.status_code == 200:
        result = response.json()
        print("認識結果:", result["text"])
    else:
        print("エラー:", response.status_code, response.text)
    
    return result["text"]
input_key.py
import pyautogui
import pyperclip

def input_blue_spell(txt):
    pyperclip.copy('/blueaction ' + txt)
    pyautogui.hotkey('ctrl', 'v')
    pyautogui.hotkey('enter')
mc_check.py
import pyaudio

pa = pyaudio.PyAudio()

for i in range(pa.get_device_count()):
    device_info = pa.get_device_info_by_index(i)
    print(device_info)
pa.terminate()

動かしてみた!

さぁマイクに向かって水鉄砲としゃべるんだ!


・・
・・・たどたどしすぎるのか、認識率がいまいち。マイクの調整不足かもしれない。
大人の本気を見せてやろう!

結構青魔法が発動しているのではないでしょうか。
実は青魔道士の超硬化ホワイトウィンドなども使いたかったのですが、音声認識を通すと、超高価ホワイトウインドウというような具合に認識され、うまく行きませんでした。恐らく、日常でよく使いそうな文字列が優先されるのかな?と感じました。
辞書登録もしてみたのですが、超硬化はうまくいきませんでしたねー。
なので動画では、うまくいきそうな青魔法を選んでマイク入力しています。

2024/05/13追記
AMIVOICE_APIをエンジンを、うっかり”会話_汎用”を選択していました。
”音声入力_汎用”にすると、超硬化を詠唱できたのかもしれません!
AMIVOICEさん疑ってごめんなさい(やり直す元気はないですが)

2024/06/04追記
今ぼんやり見てたら、単語登録の画面に

セッション接続時に「profileId」の値に「サービスID」を指定した場合に限り、本ページで登録した単語が読み込まれ、音声認識に活用されます。

って書いてありました!
全然見てませんでした。申し訳ございません!

send_voice.py
    # リクエストのパラメータを設定
    params = {
-        "d": "-a-general"
+        "d": "-a-general-input"
    }

これであなたも青魔道士!

ゲームプレイ的には、通常の操作で約2秒ごとに青魔法を発動できるのに対し、音声入力待ち3秒+通常の2秒で、5秒ごとの魔法発動で、全く役には立ちませんね。

参考にさせていただいた記事

全ては参考にさせていただいた皆様のおかげです!記事投稿ありがとうございます!

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?