VSS の Event Reviewer で映像をリアルタイム監視してみた

VSS の Event Reviewer で映像をリアルタイム監視してみた

2026.03.10

はじめに

こんにちは、クラスメソッド製造ビジネステクノロジー部の森茂です。

以前の記事では VSS(Video Search and Summarization)の Standard VSS を DGX Spark にデプロイし、蓄積映像の検索と日本語 Q&A を試しました。前回は 3.0.0 EA の Warehouse Blueprint で、マイクロサービス化されたアーキテクチャを先行体験しています。

今回は VSS 2.4.1 GA のもう一つのデプロイモード「Event Reviewer」を使い、カメラ映像のリアルタイム監視環境を構築してみました。Standard VSS が「録画映像を後から検索する」ツールだとすれば、Event Reviewer は「今この瞬間の検出イベントを自動検証する」ツールです。

コンベアベルト

GroundingDINO による物体検出でコンベアベルト上の段ボール箱を検知し、VLM(Cosmos-Reason2-8B)が映像を見て「箱に損傷があるか?」を判定する。この CV + VLM の二段構えを、DGX Spark 1 台で動かします。

Event Reviewer とは

Standard VSS との違い

VSS には Standard VSS と Event Reviewer の 2 つのデプロイモードがあります。前回の記事で使った Standard VSS は映像をアップロードすると VLM でキャプションを生成し、ベクター DB とグラフ DB にインデックスして後から自然言語で検索できるようにするものでした。

Event Reviewer は発想が違います。CV パイプライン(物体検出モデル)が「何か検出した」というイベントをトリガーに、VLM が短いクリップ映像を確認して「本当にそうか?」を判定する。いわば、CV の検出結果を VLM がダブルチェックする仕組みです。

VSS Event Reviewer Architecture
出典: VSS Blueprint Architecture — NVIDIA Documentation

公式のアーキテクチャ図を見ると、左から CV Pipeline Manager UI → CV Pipeline(GroundingDINO 等)→ Alert Bridge → VLM → Alert Inspector UI という流れが分かります。Video Storage Toolkit(VST)がクリップの保管を担当し、各コンポーネント間は REST API と Redis Streams で繋がっています。

製造業の現場をイメージすると、使い分けはこうなります。

Standard VSS は事後分析型です。1 週間分の製造ラインの映像から「製品が落下した場面」を検索して原因を分析するような用途に向いています。VLM に加えて LLM と RAG のフルスタックが必要で、コンテナ数も多くなります。

Event Reviewer はリアルタイム監視型です。コンベアベルト上の段ボール箱を検知したら、VLM が映像を確認して「損傷があるか?」を判定する。作業者の安全装備チェックにも使えます。RAG は不要で、VLM だけで動くため軽量です。

項目 Standard VSS(V1 で検証) Event Reviewer(今回)
用途 蓄積映像の検索と Q&A リアルタイムのイベント検証
処理方式 バッチ(アップロード → インデックス → 検索) イベントドリブン(検出 → クリップ → VLM 判定)
モデル構成 VLM + LLM + Embedding + Reranker + RAG CV(GroundingDINO)+ VLM のみ
主な UI Standard VSS Web UI(:9100) Alert Inspector UI(:7860)+ CV UI(:7862)
DGX Spark での負荷 高(メモリ 95GB 以上) 低(GPU 使用率 1-37%)

コンポーネント構成

Event Reviewer は 2 つの Docker Compose で構成されます。

Event Reviewer 本体(deploy/docker/event_reviewer/)は 6 サービスです。中核となるのは via-server(VLM 推論)、Alert Bridge(イベントの取り込みと VLM への振り分け)、Alert Inspector UI(レビュー画面)の 3 つ。残りの storage-ms(Video Storage Toolkit)がクリップの保管、Redis がイベントバス、api-gateway が Nginx リバースプロキシを担当します。

CV パイプライン(examples/cv-event-detector/)は 2 サービスで、nv-cv-event-detector が GroundingDINO による物体検出とクリップ生成を担当し、cv-ui が検出設定の操作画面を提供します。

合計 8 コンテナです。前回の 3.0.0 EA(Warehouse Blueprint)が 42 コンテナだったことを考えると、かなりコンパクトです。

全体のデータフローを図にすると以下のようになります。

Blueprint が提供するのは緑と青の部分まで。赤の外部連携は Redis Streams や WebSocket から読み取って自前で実装する設計です。

DGX Spark に Event Reviewer をデプロイする

前提条件

項目 要件
DGX OS 7.2.3 以上
GPU ドライバー 580.95.05 以上
NGC API Key NGC コンテナレジストリアクセス用
HuggingFace Token Cosmos-Reason2-8B アクセス用
ストレージ /tmp/ に 10GB 以上の空き

VSS は GitHub でオープンソースとして公開されている NVIDIA AI Blueprint です。まずリポジトリをクローンします。

git clone https://github.com/NVIDIA-AI-Blueprints/video-search-and-summarization.git
cd video-search-and-summarization

Event Reviewer の起動

Event Reviewer のデプロイパスは Standard VSS とは別で、deploy/docker/event_reviewer/ にあります。

cd deploy/docker/event_reviewer

# キャッシュクリーナー起動(DGX Spark の ARM 環境で推奨)
sudo sh ../scripts/sys_cache_cleaner.sh &

# Docker ネットワーク作成(CV パイプラインと共有)
docker network create vss-shared-network

# VST ボリュームのクリア
rm -rf vst/vst_volume/*

# 起動(DGX Spark は IS_SBSA=1 が必要)
IS_SBSA=1 ALERT_REVIEW_MEDIA_BASE_DIR=/tmp/alert-media-dir docker compose up -d

IS_SBSA=1 は前回・前々回と同じく、DGX Spark(ARM64 / SBSA)でコンテナイメージのサフィックスを -sbsa に切り替えるフラグです。ALERT_REVIEW_MEDIA_BASE_DIR は CV パイプラインが生成するクリップの保存先で、Event Reviewer と CV パイプラインの両方がマウントする共有ディレクトリです。

ここで一つ注意点があります。via-server は Cosmos-Reason2-8B(約 17GB)のダウンロードと vLLM のロードに時間がかかるため、初回は healthcheck が通るまで数分かかります。alert-bridge と alert-inspector-ui は via-server の health に依存しているので、via-server が unhealthy な状態で docker compose up -d を実行すると Created のまま止まることがありました。

# via-server の起動を待つ
docker compose logs -f via-server | grep -i "health\|ready"

# healthy になったら再度 up(alert-bridge と UI が起動する)
IS_SBSA=1 ALERT_REVIEW_MEDIA_BASE_DIR=/tmp/alert-media-dir docker compose up -d

2 回目以降は Docker ボリューム(event_reviewer_via-hf-cache)にモデルがキャッシュされるため、vLLM ロード完了まで約 80 秒で済みます。

全サービスが起動したら確認しましょう。

docker compose ps

6 つのサービスすべてが running (healthy) になっていれば OK です。

Alert Inspector UI にアクセス

ブラウザで http://<DGX Spark の IP>:7860 を開くと、Alert Inspector UI にアクセスできます。

Gradio ベースの UI で、アラートのテーブル一覧、映像プレビュー、VLM とのチャット機能が統合されています。この時点ではまだ CV パイプラインを起動していないので、アラートは空の状態です。

CV パイプラインで物体検出を有効化する

GroundingDINO とは

Event Reviewer 本体はデフォルトで CV パイプラインが無効化(DISABLE_CV_PIPELINE=true)されています。CV パイプラインは別ディレクトリ examples/cv-event-detector/ で独立して起動します。

このサンプルパイプラインでは GroundingDINO(swin_tiny)をオープンボキャブラリの物体検出モデルとして使います。「オープンボキャブラリ」というのは、事前に定義されたクラスリスト(人、車、犬……)に縛られず、テキストプロンプトで任意のオブジェクトを検出できるということです。「cardboard box .」と書けば段ボール箱を、「Person . Hard hat .」と書けば人とヘルメットを検出してくれます。

CV パイプラインの起動

cd ~/video-search-and-summarization/examples/cv-event-detector

IS_SBSA=1 ALERT_REVIEW_MEDIA_BASE_DIR=/tmp/alert-media-dir docker compose up -d

nv-cv-event-detector コンテナは初回起動時に GroundingDINO の ONNX モデルを TensorRT FP16 エンジンに変換します。ARM SBSA 環境では strongly typed mode にフォールバックしますが、動作には問題ありません。

起動が完了したら、CV UI にアクセスします。

CV UI で映像を処理する

http://<DGX Spark の IP>:7862 を開くと、Computer Vision Pipeline Manager(CV UI)が表示されます。

CV UI のスクリーンショット

今回は V1/V2 で使った倉庫映像ではなく、サンプルに含まれているコンベアベルト検品映像(conveyor_belt_inspection_sdg_1080p.mp4)を使います。NVIDIA の合成データ生成ツール(SDG)で作られた 1080p 30fps の映像で、青いフレームのベルトコンベア上を段ボール箱が流れていく様子が映っています。

CV UI では以下のように設定しました。

Detection Parameters では検出クラスに cardboard box を指定します。GroundingDINO がベルトコンベア上の段ボール箱を検出し、検出数が Object Detection Threshold を超えるとイベントクリップが生成されます。

VSS Alert Parameters では Enable Yes/No Verification を ON にし、Alert Prompts に検品用のプロンプトを設定します。

You are a warehouse conveyor belt inspection system. You must inspect the
cardboard box on the conveyor belt to look for signs of physical damage.
Physical damage includes Crumpling, Tearing, Dents, Creases, Open boxes.
Does the cardboard box clearly show signs of physical damage?

「Process Video」を押すと、GroundingDINO が映像を解析してイベントクリップを生成します。82 秒のコンベアベルト映像から 38 件のイベントクリップが生成されました(処理時間は約 28 分)。生成されたクリップは自動的に Alert Bridge に送信され、VLM(Cosmos-Reason2-8B)が 1 件ずつ「段ボール箱に損傷があるか?」を判定していきます。

Alert Inspector UI で検証結果を確認する

Alert Inspector UI に戻ると、VLM の検証結果がテーブルに表示されています。

Alert Inspector UI アラート一覧のスクリーンショット

結果を見ると、VLM が損傷のある箱とない箱をそれぞれ判別しています。VLM Response が「Yes」なら段ボール箱に物理的損傷あり(Alert Result: True)、「No」なら損傷なし(Alert Result: False)です。True のアラートだけを管理者に通知する運用が想定されています。

チャット機能で映像について質問する

Alert Inspector UI にはチャット機能も組み込まれています。映像を選択した状態で質問を入力すると、Cosmos-Reason2-8B が映像の内容を分析して回答してくれます。

チャット機能

日本語での質問にも対応しています。「日本語で状況を教えてください」と入力したところ、「カーブしたコンベアベルトの始点に、茶色の紙袋が置かれます。次に、紙袋はベルト上を移動し始めます」と映像の状況を時系列で説明してくれました。段ボール箱を「紙袋」と表現しているのは合成映像の見え方によるものかなと思いますが、ベルト上の物体の動きは正確に捉えています。アラート検証は英語の Yes/No 判定ですが、チャットでは日本語で質問しても答えてくれます。

RTSP ライブストリームに切り替える

MediaMTX で RTSP サーバーを立てる

ここまではサンプル映像のファイル処理でしたが、実運用を想定して RTSP ライブストリームに切り替えてみましょう。

今回はカメラの代わりに、MediaMTX と ffmpeg でサンプル映像を RTSP ストリームとして配信します。

# MediaMTX RTSP サーバーを起動
docker run --rm -d --name mediamtx -p 8554:8554 bluenviron/mediamtx:latest

# コンベアベルト映像をループ再生で RTSP 配信
ffmpeg -re -stream_loop -1 -i conveyor_belt_inspection_sdg_1080p.mp4 \
  -c copy -f rtsp rtsp://localhost:8554/conveyor

-stream_loop -1 で無限ループ、-re でリアルタイムレートでの配信です。これで rtsp://<host-ip>:8554/conveyor に RTSP ストリームが常時配信されます。

ライブ映像でリアルタイム検出

CV UI で RTSP URL を指定すると、ライブ映像のリアルタイム処理が始まります。デフォルトの 10 秒間隔で映像を取得し、GroundingDINO で検出 → クリップ生成 → Alert Bridge 送信 → VLM 検証というフルフローが動きます。

ファイル処理と違い、ライブストリームでは検出イベントが継続的に発生します。Alert Inspector UI をリロードすると、新しいアラートがどんどん追加されていく様子が確認できます。

リソース使用量を確認する

Event Reviewer + CV パイプラインが動いている状態で、DGX Spark のリソース使用量を確認してみました。

項目 前回(3.0.0 EA) 今回(2.4.1 Event Reviewer)
コンテナ数 42 8(Event Reviewer 6 + CV 2)
GPU メモリ 84GB / 128GB(66%) 45GB / 128GB(35%)
GPU 使用率 高負荷 1 - 37%
GPU 温度 49°C
GPU 消費電力 25W

前回の 3.0.0 EA では 42 コンテナが 128GB 中 84GB を消費し、DGX Spark がかなりギリギリの状態でした。今回の Event Reviewer は 8 コンテナで GPU 使用率も低く、余裕を持って動作しています。

これは Event Reviewer が RAG スタック(LLM、Embedding、Reranker、Milvus、Neo4j 等)を使わないためです。VLM 1 つと CV モデル 1 つだけなので、リソース消費が段違いに少なくなっています。チャットのレスポンスも体感で数秒と快適でした。

Alert Bridge API の詳細

ここまでは CV UI を通じたフローでしたが、Alert Bridge は REST API も提供しています。独自の検出システムや外部の IoT センサーからアラートを送信するケースを想定した API です。

アラート送信 API

POST http://localhost:9080/api/v1/alerts にアラートを JSON で送信します。

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "@timestamp": "2026-03-08T19:50:00Z",
  "sensor_id": "conveyor-cam-1",
  "video_path": "/tmp/alert-media-dir/clip.mp4",
  "alert": {
    "type": "package_damage",
    "description": "Cardboard box with potential damage detected",
    "severity": "medium",
    "status": "REVIEW_PENDING"
  },
  "event": {
    "type": "object_detection",
    "description": "Cardboard box detected on conveyor belt"
  },
  "vss_params": {
    "num_frames_per_chunk": 8,
    "vlm_params": {
      "prompt": "Does the cardboard box clearly show signs of physical damage such as crumpling, tearing, dents, creases, or being open? Answer Yes or No.",
      "system_prompt": "You are a warehouse conveyor belt inspection system.",
      "max_tokens": 200,
      "temperature": 0.3
    }
  }
}

API のハマりポイント

実際に API を叩いてみると、ドキュメントには明記されていないバリデーションルールがいくつかありました。同じ罠にハマる方のために整理しておきます。

ハマりポイント 原因 対処
id のバリデーションエラー via-server が UUID 形式を要求 UUID v4 形式で送信する
alert.severityalert.status が必須 ドキュメントに記載なし severity は high/medium/low、statusREVIEW_PENDING を指定
event.confidence で "Extra inputs not permitted" via-server のスキーマが strict event オブジェクトに confidence を含めない
VLM が prompt を取得できない vss_params.prompt ではなく vss_params.vlm_params.prompt にネスト必要 上記の JSON のように vlm_params の中に入れる

特に最後のプロンプトのネストが分かりにくかったです。vss_params 直下に prompt を書くと null として扱われ、デフォルトプロンプト(alert_request_defaults.yaml で定義)にフォールバックします。カスタムプロンプトを使いたい場合は vlm_params.prompt に指定します。

プロンプト管理 API

Alert Bridge にはプロンプトを事前登録して管理する API もあります。

# アラートタイプごとのプロンプトを登録
curl -X POST http://localhost:9080/api/v1/prompts \
  -H "Content-Type: application/json" \
  -d '{
    "alert_type": "package_damage",
    "prompt": "Does the cardboard box clearly show signs of physical damage? Answer Yes or No.",
    "system_prompt": "You are a warehouse conveyor belt inspection system."
  }'

プロンプトの優先順位は「リクエスト内 > 登録済みプロンプト > デフォルト設定」です。検品ラインであれば、段ボール箱の損傷、ラベルの欠落、向きの異常など、アラートタイプごとに検証プロンプトを事前登録しておくのが実用的でしょう。

検証結果の出力と外部連携

ここで気になるのが「VLM の検証結果をどうやって外部システムに通知するか?」です。

Alert Bridge の config.yaml を見ると、VLM 検証結果の出力先は Redis Streams です。

redis_sink:
  streams:
    enhanced_anomaly_stream: 'alert-bridge-enhanced-stream'
    incidents_stream: 'alert-bridge-incidents-stream'

VLM が判定を終えると、結果は alert-bridge-enhanced-streamalert-bridge-incidents-stream に書き込まれます。リアルタイムで受け取りたい場合は WebSocket(ws://localhost:9080/ws/alerts)も使えます。Alert Inspector UI は内部的にこの WebSocket を使って画面を更新しています。

一方、Slack 通知やメールアラート、PagerDuty 連携のような「外部サービスへの通知」は Blueprint には含まれていません。Redis Streams から読み取って自前で実装するか、config.yaml の sinkTypekafka に切り替えて Kafka Connect 経由で各種 SaaS に繋ぐ形になります。

Standard VSS 側には notification_tool というコールバックエンドポイントの仕組みがありますが、Event Reviewer では使われていません。Blueprint はあくまで「検出 → VLM 検証 → 結果のストリーム出力」までを提供していて、その先のアクション(通知、チケット起票、ラインの自動停止など)は利用者に委ねる設計です。逆に言えば、Redis Streams や WebSocket という標準的なインターフェースで出力してくれるので、既存のシステムに組み込む自由度は高いかなと思います。

まとめ

VSS 2.4.1 GA の Event Reviewer を DGX Spark にデプロイし、GroundingDINO による物体検出から VLM 検証までのリアルタイム監視パイプラインを動かしました。

Standard VSS が「蓄積映像を後から検索する」ツールだとすれば、Event Reviewer は「CV 検出イベントをリアルタイムで VLM が検証する」ツールです。RAG スタックが不要なぶん軽量で、DGX Spark 1 台で 8 コンテナ、GPU 使用率 1-37% と余裕を持って動作します。3.0.0 EA の 42 コンテナ構成と比べると、この軽さは地味にありがたいですね。

GroundingDINO のオープンボキャブラリ検出もなかなか便利で、テキストプロンプトを変えるだけで検出対象を柔軟に切り替えられます。固定クラスのモデルと違い、「今日はこの製品の外観を見たい」という要望にも再学習なしで対応できるのは、PoC 段階では大きなメリットかなと思います。

個人的に気に入ったのは Alert Bridge の API 設計です。REST API で外部からアラートを投入でき、プロンプト管理 API でアラートタイプごとに検証内容をカスタマイズできる。Blueprint は「そのまま使う完成品」ではなく「カスタマイズの出発点」として設計されていて、独自のユースケースに組み込みやすい構造になっています。

次回は、この Event Reviewer をベースに製造業のユースケースをもう少し深掘りしてみたいと思います。CV パイプラインを Jetson Orin Nano Super に分離してエッジ-サーバー構成を組んだり、ドメイン特化のプロンプト設計でどこまで検品精度を上げられるか試したり。今回の Blueprint を「カスタマイズの出発点」として、実運用に近づけていく検証ですね。

参考リンク

この記事をシェアする

FacebookHatena blogX

関連記事