mcpField
V
video-search

video-search

github.com/video-db其他13913 次安装今天更新
代码仓库

关于 video-search

这是用于定位视频片段并回答视频语音或画面内容问题的 VideoDB 技能。它指导 Agent 通过转录文本搜索,或使用 VideoDB 工具和 Python SDK 深入分析单个视频及视频集合。

主要功能

  1. 01搜索转录文本中的匹配片段
  2. 02针对视频内容提问
  3. 03跨视频集合搜索
  4. 04筛选或汇总检测到的物体
  5. 05根据匹配片段生成剪辑

适用场景

  1. 01查找视频中讨论某主题的位置
  2. 02回答有关场景和屏幕文字的问题
  3. 03搜索并比较视频库中的内容

MCP 相关

提供 VideoDB 连接器工具时,该技能指导 Agent 上传、分析和搜索视频及视频集合;也说明了连接器不可用时使用 Python SDK 的方式。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/video-db/skills --skill video-search

安装后在 Claude Code 中输入/video-search确认已加载。

详细介绍

查找片段,或向视频提问

选择路径

  1. 已提供 VideoDB 连接器工具(名称如 upload_media、search_video、ask_video、understand_video):使用这些工具。这是在 Claude 网页版、桌面版和移动版聊天,以及 Cowork 中使用的路径。无需安装任何内容,也不要索要 API 密钥。
  2. 没有 VideoDB 工具,但有 shell(Claude Code、Cowork,或任何能运行 Python 的 Agent):用一句友好的话索要 VideoDB API 密钥(可在 https://console.videodb.io 免费获取,含 $20 额度,无需银行卡)。用户通过聊天或其他方式提供密钥后,由你自行将其保存到项目的 .env 文件中,变量名为 VIDEO_DB_API_KEY;绝不要打印密钥,然后继续使用本文末尾的 Python SDK 路径。在 Claude Code 中,也可以使用 /mcp,然后授权 videodb。
  3. 没有 VideoDB 工具,也没有 shell:你当前处于 Claude 聊天中。只回复以下内容,并根据请求调整措辞:“尚未连接 VideoDB。请打开 Settings → Connectors,找到 VideoDB,点击 Connect 并登录(免费,无需银行卡)。然后重新发送此请求,我会接手处理。”此处不要提及 API 密钥、.env、shell、Claude Code 或 /mcp;这些都不适用于聊天,而且在聊天中粘贴密钥也无法使用,因为这里不能运行代码。

与用户交流时:回复中绝不要使用“索引”“已索引”或“正在索引”。请说“可搜索”(“现在可以根据说了什么和画面中显示的内容进行搜索”),并使用“转录”,不要提及任务名称。每次只发送一行状态信息,然后给出结果。

长时间运行的任务会返回 status: processing。回复中会包含 output_url,并指出用于轮询的工具(poll_with,旧版服务则使用 retry_with)。使用该工具和 output_url 继续轮询,直到状态变为 done;连续多次返回 processing 属于正常情况(上传一个 10 分钟的 YouTube 视频大约需要五分钟),如果返回 done 但结果为空,请再轮询一次。绝不要重新运行写入操作,否则会启动第二个任务。

使用连接器工具

1. 获取视频。 首先调用 search_videos_by_title(query),并传入视频标题或链接中的文字;如果账号中已有该视频的 m- ID,则重复使用。否则,对于 YouTube 链接或公开 URL,调用 upload_media(url),轮询直到状态为 done,并记下 m- ID 和以秒为单位的 length。用户没有 URL,且文件在其电脑上:连接器无法接收本地文件;请引导他们前往 https://console.videodb.io 上传,然后继续使用 m- ID。

2. 选择快速路径或索引路径。

快速路径,默认用于回答关于视频中说了什么的一次性问题。 自行阅读转录文本并找到相关片段:

generate_transcript(media_id)                                   # a job; poll until done (instant if already transcribed)
get_transcript(media_id, timestamped=true, segmenter="sentence")   # sentence segments with start and end seconds

扫描各片段,找出用户描述的时刻,记下起止时间,然后转到步骤 4。无需建立索引。注意两个问题:转录任务的 done 结果包含文本和词语列表,但该列表会被截断,因此务必使用 get_transcript 读取;默认的分段器按词分段,最多 2000 个片段,因此请传入 segmenter="sentence"(可处理几小时的语音),或使用 start 和 end 指定时间窗口。如果工具截断的视频仍然过长,或者用户会持续询问该视频相关问题,就说明应该使用索引路径。

没有匹配项:直截了当地说明,不要把牵强的匹配说成用户询问的内容。YouTube 上传内容可能只是较长演讲的节选。可以提供最接近的片段,并明确标注;也可以请用户提供另一个视频。

索引路径。 如果问题涉及画面内容而非说话内容、用户需要计数或精确筛选条件、用户会针对同一视频或媒体库提出多个问题,或者转录文本过长而无法阅读,请使用此路径。先检查 list_indexes(video_id);如果没有可用索引:

understand_video(video_id, analyzers=[
  {"type": "spoken_words", "name": "transcript"},
  {"type": "vlm", "name": "scene", "config": {"prompt": "Describe the scene and any on-screen text."}}
])

轮询 get_understanding(video_id, understanding_id),直到每个分析器的状态都为 done,然后为每个分析器建立一个索引:

create_index(video_id, understanding_id, analyzer_name="transcript")
create_index(video_id, understanding_id, analyzer_name="scene")

只需处理语音内容(播客、通话):仅运行 spoken_words 分析器。涉及对象和计数(“有多少辆汽车”):添加 {"type": "object_detection"} 或 {"type": "activity_recognition"}。

3. 检索(索引路径)。

用户需求调用
带时间戳的片段search_video(video_id, query, include_clip=true)
带来源的书面回答ask_video(video_id, question, include_sources=true)
搜索整个媒体库search_collection(query) 或 ask_collection(question)
计数和分组(“哪些对象出现得最多”)aggregate_index(video_id, index_name="objects", group_by="frames.detections.label")
精确筛选条件(“标签 = car 的场景”)query_index(video_id, index_name, filter)
深入调查并进行后续提问search_video(..., mode="deepsearch"),然后在下次调用时传入 session_id

4. 提供结果。 将片段的 start 到 end 时间以 mm:ss 格式给出,并附上匹配的文字(引用转录文本或每条搜索结果中的 text);如果设置了 include_clip,还要提供每个片段的 player_url。将匹配项剪辑成一个片段:调用 generate_clip(video_id, timeline=[[start, end], ...])(单位为秒,在每侧留出几秒余量会更便于阅读),轮询,然后分享 player_url。

使用 index_spoken_words 或 index_scenes(v1)建立索引的旧视频,需使用 legacy_search_video 和 legacy_search_collection 进行搜索。

使用 Python SDK(Claude Code)

如果 import videodb 失败,请先使用 /videodb:setup 进行设置。完整参考文档:${CLAUDE_PLUGIN_ROOT}/python/SKILL.md 和 ${CLAUDE_PLUGIN_ROOT}/python/reference/search.md。

from dotenv import load_dotenv; load_dotenv(".env")
import videodb, time
conn = videodb.connect(); coll = conn.get_collection()
video = coll.upload(url="https://www.youtube.com/watch?v=VIDEO_ID")
u = video.understand(analyzers=[{"type": "spoken_words", "name": "transcript"},
                                {"type": "vlm", "name": "scene", "config": {"prompt": "Describe the scene."}}])
u.wait_until_complete()
for a in u.list_analyzers():
    if a.is_successful: video.index(source=a, name=a.name).wait_until_complete()
r = video.search("the part about pricing")
for s in r.shots: print(f"[{s.start:.0f}s-{s.end:.0f}s] {s.text}")
print(r.compile())   # stream URL of the matches; player: https://console.videodb.io/player?url={STREAM_URL}

评论

支持 Markdown