ollama環境で動画を読み込むことができる無料のLLMを使って内容を把握する方法
はじめに
、Vision Language Models (VLM) と呼ばれる、画像とテキストを同時に理解できるマルチモーダルAI GPT-4o(OpenAI社) 、LLaVA-NeXT-Video(ByteDance社) 、Gemini 1.5 Pro(GoogleなどありますがInternVL・LLaVA-Video・Video-LLaMA GLM-4.6V-Flash Qwen2.5-VLなどのオープンソースモデルも使うことができます
モデル
ollama run blaifa/InternVL3_5:4B
ollama run ManishThota/llava_next_video
ollama run qwen2.5vl
ollama run gurubot/GLM-4.6V-Flash-GGUF:Q4_K_M動画を分解して理解する Python プログラム
インストール
pip install ollama
プログラム
import os
import subprocess
import ollama
from pathlib import Path
FFMPEG_PATH = r"D:\WinPython\ffmpeg\bin\ffmpeg.exe"
TEMP_DIR = r"Y:\temp_frames"
INPUT_DIR = r"Y:\gif"
OUTPUT_DIR = r"Y:\output"
MODEL_NAME = "blaifa/InternVL3_5:4B"
# ===== フレーム抽出(GIF / MP4 共通) =====
def extract_frames(video_path):
os.makedirs(TEMP_DIR, exist_ok=True)
# 既存フレーム削除
for f in Path(TEMP_DIR).glob("*.jpg"):
f.unlink()
cmd = [
FFMPEG_PATH,
"-i", video_path,
os.path.join(TEMP_DIR, "frame_%06d.jpg")
]
print("ffmpeg 実行:", " ".join(cmd))
subprocess.run(cmd)
print("フレーム抽出完了:", TEMP_DIR)
frames = sorted(str(p) for p in Path(TEMP_DIR).glob("*.jpg"))
return frames
# ===== InternVL3.5 で解析 =====
def analyze_images(image_paths, lang="ja"):
if lang == "ja":
prompt = """
あなたは映像解析の専門家です。
以下の画像は動画またはアニメーションの全フレームです。
【重要】
- 日本語で非常に詳しく説明する
- 背景(場所・環境・状況)を細かく描写
- 登場人物(性別・服装・髪型・表情・動作)を詳細に描写
- 物体(家具・道具・乗り物など)を詳しく説明
- 時系列で「何が起きているか」を丁寧に説明
- 内部思考(<think>)は絶対に出力しない
"""
else:
prompt = """
You are an expert in video scene analysis.
The following images are all frames of a video or animation.
Requirements:
- Describe everything in detailed English
- Describe background, environment, lighting, atmosphere
- Describe people: gender, clothing, hairstyle, expression, actions
- Describe objects and surroundings
- Explain the timeline of actions step-by-step
- Do NOT output chain-of-thought or internal reasoning
"""
res = ollama.chat(
model=MODEL_NAME,
messages=[
{
"role": "user",
"content": prompt,
"images": image_paths
}
]
)
return res["message"]["content"]
# ===== 入力ファイルを自動判定して解析 =====
def process_file(path):
ext = Path(path).suffix.lower()
base = Path(path).stem
print(f"\n=== 処理開始: {path} ===")
# GIF / MP4 → フレーム抽出
if ext in [".gif", ".mp4"]:
print("アニメーションまたは動画として処理します。")
frames = extract_frames(path)
# JPG / PNG → そのまま
elif ext in [".jpg", ".jpeg", ".png"]:
print("静止画として処理します。")
frames = [path]
else:
print(f"対応していない形式: {ext}")
return
# 出力フォルダ作成
os.makedirs(OUTPUT_DIR, exist_ok=True)
# 日本語解析
ja_text = analyze_images(frames, lang="ja")
with open(Path(OUTPUT_DIR) / f"{base}_ja.txt", "w", encoding="utf-8") as f:
f.write(ja_text)
# 英語解析
en_text = analyze_images(frames, lang="en")
with open(Path(OUTPUT_DIR) / f"{base}_en.txt", "w", encoding="utf-8") as f:
f.write(en_text)
print(f"出力完了: {base}_ja.txt / {base}_en.txt")
# ===== メイン =====
if __name__ == "__main__":
files = list(Path(INPUT_DIR).glob("*.*"))
print(f"対象ファイル数: {len(files)}")
for f in files:
process_file(str(f))
print("\n=== 全ファイル処理完了 ===")








ディスカッション
コメント一覧
まだ、コメントがありません