📌

GPT-4/音声/画像/動画対応!Python Flask で作る AI チャット!

に公開

1. はじめに

Python と Flask を使って、テキストチャットだけでなく音声・画像・動画にも対応した多機能 AI バックエンド開発に取り組みました。この記事では、Python で構築した 多機能 AI チャットバックエンド を紹介します。マルチモーダル入力/出力に対応しており、似たようなバックエンド開発時に少しでもお役立ちいただければ幸いです。

GitHub リポジトリ: https://github.com/cmc-labo/flask-ai-chat

2. プロジェクト概要

このバックエンドでできること:

  • テキストチャット(GPT-3.5 / GPT-4o-mini)
  • テキスト → 音声生成(TTS)+リップシンク用データ生成
  • 音声入力 → テキスト変換 → 応答(Whisper + GPT)
  • 画像生成(Replicate API / Google Imagen-4)
  • 画像理解(GPT-4o-mini による質問応答)
  • 短編動画生成(RunwayML gen4_turbo)

フロントエンドは Flutter や iOS/Android アプリから呼び出して利用いただけます。

3. 実際の動作例

3.1 /chat の例 (テキストチャット)

curl -X POST http://127.0.0.1:5000/chat \
  -H "Content-Type: application/json" \
  -d '{"user_id": "12345", "message": "おはよう!"}'

Response:

{
  "reply": "おはようございます!元気ですか?何かお手伝いできることがありますか?"
}

3.2 /avatar の例 (テキスト → 音声生成(TTS)+リップシンク用データ生成)

curl -X POST http://127.0.0.1:5000/avatar \
  -H "Content-Type: application/json" \
  -d '{"text": "おはよう!"}'

Response:

{
  "text": "おはようございます!今日も頑張りましょう!",
  "audio_url": "http://127.0.0.1:5000/audio/output_12345abcd.wav",
  "lip_sync": [0.0, 0.12, 0.24, ...]
}

3.3 /understand_audio の例 (音声入力 → テキスト変換 → 応答(Whisper + GPT))

curl -X POST http://127.0.0.1:5000/understand_audio \
  -H "Content-Type: application/json" \
  -d '{
        "audio_url": "https://hpscript.s3.ap-northeast-1.amazonaws.com/voice.wav"
      }'

Response:

{"transcript": "AIチャットでよく聞かれることは何ですか?", "answer": "AIチャットでよく聞かれることはいくつかありますが、以下のような質問が一般的です。\n\n1. **情報提供**:\n   - 歴史的な出来事や文化に関する質問\n   - 科学や技術に関する基本的な情報\n\n2. **助言や提案**:\n   - 健康や生活に関するアドバイス\n   - 学習方法やキャリアに関する相談\n\n3. **トラブルシューティング**:\n   - コンピュータやソフトウェアの問題解決\n   - 日常生活でのトラブルへの対処法\n\n4. **エンターテイメント**:\n   - 映画や本のおすすめ\n   - ジョークやクイズ\n\n5. **雑学や豆知識**:\n   - 面白い事実や trivia\n   - 特定のテーマに関する詳細\n\n6. **技術的な質問**:\n   - プログラミングやコンピュータサイエンスに関する質問\n   - AIや機械学習の仕組み\n\nこれらの質問に対して、できる限り正確かつ詳細な情報を提供することが求められます。", "metadata": {"model": "gpt-4o-mini", "created": "20250824032605"}}

3.4 /generate_image の例 (画像生成)

curl -X POST http://127.0.0.1:5000/generate_image \
  -H "Content-Type: application/json" \
  -d '{"prompt": "an astronaut riding a horse on mars, hd, dramatic lighting"}'

Response

{
  "prompt": "an astronaut riding a horse on mars, hd, dramatic lighting",
  "image_url": "http://127.0.0.1:5000/image/image_20250823034938.png",
  "metadata": {
    "model": "google/imagen-4",
    "created": "20250823034938"
  }
}

3.5 /understand_image の例 (画像理解)

curl -X POST http://127.0.0.1:5000/understand_image \
  -H "Content-Type: application/json" \
  -d '{
        "question": "この犬の犬種は何ですか?",
        "image_url": "https://hpscript.s3.ap-northeast-1.amazonaws.com/dog.jpg"
      }'

Response

{
  "question": "この犬の犬種は何ですか?",
  "answer": "この犬はアラスカン・マラミュートという犬種のようです。大型で力強い犬で、主にそり引きとして飼育されています。特徴的な毛色と穏やかな性格が魅力です。",
  "metadata": {
    "model": "gpt-4o-mini",
    "created": "20250824022922"
  }
}

3.6 /generate_video の例 (動画生成)

curl -X POST http://127.0.0.1:5000/generate_video \
  -H "Content-Type: application/json" \
  -d '{
        "prompt": "宇宙船が飛ぶ街",
        "prompt_image": "https://hpscript.s3.ap-northeast-1.amazonaws.com/space.jpg",
        "duration": 5
      }'

Response

{
  "prompt": "宇宙船が飛ぶ街",
  "video_url": "http://127.0.0.1:5000/video/video_20250823181941.mp4",
  "metadata": {
    "model": "gen4_turbo",
    "duration": 5,
    "created": "20250823181941"
  }
}

4. 環境構築とセットアップ

4.1 必要ライブラリ

python3 -m venv venv
source venv/bin/activate
pip install flask psycopg2-binary openai python-dotenv gTTS pydub numpy replicate runwayml

4.2 環境変数設定

テキスト・音声・画像・動画の生成AI APIを利用するために、openai、replicate, runwayでのアカウント登録を行います。
.envファイル例

DB_NAME=postgres
DB_USER=postgres
DB_PASSWORD=hoge
DB_HOST=localhost
DB_PORT=5432
OPENAI_API_KEY=your_openai_api_key
REPLICATE_API_TOKEN=your_replicate_token
RUNWAY_API_KEY=your_runway_api_key

4.3 データベース作成(PostgreSQL)

CREATE TABLE chat_messages (
    id SERIAL PRIMARY KEY,
    user_id VARCHAR(50) NOT NULL,
    message TEXT NOT NULL,
    reply TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

4.4 サーバ起動

python3 app.py

5. 各APIの内部処理

5.1 /chat - テキストチャット

/chat のエンドポイントは「日常会話」「シンプルなQA」用途を想定しているので、gpt-3.5-turboを利用しています。gpt-3.5-turbo は 料金が最安 のモデルで、簡単な会話ボット用途では十分な精度を出せます。

  • GPT-3.5-turbo を使ってユーザー入力に応答
  • PostgreSQL にメッセージと応答を保存
completion = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": message}
    ]
)
reply_text = completion.choices[0].message.content

※gpt-4, gpt-4o, gpt-4.1 などは 数倍〜10倍以上の料金 がかかるため、トラフィックが多いチャットではコストが急増します。gpt-4o や gpt-4.1 は高性能ですが、安定運用を重視するシステムではまず 3.5 をベースにしておき、必要に応じて切り替える戦略を取っています。

5.2 /avatar - TTSによる音声生成 + リップシンク

ユーザー入力の受け取り音声データを作成します。「音声に合わせた口の動作制御」を リップシンク (Lip Sync) と呼び、口パクを実現するため、リップシンクデータをレスポンスとして返します。

  1. GPT で応答生成
  2. gTTS で日本語音声生成
    tts = gTTS(text=reply_text, lang='ja')
    audio_filename = os.path.join(AUDIO_DIR, f"output_{uuid.uuid4().hex}.mp3")
    tts.save(audio_filename)
  1. MP3 → WAV 変換
    wav_filename = audio_filename.replace(".mp3", ".wav")
    sound = AudioSegment.from_mp3(audio_filename)
    sound.export(wav_filename, format="wav")
  1. 音声振幅を計算してリップシンクデータを作成
    audio = AudioSegment.from_wav(wav_filename)
    samples = np.array(audio.get_array_of_samples())
    if audio.channels == 2:
        samples = samples.reshape((-1, 2)).mean(axis=1)
    samples = samples / np.max(np.abs(samples))  # Normalize

    fps = 30
    samples_per_frame = int(audio.frame_rate / fps)
    lip_sync = []
    for i in range(0, len(samples), samples_per_frame):
        frame = samples[i:i + samples_per_frame]
        lip_sync.append(float(np.abs(frame).mean()))
  1. 音声 URL とリップシンクデータを返却

※gTTSでは女性の声でやや機械的だけど聞き取りやすい音声が生成されます。gTTSではなく、例えば以下のようなサービスを使うと 声質の選択やより自然な音声が可能です。

  • OpenAI TTS (gpt-4o-mini-tts) → 高品質、複数声あり
  • Amazon Polly → 数十種類の声(男女、感情表現つき)
  • Google Cloud Text-to-Speech → WaveNet音声、より自然

(バックエンド) Python
├ 音声生成
├ 音声からリップシンクデータ生成
└ 音声ファイル + JSON (口形データ) を返す

(フロントエンド) Xcode (iOS/macOS)
├ アバター画像/3Dモデルを保持
├ JSON を読み込んでタイムライン制御
└ 音声と同期してアニメーション表示

5.3 /understand_audio - 音声理解

  • Whisper API で音声をテキストに変換
    OpenAIの Whisper API (whisper-1) を利用して音声をテキストに変換します。Whisperは多言語対応の音声認識モデルで、日本語や英語を自動判別して文字起こしします。
        audio_response = requests.get(audio_url)
        audio_path = "/tmp/temp_audio.wav"
        with open(audio_path, "wb") as f:
            f.write(audio_response.content)

        client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
        transcript_resp = client.audio.transcriptions.create(
            model="whisper-1",
            file=open(audio_path, "rb")
        )
        transcript = transcript_resp.text
  • GPT-4o-mini でテキストを理解して回答

Whisper 系モデル (例: whisper-1)は「音声認識 (ASR: Automatic Speech Recognition)」専門のモデルです。音声ファイル → テキストに変換するのが役割で、自然言語の理解や会話生成はしません。

5.4 /generate_image - 画像生成

  • Replicate API (Google Imagen-4) を使ってテキストプロンプトから画像生成
    内部的に大規模生成モデル(Google/Imagen-4)を利用しています。
        client = replicate.Client(api_token=REPLICATE_API_TOKEN)
        input_data = {
            "prompt": prompt,
            "aspect_ratio": "16:9",
            "safety_filter_level": "block_medium_and_above"
        }
        REPLICATE_MODEL = "google/imagen-4"
        output = client.run(REPLICATE_MODEL, input=input_data)
  • 生成された画像をサーバに保存して URL を返却

各サービスの画像生成のモデルを比較しました。

5.5 /understand_image - 画像理解

  • GPT-4o-mini に画像 URL と質問を渡して解析
        data = request.json
        image_url = data.get("image_url", "")
        if not image_url:
            return jsonify({"error": "Image URL is required"}), 400
        question = data.get("question", "この画像について説明してください。")

        client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
        response = client.chat.completions.create(
            model="gpt-4o-mini",
            messages=[
                {
                    "role": "user",
                    "content": [
                        {"type": "text", "text": question},
                        {"type": "image_url", "image_url": {"url": image_url}}
                    ]
                }
            ]
        )
  • 画像の内容について回答を取得

gpt-3.5-turbo はテキスト専用モデルで、画像を直接理解する機能はありません。一方、gpt-4o-mini は マルチモーダルGPT で、テキストと画像を同時に入力として理解できます。そのため、「画像を解析して説明する」という /understand_image の用途に適しています。GPT-4 系列(特に 4o-mini や 4o)の方が、複雑な文脈理解や説明能力が高く、より精度の高い回答が得られます。

5.6 /generate_video - 動画生成

  • RunwayML gen4_turbo を使って短編動画を生成
        task = client.image_to_video.create(
            model='gen4_turbo',
            prompt_text=prompt_text,
            prompt_image=prompt_image,  # None でも可
            ratio='1280:720',
            duration=duration
        ).wait_for_task_output()
  • テキストプロンプト+オプションで画像入力を指定可能
  • 動画ファイルを保存して URL を返却

パラメータ:
model='gen4_turbo':Runway の動画生成モデル
prompt_text:動画の説明文
prompt_image:オプションで指定した画像
ratio='1280:720':動画解像度
duration:秒単位の動画長さ
.wait_for_task_output() により、生成完了まで待機して結果を取得しています。

6. 今後の拡張

以下のような機能拡張を検討しております。

  • 長時間会話履歴の管理
  • キャラクター・音声のカスタマイズ
  • リアルタイムフロントエンドとの連携
  • 生成メディアの保存・ストリーミング改善

7. Frontend側の実装例

import SwiftUI

struct ContentView: View {
    @State private var userMessage: String = ""
    @State private var aiReply: String = ""
    
    var body: some View {
        VStack(spacing: 20) {
            Text("AI Chat Demo")
                .font(.title)
            
            TextField("メッセージを入力", text: $userMessage)
                            .textFieldStyle(RoundedBorderTextFieldStyle())
                            .padding()
            
            Button("送信") {
                sendMessage()
            }
            .padding()
            
            Text("AIの返答: \(aiReply)")
                .padding()
            
            Spacer()
        }
        .padding()
    }
    func sendMessage() {
        guard let url = URL(string: "http://192.168.33.10:5000/chat") else { return }
        
        let body: [String: Any] = [
            "user_id": "12345",
            "message": userMessage
        ]

        let jsonData = try? JSONSerialization.data(withJSONObject: body)
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = jsonData

        URLSession.shared.dataTask(with: request) {data, response, error in
            if let data = data {
                if let decoded = try? JSONDecoder().decode(ChatResponse.self, from: data) {
                                    DispatchQueue.main.async {
                                        self.aiReply = decoded.reply
                                    }
                                }
            }
        }.resume()
    }
}

struct ChatResponse: Codable {
    let reply: String
}

7. まとめ

今回紹介した「flask-ai-chat」では、Flask をベースに テキスト・音声・画像・動画といった複数モーダルを扱える AI チャットバックエンド を実装しました。

単なるテキストチャットにとどまらず、音声入力を文字起こしして対話に使ったり、テキストから自然な音声を生成したり、リップシンク用のデータを作成してアバターの口パクを制御したり、さらに画像や動画まで生成できるのは大きな特徴です。

また、利用するモデルも目的に応じて使い分けています。

  • gpt-3.5-turbo → 軽量で低コストなテキスト応答
  • gpt-4o-mini → マルチモーダル対応の高度な応答生成
  • whisper-1 → 高精度な音声認識
  • Replicate / RunwayML → 高品質な画像・動画生成

これらを Flask のエンドポイントごとに整理することで、バックエンドとしての拡張性・柔軟性を高めています。

このような構成は、教育アプリやカスタマーサポート、バーチャルアシスタント、エンタメコンテンツなど、多様な分野に応用可能と思われます。さらに、ユーザーの好みに合わせてキャラクターの声や見た目を変えることで、よりパーソナライズされた体験を提供することもできるかもしれません。

本記事とリポジトリのコードが、皆さんの AI サービス開発の参考になれば幸いです。

Discussion