見出し画像

Gemini API で 動画の質問応答 を試す

「Gemini API」で動画の質問応答を試したので、まとめました。

【最新版の情報は以下で紹介】


1. Gemini 1.5 Pro の 動画データ入力

「Gemini 1.5 Pro」で動画データでの入力が可能になりました。
サポートしているファイル形式は、次のとおりです。

・動画を一連の静止画フレームと個別の音声ファイルに分割して使用。
・1秒あたり何フレームにするかで、データ量と詳細レベルを調整。
・静止画フレームと音声は個別プロンプトとみなされる。
同一時間における静止画フレームと音声の関係を問う質問はうまくいかない場合があります。

2. 動画の質問応答

動画の質問応答の手順は、次のとおりです。

(1) パッケージのインストール。

# パッケージのインストール
!pip install -U -q google-generativeai

(2) 「Google AI Studio」でAPIキーを取得し、シークレットの「GOOGLE_API_KEY」に登録後、以下のセルを実行。

from google.colab import userdata
import google.generativeai as genai

# 環境変数の準備 (左端の鍵アイコンでGOOGLE_API_KEYを設定)
GOOGLE_API_KEY=userdata.get("GOOGLE_API_KEY")
genai.configure(api_key=GOOGLE_API_KEY)

(3) 静止画フレームの準備。
今回はOpenCV を使用して、短編映画「Big Buck Bunny」から1秒あたり1フレームを抽出します。

(c) copyright 2008, Blender Foundation / www.bigbuckbunny.org and licensed under the Creative Commons Attribution 3.0 License.
import cv2
import os
import shutil

# 動画ファイル名
video_file_name = "https://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4"

# フォルダの準備
FRAME_EXTRACTION_DIRECTORY = "/content/frames"
FRAME_PREFIX = "_frame"
def create_frame_output_dir(output_dir):
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    else:
        shutil.rmtree(output_dir)
        os.makedirs(output_dir)

# 動画からのフレーム抽出
def extract_frame_from_video(video_file_path):
    create_frame_output_dir(FRAME_EXTRACTION_DIRECTORY)
    vidcap = cv2.VideoCapture(video_file_path)
    fps = vidcap.get(cv2.CAP_PROP_FPS)
    frame_duration = 1 / fps  # フレーム間の時間間隔 (秒単位)
    output_file_prefix = os.path.basename(video_file_path).replace('.', '_')
    frame_count = 0
    count = 0
    while vidcap.isOpened():
        success, frame = vidcap.read()
        if not success: # 動画終了
            break
        if int(count / fps) == frame_count: # 毎秒フレームを抽出
            min = frame_count // 60
            sec = frame_count % 60
            time_string = f"{min:02d}:{sec:02d}"
            image_name = f"{output_file_prefix}{FRAME_PREFIX}{time_string}.jpg"
            output_filename = os.path.join(FRAME_EXTRACTION_DIRECTORY, image_name)
            cv2.imwrite(output_filename, frame)
            frame_count += 1
        count += 1
    vidcap.release() # vidcapの解放
    print("Completed:", frame_count, "frames")

# 動画からのフレーム抽出の実行
extract_frame_from_video(video_file_name)
Completed: 597 frames

framesフォルダに静止画フレームが生成されます。

(4) Fileリストに読み込み
静止画フレームをFileリストに読み込みます。Fileはfile_path、display_name、timestamp、responseを持つカスタムクラスです。

import os

# Fileクラスの定義
class File:
    def __init__(self, file_path: str, display_name: str = None):
        self.file_path = file_path
        if display_name:
            self.display_name = display_name
        self.timestamp = get_timestamp(file_path)

    def set_file_response(self, response):
        self.response = response

# timestampの取得
def get_timestamp(filename):
    parts = filename.split(FRAME_PREFIX)
    if len(parts) != 2:
        return None
    return parts[1].split('.')[0]

# Fileリストの準備
files = os.listdir(FRAME_EXTRACTION_DIRECTORY)
files = sorted(files)
files_to_upload = []
for file in files:
    files_to_upload.append(
        File(file_path=os.path.join(FRAME_EXTRACTION_DIRECTORY, file)))

(5) ファイルのアップロード。

# 動画全体をアップロードするかどうか (Falseは10秒のみ)
full_video = False

# ファイルのアップロード
uploaded_files = []
for file in files_to_upload if full_video else files_to_upload[40:50]:
    print(f'Uploading: {file.file_path}...')
    response = genai.upload_file(path=file.file_path)
    file.set_file_response(response)
    uploaded_files.append(file)
Uploading: /content/frames/BigBuckBunny_320x180_mp4_frame00:40.jpg...
Uploading: /content/frames/BigBuckBunny_320x180_mp4_frame00:41.jpg...
Uploading: /content/frames/BigBuckBunny_320x180_mp4_frame00:42.jpg...
Uploading: /content/frames/BigBuckBunny_320x180_mp4_frame00:43.jpg...
Uploading: /content/frames/BigBuckBunny_320x180_mp4_frame00:44.jpg...
Uploading: /content/frames/BigBuckBunny_320x180_mp4_frame00:45.jpg...
Uploading: /content/frames/BigBuckBunny_320x180_mp4_frame00:46.jpg...
Uploading: /content/frames/BigBuckBunny_320x180_mp4_frame00:47.jpg...
Uploading: /content/frames/BigBuckBunny_320x180_mp4_frame00:48.jpg...
Uploading: /content/frames/BigBuckBunny_320x180_mp4_frame00:49.jpg...

(6) 動画の質問応答。
プロンプトには、テキスト指示と、タイムスタンプと静止画フレームを設定しています。

# モデルの準備
model = genai.GenerativeModel("models/gemini-1.5-pro-latest")

# プロンプトの準備
prompt = "この動画を日本語で説明してください。"
request = [prompt]
for file in uploaded_files:
    request.append(file.timestamp) # タイムスタンプ (00:00)
    request.append(file.response) # 静止画フレーム

# 推論の実行
response = model.generate_content(
    request,
    request_options={"timeout": 600} # タイムアウト指定
)
print(response.text) 

動画は、大きな灰色のウサギが巣穴から出てくる様子を示しています。ウサギは最初は眠そうで、ゆっくりと目を開けています。それから、伸びをして巣穴から出てきます。ウサギは太っていて、毛皮は短くて灰色です。巣穴は草や岩に囲まれた丘の側面にあります。背景には木々と湖が見えます。

(7) ファイルの削除。

# ファイルの削除
for file in uploaded_files:
    genai.delete_file(file.response.name)  



この記事が気に入ったらサポートをしてみませんか?