vss-search-index について
Video Search & Summarization アプリでインデックス済み動画を検索するスキルです。動画の取り込み、埋め込み生成、自然言語検索、保存した検索の管理を扱います。
主な機能
- 01VSS のチェックアウトを準備または再利用
- 02動画のアップロードと確認
- 03検索用埋め込みの生成
- 04テキスト、タグ、時間によるクリップ検索
- 05保存した検索の作成と再実行
活用シーン
- 01自然言語の説明に合う動画クリップの検索
- 02タグや期間でクリップ検索を絞り込み
- 03監視対象の検索による定期的な追跡
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ open-edge-platform/ edge-ai-libraries --skill vss-search-indexインストール後、Claude Code で/vss-search-indexを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
benchmark/benchmark.mdevals/evals.jsonexample-prompts/01-upload-and-index-new-clip.md02-simple-natural-language-search.md03-tag-and-time-filtered-search.md04-reindex-failed-embeddings.md05-find-filenames-for-ranked-clips.md06-persistent-watched-query.md07-bootstrap-fresh-machine.mdREADME.mdreferences/search-request.mdscripts/vss-bootstrap.sh詳細
VSS 検索
インデックス化された動画ライブラリを自然言語で検索します。curl コマンドはご自身で実行し、結果を伝えてください。エンドポイントでは nginx の /manager プレフィックスを使用します。
HOST=http://${HOST_IP:-localhost}:${APP_HOST_PORT:-12345} を設定します。
環境のセットアップ(最初に実行)
このスキルは実際のソースファイルを通じて Video Search & Summarization アプリを操作するため、VSS アプリが存在し、アプリのルートディレクトリからコマンドを実行する必要があります。ほかの作業を始める前に実行してください。VSS のソースがすでにワークスペースにあるかどうかにかかわらず動作します。
同梱のブートストラップを実行します。まず、現在のディレクトリから上位へたどり、親の git リポジトリを調べて既存の VSS チェックアウトを探します。見つかった場合は、再クローンせずに再利用します。チェックアウトが見つからない場合に限り、main から sample-applications/video-search-and-summarization のみを対象に、浅い単一ブランチのスパースチェックアウトを行います。解決されたアプリのルートディレクトリを標準出力に表示します。
# SKILL_DIR is THIS skill's own directory (shown to you when the skill loads);
# in-repo it is .github/skills/vss-search-index. Works the same if the skill is installed standalone.
SKILL_DIR=".github/skills/vss-search-index"
APP_ROOT="$(bash "$SKILL_DIR/scripts/vss-bootstrap.sh")"
cd "$APP_ROOT"
以下のコマンドはすべて、この APP_ROOT を作業ディレクトリとして実行することを前提としています。フォーク/ブランチから取得する場合や、特定のチェックアウトディレクトリを再利用する場合は、実行前に VSS_REPO_URL、VSS_REPO_BRANCH、または VSS_CLONE_DIR を上書きしてください。
前提条件
バックエンドが正常で、検索が有効であることを確認します。まず状態を確認し、そうでない場合は
vss-troubleshoot / vss-deploy を使用してください。
curl -sf "$HOST/manager/health" >/dev/null && \
curl -s "$HOST/manager/app/features" | jq '.search // .'
1. 動画をアップロードする(まだ取り込まれていない場合)
POST /manager/videos — multipart/form-data を使用し、フィールド名は video、tags は任意のカンマ区切りです。ファイルはストリーミング可能な MP4 である必要があります(それ以外はサーバーが拒否します)。
curl -s -X POST "$HOST/manager/videos" \
-F "video=@/path/to/clip.mp4" \
-F "tags=outdoor,daytime" | jq .
# → { "videoId": "<VIDEO_ID>" }
代わりに、既存の動画を一覧表示/確認してください。一覧のレスポンスは { "videos": [...] } というオブジェクトであり、配列そのものではありません。name は生成されたハッシュなので、実際のファイル名には url / dataStore.fileName を使用してください。
curl -s "$HOST/manager/videos" | jq '.videos[] | {videoId, file: .dataStore.fileName}'
curl -s "$HOST/manager/videos/<VIDEO_ID>" | jq '.video' # single record is wrapped under .video
2. 検索用埋め込みを生成する
埋め込みが存在するまで、動画は検索できません。アップロード後、または失敗した処理を再試行する場合に生成を開始します。
curl -s -X POST "$HOST/manager/videos/search-embeddings/<VIDEO_ID>" | jq .
完了するまで待ってから(動画レコードを再確認してから)クエリを実行してください。
3. クエリを実行する
単発のクエリ — POST /manager/search/query。レスポンスは { "results": [ { "query_id", "results": [ … ] } ] } というオブジェクトで、配列そのものではなくラップされています。そのため、ランク付けされたクリップは .results[].results[] にあります。
curl -s -X POST "$HOST/manager/search/query" \
-H 'Content-Type: application/json' \
-d '{
"query": "person wearing a hat",
"tags": "indoor",
"timeFilter": { "value": 7, "unit": "days" }
}' | jq -r '.results[].results[]
| "score=\(.metadata.relevance_score) clip=\(.metadata.segment_start)-\(.metadata.segment_end)s seek=\(.metadata.seek_timestamp)s video_id=\(.metadata.video_id)"'
query(必須):自然言語。tags(任意):カンマ区切り。クエリとの積集合が取られます。timeFilter(任意):相対指定(valueとunit。minutes|hours|days|weeksのいずれか)、または絶対指定(ISO-8601 形式のstart/end)のどちらかを指定します。詳細はreferences/search-request.mdを参照してください。
各クリップの metadata には、relevance_score(0~1。最上位の結果は正確に 1 の場合があります)、video_id、video_url、segment_start / segment_end、seek_timestamp、tags、video_metadata(再生時間/fps)が含まれます。検索モードでは、page_content はキャプションではなく、セグメントの位置情報(「Video segment from Ns to Ms…」)です。
ファイル名は結果に含まれません。metadata には video_id がありますが、video / file_name はありません。クリップのファイル名を表示するには、video_id を動画一覧の .videos[].dataStore.fileName に対応付けてください。
curl -s "$HOST/manager/videos" \
| jq '[.videos[] | {key:.videoId, value:.dataStore.fileName}] | from_entries' > /tmp/idmap.json
curl -s -X POST "$HOST/manager/search/query" -H 'Content-Type: application/json' \
-d '{ "query": "person wearing a hat" }' \
| jq --slurpfile m /tmp/idmap.json -r '.results[].results[]
| "score=\(.metadata.relevance_score) file=\($m[0][.metadata.video_id] // "?") clip=\(.metadata.segment_start)-\(.metadata.segment_end)s"'
上位の結果は、ファイル名、クリップの時間範囲、シーク時刻とともに提示してください。
4. 保存済み/管理対象のクエリ(任意)
curl -s -X POST "$HOST/manager/search" -H 'Content-Type: application/json' \
-d '{"query":"forklift"}' | jq . # create a persistent query → queryId
curl -s "$HOST/manager/search/<QUERY_ID>" | jq . # fetch results
curl -s -X POST "$HOST/manager/search/<QUERY_ID>/refetch" | jq . # re-run
curl -s -X PATCH "$HOST/manager/search/<QUERY_ID>/watch" \
-H 'Content-Type: application/json' -d '{"watch":true}' # auto-refresh
curl -s "$HOST/manager/search/watched" | jq .
curl -s -X DELETE "$HOST/manager/search/<QUERY_ID>"