LoginSignup
53
35

リリースされたGPT-4oを使って動画のサマリー生成をしてみる!

Posted at

概要

GPT-4oが発表されました。
GPT-4oについては以下のツイートによくまとまっています。

使用している映像は以下でまとめられています。

非常に優秀でAI系のプロダクトがまた何個か死んだと思いますが、それはさておき使っていきましょう。
APIではすでに利用可能になっております。

今回は以下のcookbookにある動画要約をgradioに移植します。
https://cookbook.openai.com/examples/gpt4o/introduction_to_gpt4o

デモ

以下の Huggingface Space を作りました。APIキーと動画を貼り付けて試用することができます。
1分間の動画で0.1ドル / 60秒くらいかかります。API使用料に注意してください。

現状のGPT-4o APIの制限

  • 動画はそのままアップロードできません
    • これは将来的にもできるとされていないため、ffmpegなどを使ってフレームを処理する必要があります。また、秒間30フレームとか送ると大量のトークンを消費するため、動画理解に必要と思われる分だけ送る必要があります
    • だいたい秒間0.5フレーム (2秒で1フレーム) 程度で十分でしょう
  • 音声はそのままアップロードできません
    • これは数週間のうちに可能になるとのことです
    • 現状ではWhisperで書き起こしの形状にしてから送ります

実装

動画のフレーム抽出と音声抽出

cookbook にあるものと同じです。シンプルな処理です。

def process_video(video_path, seconds_per_frame=2):
    base64Frames = []
    base_video_path, _ = os.path.splitext(video_path)
    video = cv2.VideoCapture(video_path)
    total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
    fps = video.get(cv2.CAP_PROP_FPS)
    frames_to_skip = int(fps * seconds_per_frame)
    curr_frame = 0

    while curr_frame < total_frames - 1:
        video.set(cv2.CAP_PROP_POS_FRAMES, curr_frame)
        success, frame = video.read()
        if not success:
            break
        _, buffer = cv2.imencode(".jpg", frame)
        base64Frames.append(base64.b64encode(buffer).decode("utf-8"))
        curr_frame += frames_to_skip
    video.release()

    audio_path = f"{base_video_path}.mp3"
    clip = VideoFileClip(video_path)
    clip.audio.write_audiofile(audio_path, bitrate="32k")
    clip.audio.close()
    clip.close()

    return base64Frames, audio_path

APIの呼び出し

APIの使い方はGPT-4Vと同様です。

# Whisperで音声を文字起こし
transcription = client.audio.transcriptions.create(
    model="whisper-1", file=open(audio_path, "rb")
)

# GPT-4oで要約生成
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[
        {
            "role": "system",
            "content": """あなたは優秀な要約者です。提供された動画とその書き起こしの要約をMarkdown形式で作成してください""",
        },
        {
            "role": "user",
            "content": [
                "これらは動画から取得されたフレームです",
                *map(
                    lambda x: {
                        "type": "image_url",
                        "image_url": {
                            "url": f"data:image/jpg;base64,{x}",
                            "detail": "low",
                        },
                    },
                    base64Frames,
                ),
                {
                    "type": "text",
                    "text": f"動画の書き起こしはこちらです: {transcription.text}",
                },
            ],
        },
    ],
    temperature=0,
)

return response.choices[0].message.content

おわりに

今回は試してみやすいように Huggingface Space に上げました。
サンプルコードがなかったとしてもこの程度の実装であれば1分くらいでできると思います。いい時代ですね。
音声合成がAPIにパックされているかは不明であるため、APIで使う場合は別途text-to-speech APIを叩くか自前で用意しなければならないかもしれません。つらいですね。

53
35
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
53
35