关于 vss-search-index
通过 Video Search & Summarization 应用搜索已索引视频库的操作技能,涵盖视频导入、生成嵌入、自然语言查询及持久化监控搜索。
主要功能
- 01初始化或复用 VSS 检出目录
- 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 源代码是否已在工作区中,这些命令都适用。
运行捆绑的引导程序。它会先尝试查找现有的 VSS 检出版本——从当前目录向上查找并检查外层 git 仓库——找到后便会复用,绝不会重新克隆。只有在找不到检出版本时,才会从 main 浅克隆单分支,并稀疏检出仅包含 sample-applications/video-search-and-summarization 的内容。它会在 stdout 中输出解析后的应用根目录:
# 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。如需从 fork/分支拉取,或复用指定的检出目录,请在运行前覆盖 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),也可以是绝对时间(start/endISO-8601)。请参阅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>"