音声認識キャンペーンに参加!
音声認識エンジンを使って何かやってみませんか?みたいなキャンペーンをQiitaで開催されていて、AmiVoice APIという音声認識APIサービスの無料利用クーポンも振る舞われるとか。
面白そうなキャンペーンだけど、音声認識できたとして、さて何に使えば面白いかなー?
大好きなFF14の青魔法を詠唱してみよう!
身振り手振りで遊ぶゲームがあるんだから、声を出してもいいだろう。
大好きなFF14の青魔道士で、ボタンぽちーではなく、かっこ良く青魔法を詠唱し、その魔法でモンスターをやっつけたらカッコいいのではないか!
流れはこんな感じか?
青魔法をマイクでしゃべる > AmiVoice APIに送信 > 認識した文字を貼り付け
うむ、ゲームプレイ的には全く効率的とは思えないが、魔法詠唱できるのだから小さいことには目をつむろう
早速作ってみる!
言語:Python3.11
音声認識:AmiVoice API
音声入力:pyaudio
キーボード操作:pyautogui
特に問題なくpipでインストールできました。
300秒間待っていて、キーボードのEnterキーの入力をトリガーにマイクの録音を開始、
3秒間録音し、AmiVoice APIに送信して音声認識してもらう、
音声認識の結果テキストの前に、/blueaction
をつけて、貼り付けて、Enterを入力。
(結果テキストが青魔法だったら、ゲーム内で青魔法の詠唱が始まる)
ちょうど私のゲーム設定で、Enterキーを押すと、チャット入力できるようになるので、そこに青魔法を実行するコードを貼り付ける、という形にしました。
恥ずかしながら、参考にさせていただいた記事を丸っとパクッてます・・・
記事にもありましたが、マイクがindex何番かが結構曲者ですね。(地味にはまります)
コードはこちら(折り畳み)
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()
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()
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"]
import pyautogui
import pyperclip
def input_blue_spell(txt):
pyperclip.copy('/blueaction ' + txt)
pyautogui.hotkey('ctrl', 'v')
pyautogui.hotkey('enter')
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」を指定した場合に限り、本ページで登録した単語が読み込まれ、音声認識に活用されます。
って書いてありました!
全然見てませんでした。申し訳ございません!
# リクエストのパラメータを設定
params = {
- "d": "-a-general"
+ "d": "-a-general-input"
}
これであなたも青魔道士!
ゲームプレイ的には、通常の操作で約2秒ごとに青魔法を発動できるのに対し、音声入力待ち3秒+通常の2秒で、5秒ごとの魔法発動で、全く役には立ちませんね。
参考にさせていただいた記事
全ては参考にさせていただいた皆様のおかげです!記事投稿ありがとうございます!