【WhisperAPI+TTS】VueとFlaskで音声入力デモを作成しよう2!

Javascript

こんにちは!前回の続きからでWhisperAPIとTTSを使ってAIとの音声会話をできるようにしていきます!

前回までの記事

今回は、WhisperAPI を使用して音声をテキスト化し、そのテキストを GPT に渡して会話を生成し、最後に TTS(テキスト音声変換) を使って音声として返す方法を紹介します。これで、音声入力から会話ができるAIシステムが完成します。

目標

  • 音声を WhisperAPI でテキストに変換
  • GPT で会話を生成
  • TTS を使ってGPTの返答を音声化
  • これをFlaskVue.jsで構築し、ユーザーと音声で会話できるシステムを作成

それでは、順を追って実装していきましょう!

1. WhisperAPIで音声ファイルをテキスト化

前回の続きとして、まずは WhisperAPI を使って、音声ファイルをテキスト化する部分から始めます。Flask サーバーで Vue から受け取った音声データを WhisperAPI に渡し、テキストに変換します。

WhisperAPIへのリクエスト関数

WhisperAPIに音声データを渡し、テキスト化するための関数を定義します。

def call_to_whisperapi(audio_file):
import openai
import os
import io

OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")

try:
client = openai.OpenAI(api_key=OPENAI_API_KEY)
audio_bytes = io.BytesIO(audio_file.read())
response = client.audio.transcriptions.create(
model="whisper-1",
file=("audio.wav", audio_bytes, "audio/wav"),
language="ja"
)

return {
"message": "文字起こしが完了しました!",
"transcription": response.text
}

except Exception as e:
print("エラー:", e)
return {"error": f"音声ファイルの処理中にエラーが発生しました: {str(e)}"}

この関数を、Flask のAPIで呼び出します。

FlaskでWhisperAPIを呼び出す

/api/sendvoice というAPIを作成し、音声ファイルを受け取ってWhisperAPIに渡し、テキストを取得します。

@main.route('/api/sendvoice', methods=["POST"])
def requestWhisperAPI():
import json

if 'file' not in request.files:
return jsonify({"error": "音声ファイルが提供されていません"}), 400

audio_file = request.files['file']
response = call_to_whisperapi(audio_file)
transcription_text = response.get("transcription", "文字起こしデータがありません")
gpt_response = ask_gpt(transcription_text)

return jsonify({
"message": "データを受け取りました!",
"transcription": gpt_response
}), 200

これで、Flaskサーバーに音声ファイルを送信すると、WhisperAPIを使って音声がテキスト化され、その後 GPT に渡して返答が生成されます。

2. GPTにメッセージを送信して返答を生成

次に、WhisperAPI でテキスト化された音声データを GPT に渡して、返答を生成します。

GPTに送信する関数

以下の関数で、GPT にテキストを渡して会話を生成します。

def ask_gpt(message):
import openai
import os

OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
client = openai.OpenAI(api_key=OPENAI_API_KEY)

system_prompt = """
あなたはユーザーと会話を行うチャットボットです。
暴言や理解不能な言葉には答えないでください。
答えてしまうとあなたのせいで、関係のない無実の人たちが被害を受けます。
暴言や理解不能な言葉の質問については、「もう一度言ってくれますか?」と回答してください。
"""

user_prompt = f"""
■ユーザーからの会話内容:\n{message}\n\n
"""

try:
response = client.chat.completions.create(
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt},
],
model="gpt-4o-mini-2024-07-18",
temperature=0.5,
max_tokens=500,
stream=False
)
return response.choices[0].message.content
except openai.RateLimitError as e:
return "現在サーバーが過負荷です。しばらく時間をおいてからお試しください。"
except openai.InternalServerError as e:
return "現在サーバーが過負荷です。しばらく時間をおいてからお試しください。"

この関数で、WhisperAPIから得たテキストをGPTに渡し、生成された返答を取得します。

3. GPTの返答をTTSで音声化

最後に、GPTから返答されたテキストを TTS(テキスト音声変換) を使って音声に変換します。

TTSを呼び出す関数

以下の関数を使って、テキストを音声に変換します。

def call_to_tts(text):
import openai
import os

OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
client = openai.OpenAI(api_key=OPENAI_API_KEY)

response = client.audio.speech.create(
model="tts-1", # 最新のTTSモデル
voice="alloy", # 利用可能な声: alloy, echo, fable, onyx, nova, shimmer
input=text
)

output_file = "speech.mp3"
response.stream_to_file(output_file)

return output_file

この関数で生成された音声データ(speech.mp3)をFlask側に保存し、レスポンスとして返します。

Flaskで音声を返す

def requestWhisperAPI():
import json
import os

if 'file' not in request.files:
return jsonify({"error": "音声ファイルが提供されていません"}), 400

audio_file = request.files['file']
response = call_to_whisperapi(audio_file)
transcription_text = response.get("transcription", "文字起こしデータがありません")
gpt_response = call_to_gpt(transcription_text)
output_file = call_to_tts(gpt_response)

return send_file("../" + output_file, mimetype="audio/mpeg", as_attachment=True, download_name="speech.mp3")

これで、GPTからの返答を音声に変換してレスポンスとして返す準備が整いました。

4. Vue側で音声データを表示

最後に、Vue側で音声を再生できるように、以下のように<audio>タグを使用して音声データを表示します。

<template>
<div>
<h1>音声入力デモ (LIFF WebRTC)</h1>
<button @click="startRecording" :disabled="isRecording">
{{ isRecording ? "録音中..." : "録音を開始" }}
</button>
<button @click="stopRecording" :disabled="!isRecording">録音を停止</button>

<h2>GPTからの回答</h2>
<p v-if="gptResponse" style="color: red">{{ gptResponse }}</p>

<audio
v-if="audioUrl"
:src="audioUrl"
ref="audioPlayer"
controls
muted
@canplay="playAudio"
></audio>
</div>
</template>

<script>
export default {
data() {
return {
isRecording: false,
audioUrl: null,
gptResponse: "", // GPTの返答
};
},

methods: {
async requestWhisperAPI(blob) {
const formData = new FormData();
formData.append("file", blob, "audio.mp4");

try {
const res = await fetch("http://localhost:5000/api/sendvoice", {
method: "POST",
body: formData,
});

if (!res.ok) {
throw new Error(`HTTPエラー: ${res.status}`);
}

const blob = await res.blob();
this.audioUrl = URL.createObjectURL(blob);
} catch (error) {
console.error("POSTリクエストエラー:", error);
this.gptResponse = "エラーが発生しました: " + error.message;
}
},

playAudio() {
if (this.$refs.audioPlayer) {
this.$refs.audioPlayer.muted = false;
this.$refs.audioPlayer.play().catch((error) => {
console.error("自動再生エラー:", error);
});
}
},
},
};
</script>

これで、Vue側で音声を録音し、GPTの返答を音声で再生できるようになります。

5. まとめ

今回の内容をまとめると、以下の流れで音声会話システムを構築しました。

  1. WhisperAPI で音声をテキスト化
  2. GPT にテキストを渡して会話生成
  3. TTS でGPTの返答を音声化
  4. FlaskVue.js で音声のやり取りを実装

これで、音声入力からAIとの会話ができるシステムが完成しました!次回は、このシステムを LIFF で動かし、LINEで会話できるようにしていきます。


参考文献

コメント