動画を構造化してインデックス化し、AIエージェントとの対話を通じて動画コンテンツを探索できるStreamlitアプリケーション。
Video Indexは、アップロードされた動画を自動的に分析し、階層的な構造(チャプター、セグメント)に分解します。各セグメントは専門のAIエージェントとして機能し、動画の特定部分に関する質問に正確に回答できます。
- 動画の自動インデックス化: Gemini 2.5 Flashを使用して動画を構造化
- 階層的コンテンツツリー: チャプターとセグメントの階層構造で動画を整理
- マルチエージェントシステム: 各セグメントが専門エージェントとして機能
- インタラクティブなチャット: 動画コンテンツに関する質問に回答
- ビジュアルツリービュー: 動画の構造を視覚的に表示
アプリは画面を左右2つのカラムに分割し、効率的な動画探索を実現します:
- 📹 動画プレーヤー: アップロードした動画をその場で再生
- 🌳 構造ツリー: 動画の階層構造を視覚的に表示
- チャプターとセグメントが折りたたみ可能なツリーで表示
- 各ノードに時間範囲(MM:SS形式)が表示
- 説明文で内容を素早く把握
- 💬 チャット: AIエージェントとの自然な対話
- 会話履歴が保持され、文脈を理解した回答
- マークダウン形式で見やすく整形された応答
- ストリーミング表示で応答の進行状況を確認
📹 動画: 「機械学習入門講座」(45分)
1. 動画をアップロード
→ 自動的に5つのチャプターに分割
2. ツリービューで構造を確認
Chapter 1: イントロダクション (00:00〜05:30)
Chapter 2: 教師あり学習 (05:30〜18:45)
Chapter 3: 教師なし学習 (18:45〜28:20)
...
3. チャットで質問
Q: "教師あり学習のセクションで説明されている主なアルゴリズムは?"
A: Chapter 2のエージェントが回答
→ 線形回帰、ロジスティック回帰、決定木について
05:30〜18:45の範囲で詳しく説明されています...
📹 動画: 「プロジェクト進捗会議」(1時間20分)
1. ツリービューで議題を一覧
- 予算について (12:30〜25:15)
- スケジュールについて (25:15〜42:00)
- リスク管理について (42:00〜58:30)
2. 時間を指定して質問
Q: "42:00から58:30の間で議論されたリスクは何ですか?"
A: 該当セグメントのエージェントが正確に回答
→ 技術的負債、人員不足、納期遅延の3つのリスクが
議論されました...
3. 横断的な質問も可能
Q: "この会議で決定された次のアクションアイテムをすべて教えて"
A: ルートエージェントが全チャプターを統合して回答
📹 動画: 「Dockerコンテナのデプロイ手順」(15分)
1. ツリービューで手順を確認
Segment 1: 環境準備 (00:00〜03:20)
Segment 2: Dockerfileの作成 (03:20〜07:45)
Segment 3: イメージのビルド (07:45〜10:30)
Segment 4: コンテナの起動 (10:30〜15:00)
2. 特定の手順について深掘り
Q: "Dockerfileの作成で使用されているベースイメージは?"
A: Segment 2のエージェントが映像内容を基に回答
→ alpine:3.18をベースイメージとして使用し、
軽量化を重視した構成になっています...
3. トラブルシューティング
Q: "コンテナ起動時のエラー対処法は説明されていますか?"
A: Segment 4の内容を検索して回答
- セッション内で会話履歴が保持され、前の質問を踏まえた対話が可能
- 「それについてもっと詳しく」のような参照も理解
- 階層的エージェント構造により、関連部分のみを効率的に検索
- 不要な動画全体の再分析を回避
- すべての回答に時間範囲(MM:SS形式)が含まれる
- 「どこで説明されているか」が明確
- 時間指定の質問: "03:15から03:45の間に..."
- トピック指定の質問: "機械学習について..."
- 横断的な質問: "この動画全体で..."
- 比較の質問: "AとBの違いは..."
video_index/
├── indexer.py # 動画のインデックス化ロジック
├── models.py # データモデル(VideoAnalysisResult, ChapterNode, SegmentNode)
├── agent.py # ADKエージェント呼び出しロジック
├── callbacks.py # エージェントコールバック(動画アーティファクト添付)
└── ui/ # Streamlit UIコンポーネント
├── chat.py # チャットインターフェース
├── tree_view.py # ツリービューコンポーネント
└── assets/ # CSS/JSアセット
VideoAnalysisResult (ルート)
├── video_title: str
├── overview: str
└── children: List[ChapterNode | SegmentNode]
│
├── ChapterNode (コンテナ)
│ ├── title: str
│ ├── summary: str
│ └── children: List[SegmentNode]
│ │
│ └── SegmentNode (リーフ)
│ ├── title: str
│ ├── description: str
│ └── time_span: TimeSpan
│
└── SegmentNode (リーフ)
├── title: str
├── description: str
└── time_span: TimeSpan
各ノードは専門のAIエージェントに変換されます:
- VideoAgent: 動画全体を担当するルートエージェント
- ChapterAgent: 特定のチャプターを担当し、子セグメントエージェントをツールとして保持
- SegmentAgent: 特定の時間範囲のセグメントを担当
before_model_callbackを使用して、担当時間範囲の動画クリップを自動的にLLMリクエストに添付- アーティファクトサービスから動画を読み込み、時間メタデータ(start_offset, end_offset)を設定
エージェントは階層的に連携し、質問内容に応じて適切な子エージェントに委譲します。
- Python 3.13以上
- uv パッケージマネージャー
- Google AI Studio APIキー
- リポジトリをクローン:
git clone <repository-url>
cd video_index- 依存関係をインストール:
uv sync- 環境変数を設定:
.envファイルを作成し、Google AI Studio APIキーを設定:
GOOGLE_API_KEY=your_api_key_heretask streamlit:runまたは
uv run streamlit run app.pyブラウザで http://localhost:8501 にアクセスします。
画面上部の「Browse files」ボタンをクリックし、動画ファイルを選択します。
対応フォーマット: mp4, mov, avi, mkv
アップロード後、自動的に動画の分析が始まります:
🔄 動画をインデックス化中...
処理内容:
- Gemini 2.5 Flashが動画を視聴・分析
- 意味のある単位(セグメント)に分割
- 論理的なチャプター構造を構築
- 各部分の説明文を生成
⏱️ 所要時間: 動画の長さに応じて30秒〜数分
完了すると「✅ 動画のインデックス化が完了しました!」と表示されます。
左カラムに2つのビューが表示されます:
-
動画プレーヤー
- アップロードした動画を再生
- 通常の動画プレーヤーと同様に操作可能
-
構造ツリー
- 階層的なコンテンツツリーを表示
- 各ノードをクリックして展開/折りたたみ
- 時間範囲と説明文で内容を把握
例: 講義動画の構造ツリー
📹 機械学習入門講座 (00:00〜45:30)
├─ 📂 Chapter 1: イントロダクション (00:00〜05:30)
│ ├─ 📄 講師紹介 (00:00〜02:15)
│ └─ 📄 コース概要 (02:15〜05:30)
├─ 📂 Chapter 2: 教師あり学習 (05:30〜18:45)
│ ├─ 📄 線形回帰 (05:30〜10:20)
│ ├─ 📄 ロジスティック回帰 (10:20〜14:30)
│ └─ 📄 決定木 (14:30〜18:45)
└─ 📂 Chapter 3: 教師なし学習 (18:45〜28:20)
...
右カラムのチャットインターフェースで質問を入力します。
質問の種類と例:
-
概要を把握する質問
Q: "この動画の主なトピックは何ですか?" A: この動画は機械学習の入門講座で、教師あり学習、 教師なし学習、強化学習の3つの主要トピックを カバーしています... -
特定の時間範囲について質問
Q: "03:15から07:30の間に何が説明されていますか?" A: この時間範囲では、線形回帰の基本概念と 数式表現について説明されています。 具体的には... -
特定のトピックを深掘り
Q: "決定木のアルゴリズムについて詳しく教えてください" A: 決定木については14:30〜18:45のセグメントで 説明されています。ID3アルゴリズムを例に、 情報利得の計算方法と... -
比較や関連性を質問
Q: "線形回帰とロジスティック回帰の違いは?" A: 線形回帰(05:30〜10:20)は連続値の予測に使用され、 ロジスティック回帰(10:20〜14:30)は分類問題に 使用されます。主な違いは... -
横断的な質問
Q: "この講座で紹介されているすべてのアルゴリズムをリストアップして" A: 以下のアルゴリズムが紹介されています: 1. 線形回帰 (05:30〜10:20) 2. ロジスティック回帰 (10:20〜14:30) 3. 決定木 (14:30〜18:45) ...
チャットは会話履歴を保持するため、文脈を踏まえた対話が可能です:
Q: "決定木について教えて"
A: 決定木は14:30〜18:45で説明されており...
Q: "それの実装例はありますか?"
A: はい、同じセグメント内でPythonのscikit-learnを
使った実装例が16:20頃に示されています...
Q: "その部分をもっと詳しく"
A: 16:20〜17:45の部分では、DecisionTreeClassifierの
使い方として...
プロジェクトはTaskを使用してタスクを管理しています:
# すべてのタスクを表示
task
# Streamlitアプリを起動
task streamlit:run
# ADK Web UIを起動(エージェント開発用)
task adk-web
# コードフォーマット
task format
# リント(自動修正)
task lint
# 型チェック
task typecheck
# すべてのチェックを実行
task check# 開発依存関係を含めてインストール
uv sync --all-extras開発依存関係には以下が含まれます:
ruff: コードフォーマッターとリンターipykernel: Jupyter Notebook統合
- Google ADK (Agent Development Kit): マルチエージェントシステムの構築
- Gemini 2.5 Flash: 動画分析とAIエージェント
- Streamlit: Webインターフェース
- Pydantic: データバリデーションとスキーマ定義
- uv: 高速なPythonパッケージマネージャー
video_index/
├── app.py # Streamlitアプリのエントリーポイント
├── pyproject.toml # プロジェクト設定と依存関係
├── Taskfile.yml # タスクランナー設定
├── AGENTS.md # ADKエージェント開発ガイド
├── video_index/
│ ├── __init__.py
│ ├── indexer.py # 動画インデックス化ロジック
│ ├── models.py # データモデル定義
│ ├── agent.py # エージェント呼び出しロジック
│ ├── callbacks.py # エージェントコールバック定義
│ └── ui/
│ ├── __init__.py
│ ├── chat.py # チャットUI
│ ├── tree_view.py # ツリービューUI
│ └── assets/
│ ├── tree_script.js # ツリービュー用JavaScript
│ └── tree_styles.css # ツリービュー用CSS
└── README.md
このプロジェクトはオープンソースです。
貢献を歓迎します!プルリクエストを送信する前に、以下を実行してください:
task checkこれにより、コードフォーマット、リント、型チェックが実行されます。