コンテンツにスキップ

動画・音声解析基盤 完全実装仕様書

[!NOTE] 最新の実装状況は 機能実装ステータス (Remaining Functionality) を参照してください。

目的: 本ドキュメントは evospikenet におけるマルチモーダル(映像+音声)時系列解析基盤を完全実装するための仕様書である。PoC ではなく、本番運用を想定した要件、アーキテクチャ、モジュール分割、性能目標、テスト基準、デプロイ要件、プライバシー/セキュリティ要件、および段階的実装計画を含む。

対象読者: 開発者、ML エンジニア、SRE、プロダクトオーナー

概略要件 - 処理対象: 単一/複数人物の動画(フレーム列)と同一録音トラック(wav)を入力とする。リアルタイム(ストリーミング)とバッチ両方に対応。 - 出力: 時系列イベント(トラックID, タイムスタンプ, アクションラベル, 信頼度)、ASR 字幕(タイムスタンプ付き)、マルチモーダル統合タイムライン、自然言語要約(短文) - 可用性: 99.5% (サービス SLA)、スケーラビリティ: 水平スケールで N ノード対応 - レイテンシ目標: 同期 API(小入力): - P95 < 2s(軽量 backends/fallback) - GPU 加速時 P95 < 300ms(小バッチ)

非機能要件 - モジュール化: 各処理(pose/tracking/action/asr/fusion/summary)はバックエンド差し替え可能なプラグイン形式 - リソース管理: GPU/CPU/メモリの割当制御、batching、バックプレッシャ対応 - 耐障害性: ジョブ再試行、inflight 再キュー、永続化ストア(Redis/SQLite/JSON フォールバック) - 可観測性: メトリクス(処理遅延、スループット、成功率)、トレース、ログ(構造化) - プライバシー: 顔/個人識別情報の匿名化オプション、データ保存ポリシー、同意管理

アーキテクチャ概観 - 入力層: アップロード/ストリーム受信(HTTP/GRPC)、受信時にメタデータ付与 - ワーカー層: ジョブキュー(Redis/Celery または VideoAnalysisJobStore)+ワーカー群(同期/非同期) - バックエンド層: モデルランタイムプラグイン (Torch/TensorRT/ONNX Runtime/Python fallback) - 集約層: EventFusionEngine + SummaryGenerator(LLM ラッパーまたはテンプレート) - API 層: 同期分析エンドポイント(/api/video-analysis/analyze)、非同期ジョブ API(/api/video-analysis/submit/status/result) - ストレージ: 入力アーティファクト(オプション)、結果キャッシュ、ジョブメタ(Redis/SQLite)

主要コンポーネント(機能項目) 各項は「完成実装」を目指す内容。優先度は P0/P1/P2 を併記。

1) データ受け入れ & 前処理(P0) - HTTP/GRPC/Multipart アップロードエンドポイント - ストリーミング ingestion(chunked フレーム/音声) - 入力検証(解像度、サンプルレート、長さ制限) - 前処理: フレーム正規化、音声正規化、サンプリング、切り出し

2) キーポイント抽出モジュール pose(P0) - バックエンド: MoveNet / MediaPipe / ONNX MoveNet / TensorRT エクスポート - API: estimate(frame) -> List[Pose](timestamp, keypoints(dict{name:[x,y,conf]})) - 要件: バッチ/ストリーミング両対応、GPU 有無で最適化、deterministic な fallback - 性能: 1080p で 30fps を継続処理できるスループット(GPU 時)

3) トラッキングモジュール tracking(P0) - アルゴリズム: DeepSORT / IoU ベース トラッカー(選択可能) - API: update(detections, timestamp) -> List[Tracked](track_id, bbox, keypoints) - 再識別(ReID)プラグインをサポート - ロバストネス: 遮蔽復帰、短期 ID 継続

4) 行為認識モジュール action_recognition(P0) - モデル: ST-GCN / TCN / 軽量 3D-CNN をサポート - API: classify(tracked_sequence) -> List[ActionEvent](track_id, start, end, label, score) - スライディングウィンドウ推論、オンライン更新

5) ASR モジュール asr(P0) - バックエンド: Whisper (small/medium), Kaldi/other、ONNX 等 - API: transcribe(audio_chunk) -> Transcript(segments with timestamps, confidence) - スピーカーダイアリゼーション/重ね話対策(プラグイン)

6) イベント融合エンジン fusion(P0) - タイムライン同期:映像イベントと ASR セグメントを統合 - トリガー抽出: 重要イベント抽出(しきい値、ルール、ML ベース) - 出力フォーマット: timeline, summary_candidates, metrics

7) 要約生成 summary(P1) - 軽量テンプレート要約 + LLM ベース要約プラグイン - API: generate_summary(timeline, transcript) -> str(多言語サポート)

8) 永続化ジョブストア & ワーカー(P0) - 高信頼ジョブストア: Redis primary, SQLite persistent fallback, JSON fallback - ワーカープール: 再起動時の inflight 回復、ジョブ優先度、再試行ポリシー - モニタリング: queue length, worker health, processing_latency

9) バックエンド管理 & プラグインフレームワーク(P0) - バックエンド登録 API: register_backend(name, capabilities) - ランタイム切替: GPU/CPU/FP16/INT8 の選択、モデルキャッシュ - ヘルスチェック / 自動フェイルオーバー

10) API 層(P0) - 同期: /api/video-analysis/analyze(短時間バッチ) - 非同期: /api/video-analysis/submit, /api/video-analysis/status/{id}, /api/video-analysis/result/{id} - 認証: API Key / OAuth2 / RBAC

11) テスト & 評価(P0) - 単体テスト: 各モジュールの deterministic edge cases - 統合テスト: 小サンプル動画 end-to-end(mAP/IDF1/WER) - 性能テスト: スループット、レイテンシ、スケーリング試験 - データ品質テスト: ASR WER レポート、IDF1

12) プライバシー & セキュリティ(P0) - 顔/音声匿名化フィルタ(オプション) - 保管暗号化(DataAtRestEncryption)、転送時 TLS - 同意/削除 API、ログ最小化

13) デプロイ & オーケストレーション(P1) - Docker + Kubernetes マニフェスト、GPU ノード設定 - Horizontal Pod Autoscaler 用のメトリクス出力(custom metrics) - Canary / Blue-Green デプロイ戦略、モデルホットスワップ

14) 可視化 / フロントエンド(P1) - タイムライン可視化、トラック可視化、要約ビュー - WebSocket または SSE によるリアルタイム更新

受け入れ基準(例) - 単体テスト網羅率: モジュールごとに 90% 以上(重要ロジック) - 統合 E2E: サンプル動画で pipeline が成功し、IDF1 >= 0.60(簡易データ)、WER <= 0.30(雑音少) - レイテンシ: 軽量 fallback で P95 < 2s、GPU 環境で P95 < 300ms - セキュリティ: データ保存時に AES-256-GCM を使用、削除 API がリクエストで動作

段階的実装計画(短期→中期) Phase 1 (2週): 基本 API、ジョブキュー、pose fallback、job store、ユニットテスト Phase 2 (3週): トラッキング、簡易 action_recognition、ASR fallback、fusion, simple summary Phase 3 (4週): 本格モデル統合(MoveNet/Whisper/ST-GCN)、GPU 最適化、性能チューニング Phase 4 (継続): プライバシー強化、K8s デプロイ、監視・SLO 達成

開発・CI 要件 - requirements.txt に optional extras: video[torch], onnxruntime-gpu, whisper, opencv-python-headless, redis, fastapi[all] などを追加管理 - CI: GPU を必要とするテストはラベル付け、CPU フォールバックのテストは常時実行

ドキュメント配置 - 仕様書: Docs/VIDEO_AUDIO_ANALYSIS_SPEC.md(本ファイル) - 実装チェックリスト: docs/implementation/video_analysis_checklist.md(実装進捗とファイル証跡を連携)


実装状況(2026-04-24 更新)

実装済みモジュール一覧

以下のモジュールがすべて evospikenet/video_analysis/ に実装済みです。

モジュール ファイル フェーズ 状態
ポーズ推定 (fallback) pose.py Phase 1 ✅ 完了
トラッキング (IoU) tracking.py Phase 1 ✅ 完了
行動認識 (位置差分) action_recognition.py Phase 1 ✅ 完了
ASR ラッパー asr.py + asr_policy.py Phase 1 ✅ 完了 (fallback)
イベント融合 fusion.py Phase 1 ✅ 完了
ジョブキュー job_queue.py Phase 1 ✅ 完了
バックエンド管理 backends.py + backends_real.py Phase 2 ✅ 完了
Celery ワーカー worker.py Phase 2 ✅ 完了
プライバシー処理 privacy.py Phase 2 ✅ 完了
評価指標 metrics.py + runtime_metrics.py Phase 2 ✅ 完了
統一イベントスキーマ event_schema.py Phase 3 2026-04-24 新規
ショット境界検出 shot_boundary_detector.py Phase 3 2026-04-24 新規
VAD・話者分離 vad.py Phase 3 2026-04-24 新規
単眼深度推定 depth_estimation.py Phase 3 2026-04-24 新規
空間関係抽出 spatial_relations.py Phase 3 2026-04-24 新規
ナラティブ生成 narrative_generator.py Phase 3 2026-04-24 新規
時系列行動ローカリゼーション temporal_action_localizer.py Phase 3 2026-04-24 新規
パイプライン統合 pipeline.py (enable_extended) Phase 3 2026-04-24 更新

新規モジュール詳細

event_schema.py — 統一イベントスキーマ

  • Actor(id, type, attributes, bbox, keypoints, track_id)
  • SpatialFrame(type, coords, depth_m, relation_desc)
  • EventEvidence(detection_ids, transcript_snippet, frame_indices, pose_refs)
  • Event — dict ベースファクトリ: from_vision_detection(det, timestamp), from_asr_segment(seg), from_scene_change(frame_idx, timestamp)
  • AnalysisTimelinesorted_events(), filter_by_type(), filter_by_confidence(), to_dict()

shot_boundary_detector.py — ショット境界検出

  • 手法: ヒストグラム差分 / ピクセル差分 / 複合 (選択可能)
  • ShotBoundaryDetector(threshold, method, min_scene_len).detect(frames, fps) → [(frame_idx, timestamp), ...]
  • detect_scores() でスコア付き出力も可能

vad.py — VAD・話者分離

  • VoiceActivityDetector(energy_threshold, frame_duration_ms, merge_gap_s, min_speech_s)
  • detect(audio_wave, sample_rate) → [{"start", "end", "energy"}, ...]
  • SpeakerDiarizer(max_speakers) — pyannote.audio 置換フック

depth_estimation.py — 単眼深度推定

  • フォールバック: 輝度勾配ベース疑似深度マップ
  • 本番フック: torch.hub.load("intel-isl/MiDaS", "MiDaS_small")
  • DepthEstimator.estimate(frame) → {"depth_map": ndarray(H,W), "depth_at_center": float, "backend": str}
  • estimate_depth_at_bbox(frame, bbox) → float

spatial_relations.py — 空間関係抽出

  • get_spatial_relation(obj_a, obj_b, depth_a, depth_b) → str
  • 戻り値: left_of / right_of / above / below / in_front_of / behind / near / touching / unknown
  • extract_pairwise_relations(detections, depth_maps) → [{"subject_id", "object_id", "relation", "confidence"}, ...]
  • MotionVectorEstimator — トラック履歴から速度ベクトル・方向を付加

narrative_generator.py — ナラティブ生成

  • NarrativeGenerator(use_lm, max_events, min_confidence).generate(timeline) → str
  • テンプレートモード(デフォルト): "At {ts}s, {actor} is detected {action} (confidence {conf}%)"
  • LM モード: NeuralLanguageAdapter 経由で EvoSpikeNet LM を呼び出し、失敗時はテンプレートにフォールバック
  • generate_shot_summary(shot_start, shot_end, events, relations) → str

temporal_action_localizer.py — 時系列行動ローカリゼーション

  • TemporalActionLocalizer(window_size, stride, min_confidence, nms_overlap_threshold)
  • localize(frames, fps) → [{"start", "end", "action", "confidence"}, ...]
  • localize_with_poses(frames, pose_results, fps) → [...] — キーポイント変化量ベース
  • Temporal IoU NMS で重複除去

VideoAnalysisPipeline 更新内容

pipeline = VideoAnalysisPipeline(
    pose_backend="fallback",
    action_backend="fallback",
    asr_backend="fallback",
    depth_backend="fallback",
)
result = pipeline.run(frames, audio_wave, fps=10.0, enable_extended=True)
# result には以下が追加:
#   shot_boundaries, vad_segments, temporal_segments,
#   depth_sample, spatial_relations, narrative

テスト状況

テストファイル テスト数 状態
tests/unit/test_video_analysis_new_modules.py 62 ✅ 全通過
tests/unit/test_video_analysis_components.py 15 ✅ 全通過
tests/unit/test_video_analysis_metrics.py 1 ✅ 全通過
tests/unit/test_video_analysis_backends.py 1 ✅ 全通過
合計 82

EvoSpikeNet LM バックエンドへの切り替えガイド(2026-04-24)

パイプラインには 2 つの独立した LM 経路 があります。

経路 A: lm_summary(パイプライン全体の要約)

VideoAnalysisPipeline.run() が返す lm_summary キー。
EvoLMBackendAutoModelSelector.get_model("text")SpikingEvoTextLM を使用します。

制御方法

方法 設定例 効果
コンストラクタ引数 VideoAnalysisPipeline(lm_backend="evospikenet_lm") デフォルト。SpikingEvoTextLM を使用
環境変数で無効化 VIDEO_ANALYSIS_ENABLE_LM=0 lm_summary="", lm_backend=None になる
環境変数で有効化 VIDEO_ANALYSIS_ENABLE_LM=1 (デフォルト) LM を起動して要約を生成
import os
os.environ["VIDEO_ANALYSIS_ENABLE_LM"] = "1"  # または "0" で無効化

from evospikenet.video_analysis.pipeline import VideoAnalysisPipeline

pipeline = VideoAnalysisPipeline(lm_backend="evospikenet_lm")
result = pipeline.run(frames, audio_wave, fps=25.0)
print(result["lm_summary"])   # "人物が歩いています。" など
print(result["lm_backend"])   # "evospikenet_lm"

バックエンドスタック(経路 A)

pipeline.run()
  └─ EvoLMBackend.generate(prompt, max_new_tokens=40, temperature=0.6)
       └─ AutoModelSelector.get_model("text")
            └─ SpikingEvoTextLM.generate(input_ids, max_new_tokens)

経路 B: narrative(時系列ナラティブ生成)

pipeline.run(enable_extended=True) 時の narrative キー。
NarrativeGenerator_LMBridgeEvoLMBackendSpikingEvoTextLM を使用します。

動作フロー

NarrativeGenerator.generate(timeline)
  ├─ テンプレート文を組み立て (事前計算)
  ├─ use_lm=True の場合: _LMBridge.generate(prompt, max_new_tokens=200)
  │    └─ EvoLMBackend.generate(prompt, max_new_tokens=200)
  │         └─ SpikingEvoTextLM.generate(...)
  └─ LM 出力が 20 文字未満 or None → テンプレートフォールバック

制御方法

方法 設定例 効果
デフォルト(推奨) NarrativeGenerator(use_lm=True) LM 優先、失敗時テンプレート
LM 無効化 NarrativeGenerator(use_lm=False) 常にテンプレート
パイプライン経由 VideoAnalysisPipeline() use_lm=True がデフォルト設定済み
from evospikenet.video_analysis.narrative_generator import NarrativeGenerator

# LM を使ったナラティブ生成
gen = NarrativeGenerator(use_lm=True, max_events=15, min_confidence=0.3)
text = gen.generate(timeline)
print(text)

# ショット単位の要約
shot_text = gen.generate_shot_summary(
    shot_start=0.0, shot_end=5.0,
    events=timeline.filter_by_confidence(0.5),
    relations=[{"subject_id": 0, "object_id": 1, "relation": "left_of", "confidence": 0.8}],
)

バックエンド可用性の確認

from evospikenet.video_analysis.backends import get_backend_status

status = get_backend_status()
print(status["lm"])
# {'evospikenet_lm': {'available': True, 'tier': 'real',
#                     'note': 'local SpikingEvo models via AutoModelSelector'}}

よくある問題と対処

症状 原因 対処
lm_summary が空文字 VIDEO_ANALYSIS_ENABLE_LM=0 が設定されている 環境変数を 1 に変更
narrative がテンプレート文になる _LMBridge のロード失敗 torch インストール確認 (pip install torch)
lm_backendNone EvoLMBackend 初期化失敗(依存ライブラリ不足) pip install torch transformers
LM 出力が短すぎる/意味不明 SpikingEvoTextLM が未学習状態 学習済みモデルで AutoModelSelector のウェイトを差し替える

ウェイト差し替えとモデルカスタマイズ

SpikingEvoTextLMAutoModelSelector.get_model("text") でロードされます。
学習済みウェイトを使いたい場合は tools/train_spiking_lm.py で事前学習してください。

# 学習
python tools/train_spiking_lm.py --node-type text --epochs 10

# 推論確認
python -c "
from evospikenet.llm_backend import EvoLMBackend
lm = EvoLMBackend(task_type='text')
print(lm.generate('Events: walking:3. 日本語で一文で要約してください。', max_new_tokens=40))
"

残課題(Phase 4)

機能 優先度 担当モジュール
ByteTrack/DeepSORT 本番 MOT tracking.py / backends.py
MediaPipe/OpenPose 本番ポーズ MoveNetRealPoseBackend
TimeSformer/SlowFast 実モデル STGCNRealActionBackend
pyannote.audio 話者分離 vad.py (SpeakerDiarizer)
SAM/Mask R-CNN セグメンテーション 新規モジュール予定
TensorRT/ONNX GPU 最適化 backends.py
WebSocket リアルタイム API video_analysis_api.py
アノテーション UI 別ツール

作成日: 2026-04-19 更新日: 2026-04-24 作成者: エンジニアリングチーム