AIマルチモーダル

AIは話すだけでなく、画像を見たり、音声を聞いたり、動画を理解したりできます——マルチモーダルツールと技術をマスターしましょう。

長い間、AIは単一の感覚しか持っていませんでした。

  • テキストAIはテキストしか処理できません。例えばChatGPTに文章を書かせることができます。

  • 画像AIは画像しか処理できません。例えばMidjourneyに絵を描かせることができます。

  • 音声AIは音だけを処理できます。例えばWhisperに音声を書き起こさせることができます。

しかし現実世界はマルチモーダルです。本を読むときは挿絵を見、映画を見るときは映像と音声があり、人と交流するときは表情や口調を観察します。

マルチモーダルAIとは、複数種類のコンテンツを同時に理解し生成できるAIです。これはAIに目と耳と口を備え付けるようなもので、より人間に近い方法で世界と対話できるようにします。

実用的な例:AIにレシートの写真を見せると、文字(OCR)を認識し、購入した商品を理解し、表に整理し、音声で読み上げてくれます。これが典型的なマルチモーダルタスクです。


マルチモーダルAIとは

まず、いくつかの基本概念を明確にしましょう。

単一モーダル vs マルチモーダル

モーダル(Modality)とは、情報の表現形式を指します。

テキスト、画像、音声、動画、これらはすべて異なるモーダルです。

種類説明代表的な製品
単一モーダルAI1つのモーダルしか処理できない初期のGPT-3(テキストのみ)、Stable Diffusion(画像のみ)
マルチモーダルAI複数のモーダルを同時に処理できるGPT-4o、Claude 3、Gemini

マルチモーダルAIの核心的なブレークスルーは次の通りです:異なるモーダルの情報を同じ言語に変換して理解できることです。。

例えば、「猫」の画像を見ると、画像をベクトル(数値の集合)に変換でき、「猫」という文字もベクトルに変換できます。この2つのベクトルは数学空間では近くにあります。なぜなら、同じ概念を表しているからです。

マルチモーダルの核心的な課題

マルチモーダルは簡単そうに聞こえますが、実際には非常に難しいです。

  • 最初の課題は「アライメント」です。画像の中の「猫」とテキストの中の「猫」をモデルが同じものとして見なすにはどうすればよいか?

  • 2番目の課題は「融合」です。画像とテキストを同時に見たとき、それらの情報をどのように組み合わせるか?

  • 3番目の課題は「生成」です。テキストの説明に基づいて画像を生成する、または画像に基づいてテキストの説明を生成するにはどうすればよいか?

  • 幸いなことに、これらの問題は徐々に解決されつつあります。2024年以降の主流の大規模モデルは、ほとんどすべてマルチモーダルです。


画像理解(ビジョン)

画像理解とは、AIに画像を理解させることです。内容の説明、文字の認識、グラフの分析、細部の発見などです。

主流の大規模モデルはすべて画像入力をサポートしています。

使用方法は通常2つあります:

  • 1つは画像ファイルを直接アップロードする方法です。例えばChatGPTのWeb版で画像アイコンをクリックしてアップロードします。

  • もう1つは、Base64エンコードを使用して画像をAPIリクエストに埋め込む方法で、プログラムからの呼び出しに適しています。

モデル画像入力方法対応する画像フォーマット
GPTURL、Base64、直接アップロードJPG、PNG、WEBP、GIF
ClaudeBase64、直接アップロードJPG、PNG、WEBP、GIF
Gemini直接アップロード、Google DriveJPG、PNG、WEBP

一般的なビジョンタスクには次のものがあります:

  • 画像記述 — この画像には何がある?

  • OCR — 画像内のテキストを抽出する。

  • グラフ分析 — この棒グラフは何を言っているか?

  • 細部の発見 — このデザイン案に問題がないかチェックしてください。

実践:PythonでGPT-4o Vision APIを呼び出す

完全な例を見てみましょう。APIを使って画像を分析します。

例

# ============================================
# ファイル:サンプル_vision_demo.py
# 機能:GPT-4o Vision APIを使用して画像を分析
# ============================================

import base64
import requests
import os

# APIキーを設定(実際のキーに置き換えてください)
# 取得先:https://platform.openai.com/api-keys
OPENAI_API_KEY = "sk-your-api-key-here"
OPENAI_API_URL = "https://api.openai.com/v1/chat/completions"


def encode_image_to_base64(image_path: str) -> str:
    """
ローカル画像ファイルをBase64文字列にエンコードする
これはAPIが要求する転送フォーマットです
    """

    with open(image_path, "rb") as image_file:
        # バイナリファイルの内容を読み込み、Base64でエンコード
        base64_data = base64.b64encode(image_file.read()).decode("utf-8")
        return base64_data


def analyze_image_with_gpt4o(
    image_path: str,
    prompt: str = "この画像の内容を詳しく説明してください",
    model: str = "gpt-4o"
) -> str:
    """
GPT-4o Vision APIを使用して画像を分析

パラメータ説明:
image_path: ローカル画像ファイルのパス(例:"サンプル_test.jpg")
prompt: 質問したい内容やAIにさせたいタスク
model: 使用するモデル名(デフォルトはgpt-4o)

戻り値:
AIの分析結果テキスト
    """

    # 手順1:画像をBase64にエンコード
    base64_image = encode_image_to_base64(image_path)

    # 手順2:リクエストヘッダーを作成
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {OPENAI_API_KEY}"
    }

    # 手順3:リクエストボディを作成
    # 注意:画像コンテンツはimage_urlフィールドで渡され、形式は "data:image/jpeg;base64,..." です。
    payload = {
        "model": model,
        "messages": [
            {
                "role": "user",
                "content": [
                    # 最初の部分はテキストプロンプト
                    {"type": "text", "text": prompt},
                    # 2番目の部分は画像
                    {
                        "type": "image_url",
                        "image_url": {
                            "url": f"data:image/jpeg;base64,{base64_image}"
                        }
                    }
                ]
            }
        ],
        "max_tokens": 1000  # 出力長を制御して、コストが高くなりすぎるのを防ぐ
    }

    # 手順4:APIリクエストを送信
    print(f"画像を分析中:{image_path} ...")
    response = requests.post(OPENAI_API_URL, headers=headers, json=payload)

    # 手順5:レスポンスを処理
    if response.status_code == 200:
        result = response.json()
        # AIの回答を抽出
        answer = result["choices"][0]["message"]["content"]
        return answer
    else:
        # エラー時に詳細情報を出力
        error_msg = f"リクエスト失敗:{response.status_code} - {response.text}"
        print(error_msg)
        return error_msg


def extract_text_from_image(image_path: str) -> str:
    """
OCR専用:画像内のテキストを抽出
    """

    prompt = """
この画像内のすべてのテキストを抽出してください。
要件:
1. テキストを正確に再現し、漏れなく抽出する
2. 元の段落とフォーマットを維持する
3. 表がある場合は、表形式で出力する
4. 画像にテキストがない場合は、その旨を説明する
これはサンプルチュートリアルのOCRテストです。
    """

    return analyze_image_with_gpt4o(image_path, prompt)


def analyze_chart(image_path: str) -> str:
    """
グラフ分析専用
    """

    prompt = """
このグラフを分析してください。
以下の質問に回答してください:
1. これはどのタイプのグラフですか(棒グラフ、折れ線グラフ、円グラフなど)?
2. グラフのタイトルと軸の意味は何ですか?
3. グラフが伝える主要な情報は何ですか?
4. 注目すべき傾向や異常はありますか?
これはサンプルチュートリアルのグラフ分析テストです。
    """

    return analyze_image_with_gpt4o(image_path, prompt)


# ============================================
# メインプログラム:さまざまなビジョン分析タスクをデモ
# ============================================

if __name__ == "__main__":
    # テスト用画像があると仮定します(実際の画像を用意する必要があります)
    # 例:商品写真、スクリーンショット、書類の写真、グラフなど
    test_image = "サンプル_test_image.jpg"

    # 画像が存在するか確認
    if not os.path.exists(test_image):
        print(fヒント:画像を用意し、{test_image} という名前で現在のディレクトリに置いてください)
        print("またはコード内の画像パスを変更してください")
    else:
        # タスク1:汎用画像記述
        print("\n" + "="*50)
        print("タスク1:画像記述")
        print("="*50)
        result1 = analyze_image_with_gpt4o(
            test_image,
            "主体、背景、色、構図などを含めて、この画像を詳しく説明してください"
        )
        print(result1)

        # タスク2:OCRテキスト抽出
        print("\n" + "="*50)
        print("タスク2:OCR文字抽出")
        print("="*50)
        result2 = extract_text_from_image(test_image)
        print(result2)

        # タスク3:グラフ分析(画像がグラフの場合)
        print("\n" + "="*50)
        print("タスク3:グラフ分析")
        print("="*50)
        result3 = analyze_chart(test_image)
        print(result3)

        print("\n" + "="*50)
        print("サンプルチュートリアルのデモが完了しました!")
        print("="*50)

このプログラムを実行する前に、以下が必要です:

  • 1. 依存関係をインストール:pip install requests

  • 2. テスト用の画像を1枚用意し、次の名前を付けます:サンプル_test_image.jpg

  • 3. APIキーを自分用のものに置き換えます

費用の注意:GPT-4o Visionは画像サイズに応じて課金されます。1024x1024の画像1枚で約0.00765ドルかかります。小さな画像はより安価です。デバッグ時は低解像度の画像を使用し、本番では高解像度を使用することをお勧めします。


テキストから画像(Text-to-Image)

テキストから画像を生成するとは、AIに文字による説明に基づいて画像を生成させることであり、これはもう一つの非常に成熟したマルチモーダル応用分野です。

拡散モデルの原理の概要

今日のテキストから画像を生成するツールは、基本的に拡散モデル(Diffusion Model)技術を使用しています。

その動作原理を簡単に理解するには:

  • トレーニング段階:モデルに鮮明な画像を見せ、その後、ノイズを少しずつ加えていき、全面が雪の結晶のような乱れた画像になるまで続けます。モデルは、乱れた画像を段階的に鮮明にする方法を学習します。

  • 生成段階:モデルにランダムなノイズ画像を与え、テキストプロンプトに従って段階的にノイズを除去させ、最終的に説明に合致する鮮明な画像を生成させます。

このプロセスは通常20〜50ステップ必要とするため、1枚の画像を生成するのに数秒かかります。

Midjourney 上級活用テクニック

Midjourney は現在最も人気のあるテキストから画像を生成するツールの一つで、Discord を通じて使用します。

高品質なプロンプト(Prompt)には通常、以下の要素が含まれます:

  • 主体の説明——「帽子をかぶった猫」

  • スタイル——「宮崎駿スタイル」「油絵」「3Dレンダリング」

  • 光と影——「自然光」「映画的な光」「サイバーパンク風ネオン」

  • 構図——「クローズアップ」「広角」「俯瞰」

  • 画質——「8K」「超高精細」「写真級」

パラメータ説明例
--arアスペクト比の設定--ar 16:9(動画)、--ar 3:4(スマホ)
--vモデルバージョンの指定--v 6.0(最新バージョン)
--sスタイライズ度合い(0-1000)--s 750(芸術性が強い)
--qレンダリング品質(0.25-2)--q 2(より高品質、より遅い)
--iw参照画像の重み--iw 1.5(参照画像により近い)

Stable Diffusion ローカル構築

完全な制御権が必要な場合は、Stable Diffusion をローカルで実行できます:https://github.com/compvis/stable-diffusion。

最も一般的なツールは Automatic1111 の WebUI です。

手順はおおよそ次のとおりです:

  • 1. Python 3.10 をインストール

  • 2. Stable Diffusion WebUI をダウンロード

  • 3. モデルファイルをダウンロード(.safetensors 形式)

  • 4. webui.bat(Windows)または webui.sh(Mac/Linux)を実行

ローカル展開の利点は:生成にお金がかからない、コンテンツ制限がない、LoRA でスタイルを微調整できる、ControlNet で構図を精密に制御できることです。

欠点は:VRAM が少なくとも 6GB のグラフィックカードが必要で、設定が面倒なことです。

実践:DALL·E 3 APIを呼び出して画像を生成

シンプルな API で画像を生成したいなら、DALL·E 3 は良い選択です。

例

# ============================================
# ファイル:サンプル_dalle3_demo.py
# 機能:DALL·E 3 API を使用して画像を生成
# ============================================

import requests
import os
from datetime import datetime

# APIキーを設定(実際のキーに置き換えてください)
OPENAI_API_KEY = "sk-your-api-key-here"
DALLE3_API_URL = "https://api.openai.com/v1/images/generations"


def generate_image_with_dalle3(
    prompt: str,
    size: str = "1024x1024",
    quality: str = "standard",
    style: str = "vivid",
    save_dir: str = "サンプル_generated_images"
) -> dict:
    """
DALL·E 3 API を使用して画像を生成

パラメータの説明:
prompt: テキストによる説明。詳細であればあるほど良い
size: 画像サイズ
選択可能:1024x1024、1024x1792(縦)、1792x1024(横)
quality: 画像品質
選択可能:standard(標準)、hd(高画質、より高価)
style: スタイル
選択可能:vivid(生き生きとして、より芸術的)、natural(自然で、より現実的)
save_dir: 画像の保存先ディレクトリ

戻り値:
画像のURLと保存パスを含む辞書
    """

    # ステップ1:リクエストヘッダーを準備
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {OPENAI_API_KEY}"
    }

    # ステップ2:リクエストボディを準備
    payload = {
        "model": "dall-e-3",
        "prompt": prompt,
        "n": 1,  # DALL·E 3 は一度に1枚しか生成できない
        "size": size,
        "quality": quality,
        "style": style
    }

    # ステップ3:リクエストを送信
    print(f"画像を生成中です。プロンプト:{prompt[:50]}...")
    response = requests.post(DALLE3_API_URL, headers=headers, json=payload)

    # ステップ4:レスポンスを処理
    if response.status_code == 200:
        result = response.json()
        image_url = result["data"][0]["url"]
        revised_prompt = result["data"][0].get("revised_prompt", prompt)

        print(f"DALL·E 3 が自動最適化したプロンプト:{revised_prompt}")

        # ステップ5:画像をダウンロードして保存
        if not os.path.exists(save_dir):
            os.makedirs(save_dir)

        # タイムスタンプでファイル名を生成
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        filename = f"サンプル_dalle3_{timestamp}.png"
        filepath = os.path.join(save_dir, filename)

        # 画像をダウンロード
        image_response = requests.get(image_url)
        if image_response.status_code == 200:
            with open(filepath, "wb") as f:
                f.write(image_response.content)
            print(f"画像は {filepath} に保存されました")

        return {
            "image_url": image_url,
            "filepath": filepath,
            "revised_prompt": revised_prompt
        }
    else:
        error_msg = f"リクエスト失敗:{response.status_code} - {response.text}"
        print(error_msg)
        return {"error": error_msg}


def generate_サンプル_logo_demo():
    """デモ:サンプルスタイルのロゴを生成"""
    prompt = """
    A cute and friendly robot mascot for サンプル tutorial website.
    Blue and green color scheme, modern flat design, white background.
    The robot looks helpful and intelligent, with big friendly eyes.
    Simple, clean, suitable for a tech education brand.
    """

    # 中国語のプロンプトでも大丈夫です。DALL·E 3 は多言語をサポートしています
    prompt = """
サンプルチュートリアルウェブサイトのために、かわいくてフレンドリーなロボットマスコットをデザインしてください。
ブルーグリーンの色調、モダンなフラットデザイン、白い背景。
ロボットは親切で賢そうに見え、大きくて優しい目をしています。
シンプルで清潔感があり、テクノロジー教育ブランドに適しています。
    """

    return generate_image_with_dalle3(
        prompt=prompt,
        size="1024x1024",
        quality="hd",
        style="vivid"
    )


def generate_book_cover_demo():
    """デモ:書籍カバーを生成"""
    prompt = """
    Book cover design for "AI Tutorial for Beginners".
    Modern minimalist style, deep blue and purple gradient background.
    The title text is elegant and readable.
    Subtle tech elements: floating geometric shapes, faint circuit patterns.
    Professional, trustworthy, suitable for a programming book.
    """

    return generate_image_with_dalle3(
        prompt=prompt,
        size="1024x1792",  # 縦向き
        quality="hd",
        style="natural"
    )


def generate_banner_demo():
    """デモ:バナー広告画像を生成"""
    prompt = """
    Web banner design for a coding tutorial website (サンプル).
    16:9 wide format. Modern gradient background from teal to blue.
    Clean layout with space for text.
    Abstract tech elements: floating code snippets, subtle grid lines.
    Professional and inviting.
    """

    return generate_image_with_dalle3(
        prompt=prompt,
        size="1792x1024",  # 横向き
        quality="standard",
        style="vivid"
    )


# ============================================
# メインプログラム:さまざまな生成タスクのデモ
# ============================================

if __name__ == "__main__":
    print("="*60)
    print("サンプル DALL·E 3 画像生成デモ")
    print("="*60)

    # タスク1:ロゴを生成
    print("\n[タスク1] ロゴを生成 ...")
    result1 = generate_サンプル_logo_demo()

    # タスク2:書籍カバーを生成
    print("\n[タスク2] 書籍カバーを生成 ...")
    result2 = generate_book_cover_demo()

    # タスク3:バナーを生成
    print("\n[タスク3] バナーを生成 ...")
    result3 = generate_banner_demo()

    print("\n" + "="*60)
    print(すべてのタスクが完了しました!サンプル_generated_images ディレクトリを確認してください)
    print("="*60)

DALL·E 3 の特徴は:理解力が高い、手や顔が崩れない、文字生成の効果が優れていることです。

しかし制限もあります:一度に1枚しか生成できない、スタイルを正確に制御できない、Stable Diffusion のように微調整できないことです。

著作権の注意:現在の共通認識では、AI で生成した画像について、プロンプト作成者は使用権を持ちますが、著作権は持ちません(著作権局が人間による創作を要求しているため)。商業利用の場合は、ツールの利用規約を確認することをお勧めします。


動画AI

動画AIは2つのカテゴリに分けられます:動画生成と動画理解です。

画像と比較すると、動画の技術的な難易度ははるかに高いです。動画は「時間+空間」の組み合わせであり、各フレームの一貫性と自然な動きを保証する必要があるからです。

AI動画生成ツールの比較

2024年はAI動画の元年であり、多くの企業が動画生成製品を発表しました。

ツール提供元特徴標準的な長さ
SoraOpenAI画面のディテールと空間シーンの理解は業界トップクラス、物理ロジックがリアル、まだ全面的な公開ベータテストは開放されていない最長60秒
Runway Gen-4Runwayオールラウンドな創作プラットフォーム。テキスト/画像からの動画生成、AIポストプロダクション編集、モーションブラシ、VFXエフェクトが一体化。海外のプロのクリエイターに最優先で選ばれています10〜20秒
Kling(可灵AI)快手中国語プロンプトへの適合に優れ、人物の動作が滑らかで、カメラをまたいだキャラクターの安定性があり、中国国内ではコストパフォーマンスが高く、複数セグメントのストーリーテリングの連結をサポート5〜30秒、単一セグメント最長2分
PikaPika Labs2次元、映画・イラストスタイルの表現力が非常に強く、キャラクターのイメージが統一されており、動画のスタイル再描画とフレーム補間をサポート5〜10秒
VeoGoogle映画級のライティングとカメラワーク、長回しのナラティブが安定、物理レンダリングが自然、まだ公開リリースされていない60秒以上
即梦AI(Seedance)字节跳动剪映/抖音エコシステムと緊密に統合し、中国語の意味理解が正確で、音声・映像・口元の同期ができ、スクリプトの自動絵コンテをサポート5〜15秒、複数セグメントを連結して1本の映像に仕上げる
通义万相VideoアリババDAMOアカデミーオープンソース基盤モデル、マルチ主体インタラクションが安定、画面内文字生成に対応、ローカルデプロイ推論が可能2~15秒
海螺AI(Hailuo)MiniMax稀宇軽量で超高速生成、ポスターを動的ショート動画に変換する用途やSNSのフラッシュ素材に最適、アニメ風の表現に優れる4~10秒
Luma Dream MachineLuma AI物理ダイナミクスシミュレーションはトップクラス、水・火・布・爆発などの特殊効果映像がリアルで、映画級のカメラワーク5~12秒
智影テンセントAI編集+デジタルヒューマン動画向け、膨大なショート動画テンプレート、字幕・ナレーション・クロマキー合成がワンストップ、商用利用のハードルが低い時間制限なし、AI生成クリップは5~15秒
海艺AI海艺科技4K/60fpsの高フレームレート出力に対応、複数画像を連動して動画生成、完全な編集ワークベンチを完備、期間限定の無料枠が十分1クリップあたり最長30秒

AI動画はまだ初期段階です:

  • 長所は:アイデア出しが速く、コストが低く、実写では難しい効果を実現できること。

  • 短所は:尺が限られる、細部が崩れやすい、物理ロジックが時々おかしい(例:物体が貫通する、指の本数が間違う)。

  • 適したシーン:コンセプトデモ、ショート動画素材、EC広告、ゲームアニメーション。

  • 不適切なシーン:精密なコントロールが必要な長編映画、真面目なニュース、法的証拠。

動画の理解と要約

動画を生成するだけでなく、AIは動画を理解することもできます。

動画理解の一般的なタスク:

  • 動画要約――「この動画は何についてですか?3文で要約してください。」

  • コンテンツ検索――「動画の中で誰かが自転車に乗っているシーンを見つけてください。」

  • Q&A――「動画の3人目の人物は何と言いましたか?」

技術的なアプローチは通常:動画をフレーム抽出し(例えば毎秒1フレーム)、視覚モデルでフレームごとに確認し、最後に情報を統合する。

今後の動向

動画AIの発展方向は明確です:

  • より長く――10秒から1分へ、そして10分へ。

  • より制御可能に――ストーリーボードで各カットを精密にコントロールできる。

  • より一貫性――同じキャラクターが異なるカットでも一貫している。

  • より実用的――見た目がかっこいいだけでなく、実際の問題を解決できるように。

  • 期待できること:数年後、誰もがAIで映画のような動画作品を作れるかもしれない。


オーディオと音声AI

オーディオAIの主な要素:音声認識(ASR)、音声合成(TTS)、音楽生成。

これはすでにかなり成熟した分野です。

音声をテキストに変換(Whisper API)

Whisper は OpenAI がオープンソース化した音声認識モデルで、性能が非常に良く、99言語に対応しています。

例

# ============================================
# ファイル:サンプル_whisper_demo.py
# 機能:Whisper API を使用して音声を文字起こし
# ============================================

import requests
import os

# API キーを設定
OPENAI_API_KEY = "sk-your-api-key-here"
WHISPER_API_URL = "https://api.openai.com/v1/audio/transcriptions"


def transcribe_audio_with_whisper(
    audio_path: str,
    language: str = "zh",  # zh=中国語, en=英語, 空欄の場合は自動認識
    prompt: str = "",     # 任意:専門用語のヒントを提供して精度を向上
    temperature: float = 0.0
) -> dict:
    """
Whisper API を使用して音声ファイルを文字起こし

パラメータの説明:
audio_path: 音声ファイルのパス(mp3、wav、m4a などに対応)
language: 言語コード(任意、指定しない場合は自動認識)
一般的なコード:zh(中国語)、en(英語)、ja(日本語)
prompt: プロンプト(任意、発生しうる専門用語や人名をここに記述)
temperature: サンプリング温度(0.0 は最も確定的、1.0 はより多様)

戻り値:
文字起こしテキストを含む辞書
    """

    # ステップ 1:ファイルが存在するか確認
    if not os.path.exists(audio_path):
        return {"error": f"ファイルが存在しません:{audio_path}"}

    # ステップ 2:リクエストヘッダーを準備
    headers = {
        "Authorization": f"Bearer {OPENAI_API_KEY}"
    }

    # ステップ 3:リクエストボディを準備(注意:音声は multipart/form-data 形式を使用)
    files = {
        "file": open(audio_path, "rb")
    }
    data = {
        "model": "whisper-1",
        "temperature": temperature
    }
    if language:
        data["language"] = language
    if prompt:
        data["prompt"] = prompt

    # ステップ 4:リクエストを送信
    print(f"音声を文字起こし中:{audio_path} ...")
    response = requests.post(WHISPER_API_URL, headers=headers, files=files, data=data)

    # ステップ 5:ファイルを閉じる
    files["file"].close()

    # ステップ 6:レスポンスを処理
    if response.status_code == 200:
        result = response.json()
        text = result["text"]
        print(f文字起こし完了、合計 {len(text)} 文字)
        return {
            "text": text,
            "language": language
        }
    else:
        error_msg = f"リクエスト失敗:{response.status_code} - {response.text}"
        print(error_msg)
        return {"error": error_msg}


def transcribe_with_timestamps(audio_path: str) -> dict:
    """
タイムスタンプ付き文字起こし(verbose_json 形式を使用)
    """

    headers = {
        "Authorization": f"Bearer {OPENAI_API_KEY}"
    }
    files = {"file": open(audio_path, "rb")}
    data = {
        "model": "whisper-1",
        "response_format": "verbose_json",  # タイムスタンプを含む詳細情報を返す
        "timestamp_granularities": ["segment", "word"]  # セグメントレベルとワードレベルのタイムスタンプに対応
    }

    response = requests.post(WHISPER_API_URL, headers=headers, files=files, data=data)
    files["file"].close()

    if response.status_code == 200:
        result = response.json()
        return result
    else:
        return {"error": response.text}


def translate_audio_to_english(audio_path: str) -> dict:
    """
任意の言語の音声を英語テキストに翻訳
    """

    headers = {
        "Authorization": f"Bearer {OPENAI_API_KEY}"
    }
    files = {"file": open(audio_path, "rb")}
    data = {
        "model": "whisper-1",
        "task": "translate"  # 特別指定:翻訳タスク
    }

    response = requests.post("https://api.openai.com/v1/audio/translations",
                            headers=headers, files=files, data=data)
    files["file"].close()

    if response.status_code == 200:
        return response.json()
    else:
        return {"error": response.text}


def サンプル_meeting_minutes_demo(audio_path: str) -> str:
    """
実践:会議議事録の生成
ステップ 1:Whisper で録音を文字起こし
ステップ 2:GPT-4o で議事録に整理
    """

    # まず文字起こし
    print("ステップ 1:会議の録音を文字起こし...")
    transcribe_result = transcribe_audio_with_whisper(
        audio_path,
        language="zh",
        prompt="これは サンプル 技術チームの会議で、製品開発、進捗、技術ソリューションなどを議論しています"
    )

    if "error" in transcribe_result:
        return transcribe_result["error"]

    transcript = transcribe_result["text"]

    # 次に整理(ここでは簡略化、実際のプロジェクトでは GPT-4o API を呼び出せる)
    print("ステップ 2:議事録を整理...")
    # ここではデモのため、文字起こしテキストを直接返す
    # 実際のプロジェクトでは、transcript を GPT-4o に送信して整理してもらえます
    return transcript


# ============================================
# メインプログラム
# ============================================

if __name__ == "__main__":
    # テスト用オーディオファイルを準備
    test_audio = "サンプル_test_audio.mp3"

    if not os.path.exists(test_audio):
        print(f"ヒント:オーディオファイルを準備し、{test_audio} という名前で保存してください")
        print("またはスマートフォンで音声を録音し、mp3 形式で保存してください")
    else:
        # タスク 1:単純な文字起こし
        print("\n" + "="*50)
        print("タスク 1:単純な文字起こし")
        print("="*50)
        result1 = transcribe_audio_with_whisper(test_audio, language="zh")
        if "text" in result1:
            print("文字起こし結果:")
            print(result1["text"])

        # タスク 2:タイムスタンプ付き文字起こし
        print("\n" + "="*50)
        print("タスク 2:タイムスタンプ付き文字起こし")
        print("="*50)
        result2 = transcribe_with_timestamps(test_audio)
        if "segments" in result2:
            print("段落情報:")
            for seg in result2["segments"][:3]:  # 最初の3段落のみ出力
                start = round(seg["start"], 2)
                end = round(seg["end"], 2)
                text = seg["text"]
                print(f"[{start}-{end}] {text}")

        print("\n" + "="*50)
        print(サンプル Whisper デモ完了!)
        print("="*50)

Whisper の利点は:多言語サポートが良好、アクセントに左右されない、自動で句読点を付けられる。

代表的な用途:会議録音の文字起こし、動画字幕生成、ポッドキャストの文字起こし、音声日記。

テキストから音声へ(TTS)

音声合成とは、AIに文章を「読ませる」ことです。

OpenAI も TTS API を提供しており、複数の音声スタイルに対応しています。

他の TTS ツール:ElevenLabs(最も人間らしい)、Azure TTS(商用グレード)、Edge TTS(無料)、Coqui(オープンソース)。

音楽生成(Suno、Udio)

音楽生成も大きな進歩を遂げました。

Suno と Udio は代表的な2つの製品です――歌詞とスタイルの説明を入力すると、ボーカルも伴奏もある完全な1曲を生成できます。

能力の限界:

  • できること:BGM生成、デモ曲作成、スタイルの素早い試行。

  • あまりできないこと:特定の曲を完全に複製する、音符を精密に制御する、プロ級の後処理。

  • 著作権について:ツールによって条項が異なるため、商用利用前に確認してください。


マルチモーダルモデルアーキテクチャの概要

原理を少し理解すると、ツールをより上手く使えます。

CLIP:画像とテキストを整列させる基盤

CLIP(Contrastive Language-Image Pre-training)は OpenAI が2021年に発表したモデルです。

そのアイデアはシンプル:画像とテキストを同時に見て、それらを対応付けることを学習します。

トレーニング時、モデルに一連の画像+説明のペアを与え、次のことを学習させます:

  • 1. 画像をベクトルに変換

  • 2. テキストをベクトルに変換

  • 3. ペアの画像・テキストベクトルをできるだけ近づけ、ペアでないものはできるだけ遠ざける

CLIP の意義は:「クロスモーダル理解」が実現可能であることを証明した。

後の Stable Diffusion、GPT-4o などは、CLIP から影響を受けています。

LLaVA:オープンソースのマルチモーダルLLM

LLaVA(Large Language and Vision Assistant)はオープンソースのマルチモーダルモデルです。

そのアーキテクチャは明確です:

  • 視覚エンコーダー(例:ViT)――画像を担当

  • 大規模言語モデル(例:LLaMA)――言語を担当

  • 射影層――画像ベクトルを言語モデルが理解できる形式に変換

トレーニングは2段階:

  • ステップ 1:事前学習による整合――視覚エンコーダーと言語モデルが同じ言語を話すようにする

  • ステップ 2:命令チューニング――画像・質問・回答のデータでトレーニングし、指示に従って回答できるようにする

LLaVA はマルチモーダル技術を学ぶのに最適な出発点です——コードはオープンソース、アーキテクチャは明確、効果も良好です。


実践:画像分析ツールの構築

これまでの知識を統合して、実用的な画像分析ツールを作りましょう。

例

# ============================================
# ファイル:サンプル_image_analyzer.py
# 機能:完全なマルチモーダル画像分析ツール
# ============================================

import base64
import requests
import os
import json
from datetime import datetime
from typing import Optional, Dict, Any


class サンプルImageAnalyzer:
    """
サンプル 画像分析器——カプセル化されたマルチモーダルツールクラス
    """


    def __init__(self, api_key: str, base_url: str = "https://api.openai.com/v1"):
        """
分析器の初期化

パラメータ:
api_key: OpenAI API キー
base_url: API アドレス(プロキシ設定可能)
        """

        self.api_key = api_key
        self.base_url = base_url
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {api_key}"
        }

    def _encode_image(self, image_path: str) -> str:
        """画像を Base64 にエンコードする"""
        with open(image_path, "rb") as f:
            return base64.b64encode(f.read()).decode("utf-8")

    def _call_vision_api(
        self,
        image_path: str,
        prompt: str,
        model: str = "gpt-4o",
        max_tokens: int = 2000
    ) -> Optional[str]:
        """内部メソッド:ビジョン API を呼び出す"""
        base64_image = self._encode_image(image_path)

        payload = {
            "model": model,
            "messages": [
                {
                    "role": "user",
                    "content": [
                        {"type": "text", "text": prompt},
                        {
                            "type": "image_url",
                            "image_url": {"url": f"data:image/jpeg;base64,{base64_image}"}
                        }
                    ]
                }
            ],
            "max_tokens": max_tokens
        }

        url = f"{self.base_url}/chat/completions"
        response = requests.post(url, headers=self.headers, json=payload)

        if response.status_code == 200:
            return response.json()["choices"][0]["message"]["content"]
        else:
            print(f"API エラー:{response.status_code} - {response.text}")
            return None

    def describe(self, image_path: str) -> Optional[str]:
        """画像の内容を詳細に説明する"""
        prompt = """
この画像について詳しく説明してください。以下を含みます:
1. 主体となる内容(どのような人・物があるか)
2. 背景の環境
3. 色と光
4. 全体的な雰囲気
中国語で回答し、構造を明確にしてください。
        """

        return self._call_vision_api(image_path, prompt)

    def extract_text(self, image_path: str) -> Optional[str]:
        """画像内のすべての文字を抽出する(OCR)"""
        prompt = """
この画像内のすべての文字内容を抽出してください。
要件:
1. 正確に再現し、漏れがないこと
2. 元の段落構造を維持すること
3. 表の場合は Markdown テーブル形式で出力すること
4. 文字がない場合は「画像に認識可能な文字はありません」と明確に説明すること
        """

        return self._call_vision_api(image_path, prompt)

    def analyze_ui(self, image_path: str) -> Optional[str]:
        """UI デザイン稿(スクリーンショット)を分析する"""
        prompt = """
この UI デザイン稿を分析してください:
1. これはどのタイプのインターフェースですか(アプリ、Web ページ、ミニアプリなど)?
2. 画面の主要な機能モジュールは何ですか?
3. デザインスタイルはどうですか(配色、レイアウト、フォント)?
4. 改善できる点は何ですか?
中国語で回答し、箇条書きで列挙してください。
        """

        return self._call_vision_api(image_path, prompt)

    def analyze_product(self, image_path: str) -> Optional[str]:
        """商品画像を分析し、EC コピーを生成する"""
        prompt = """
この商品画像を分析して、EC 向けコピーを生成してください。
コピーには以下を含めること:
1. 商品名とタイプ
2. 外観の特徴(色、素材、デザイン)
3. 魅力的な短い推薦文(30〜50 文字)
中国語で回答し、友好的で前向きなトーンにしてください。
        """

        return self._call_vision_api(image_path, prompt)

    def classify(self, image_path: str, categories: list = None) -> Optional[str]:
        """画像を分類する"""
        if categories is None:
            categories = [
                "人物写真", "風景写真", "グルメ写真", "製品写真",
                "デザイン稿/スクリーンショット", "ドキュメント/表", "グラフ/データ可視化", "その他"
            ]
        cat_list = "、".join(categories)
        prompt = f"""
この画像がどのカテゴリに属するかを判定してください。
選択可能なカテゴリ:{cat_list}
最も一致するカテゴリ名を 1 つだけ返してください。他の文字は不要です。
        """

        return self._call_vision_api(image_path, prompt)

    def full_analysis(self, image_path: str, output_dir: str = "サンプル_analysis") -> Dict[str, Any]:
        """
完全分析:詳細な分析レポートの生成

すべての分析結果を含む辞書を返します
        """

        print(f"画像の分析を開始:{image_path}")

        # まず分類
        print("[1/5] 分類中...")
        category = self.classify(image_path) or "不明"

        # 説明
        print("[2/5] 説明中...")
        description = self.describe(image_path) or ""

        # 文字を抽出
        print("[3/5] OCR 処理中...")
        text = self.extract_text(image_path) or ""

        # カテゴリに応じて専門分析
        print("[4/5] 専門分析中...")
        special_analysis = ""
        if "デザイン" in category or "スクリーンショット" in category:
            special_analysis = self.analyze_ui(image_path) or ""
        elif "製品" in category or "商品" in category:
            special_analysis = self.analyze_product(image_path) or ""

        # レポートを保存
        print("[5/5] レポート生成中...")
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)

        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        report = {
            "image_file": os.path.basename(image_path),
            "analysis_time": datetime.now().isoformat(),
            "category": category,
            "description": description,
            "extracted_text": text,
            "special_analysis": special_analysis
        }

        # JSON を保存
        json_path = os.path.join(output_dir, f"report_{timestamp}.json")
        with open(json_path, "w", encoding="utf-8") as f:
            json.dump(report, f, ensure_ascii=False, indent=2)

        # 読み取り可能なテキストを保存
        txt_path = os.path.join(output_dir, f"report_{timestamp}.txt")
        with open(txt_path, "w", encoding="utf-8") as f:
            f.write("="*60 + "\n")
            f.write("サンプル 画像分析レポート\n")
            f.write("="*60 + "\n\n")
            f.write(f"画像:{report['image_file']}\n")
            f.write(f"時間:{report['analysis_time']}\n")
            f.write(f"分類:{report['category']}\n\n")
            f.write("-"*60 + "\n")
            f.write("画像の説明:\n")
            f.write("-"*60 + "\n")
            f.write(report["description"] + "\n\n")
            f.write("-"*60 + "\n")
            f.write("抽出した文字:\n")
            f.write("-"*60 + "\n")
            f.write(report["extracted_text"] + "\n\n")
            if report["special_analysis"]:
                f.write("-"*60 + "\n")
                f.write("専門分析:\n")
                f.write("-"*60 + "\n")
                f.write(report["special_analysis"] + "\n")

        print(f"分析完了!レポートは {output_dir} に保存されました。")
        return report


# ============================================
# 使用例
# ============================================

def main():
    # API キーを設定
    api_key = "sk-your-api-key-here"

    # 分析器を作成
    analyzer = サンプルImageAnalyzer(api_key)

    # 分析する画像のパス
    image_path = "サンプル_test_image.jpg"

    if not os.path.exists(image_path):
        print(f"先に画像を準備してください:{image_path}")
        return

    # 方法 1:特定の機能を単独で使用
    print("\n方法 1:OCR 機能を単独で使用")
    print("-"*40)
    text = analyzer.extract_text(image_path)
    if text:
        print("抽出した文字:")
        print(text)

    # 方法 2:完全分析
    print("\n方法 2:完全分析")
    print("-"*40)
    report = analyzer.full_analysis(image_path)
    print(f"分類結果:{report['category']}")
    print(f"レポートは保存されました")


if __name__ == "__main__":
    main()

このツールはよく使われる画像分析機能をカプセル化しており、プロジェクトで直接使用できます。

必要に応じて拡張できます:

  • 分析シナリオをさらに追加する(例:医用画像、産業検査、教育問題の分析)

  • シンプルな Web インターフェースを追加する(Flask または Gradio を使用)

  • フォルダ内の画像の一括処理をサポートする

  • 結果をデータベースに保存する

その他の拡張