mcpField
V
videodb

videodb

github.com/video-db创意与媒体1391.5k 次安装今天更新
代码仓库

关于 videodb

videodb 是一项技能,指导通过 VideoDB 的 Python SDK 在其服务器上处理视频。它面向开发者和 Agent,涵盖导入、分析、搜索与编辑,并建议常见任务使用配套技能。

主要功能

  1. 01从网址或本地文件上传视频
  2. 02使用可配置分析器分析视频
  3. 03按语义或精确条件搜索视频
  4. 04生成转录文本和字幕
  5. 05合成、转码及重构视频画幅

适用场景

  1. 01在视频集合中查找相关片段
  2. 02制作字幕或翻译视频素材
  3. 03合成包含音频、图像和文字的片段
  4. 04在 Python 项目中运行视频处理

MCP 相关

该技能介绍了供 Claude Code 使用的托管 VideoDB MCP 服务,其授权与 SDK API 密钥分开。MCP 工具无需本地安装 Python 或 API 密钥即可执行视频操作;在该插件配置之外,文档所述路径为 SDK。

安装

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

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

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

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

.env.example
reference/
api-reference.md
capture-reference.md
capture.md
editor-reference.md
editor.md
generative.md
indexing-reference.md
indexing.md
migration.md
rtstream-reference.md
rtstream.md
sandbox-reference.md
sandbox.md
search-reference.md
search.md
streaming.md
use-cases.md
reference/legacy/
index-reference.md
index.md
search.md
scripts/
ws_listener.py

详细介绍

VideoDB:设置与 Python SDK

VideoDB 会在其服务器上处理视频:导入、理解、索引、搜索、剪辑、添加字幕、合成和流式传输。本技能涵盖设置与 Python SDK。另有五个较小的技能涵盖常见任务;符合需求时应优先使用:

任务技能
查找某个时刻、询问视频内容、统计画面中出现的事物video-search
剪辑、精彩集锦、竖屏剪辑、MP4 文件video-clips
转录文本、字幕、翻译video-subtitles
音乐、叠加内容、字幕、合成video-edit
摄像头、直播、会议、屏幕录制video-live

选择路径

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

代码、脚本、笔记本、桌面录制、AI 生成、配音和沙盒计算也只能通过 SDK 完成,连接器无法处理这些任务。与用户交流时:回复中绝不要写“索引”“已索引”或“正在索引”;应使用“可搜索”。

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

输出

  • 流媒体 URL,可通过 https://console.videodb.io/player?url={STREAM_URL} 播放;连接器工具也会返回 player_url
  • 带时间戳和可播放证据的搜索结果
  • 生成的素材:字幕、音频、图片、剪辑
  • 直播的事件和警报载荷
  • 桌面会话摘要和可搜索时间线

运行 Python 代码

**重要:**运行 Python 代码前,务必先 cd 到用户的项目目录。这样可以确保 load_dotenv(".env") 找到正确的 .env 文件。

from dotenv import load_dotenv
load_dotenv(".env")

import videodb
conn = videodb.connect()

它会按以下顺序读取 VIDEO_DB_API_KEY:

  1. 环境变量(如果已导出)
  2. 当前目录下项目的 .env 文件

如果缺少密钥,videodb.connect() 会自动引发 AuthenticationError。

短小的内联命令即可完成时,不要编写脚本文件。

编写内联 Python(python -c "...")时,务必使用格式规范的代码——用分号分隔语句,并保持易读。超过约 3 条语句时,请改用 heredoc:

python << 'EOF'
from dotenv import load_dotenv
load_dotenv(".env")

import videodb
conn = videodb.connect()
coll = conn.get_collection()
print(f"Videos: {len(coll.get_videos())}")
EOF

设置

用户询问“设置 videodb”或类似内容时:

1. 安装 SDK
pip install "videodb[capture]>=0.5.0" python-dotenv

如果在 Linux 上安装 videodb[capture] 失败,请在不添加 capture 扩展的情况下安装:

pip install "videodb>=0.5.0" python-dotenv

>=0.5.0 这一版本限制很重要——更早版本中没有 understand/index/ask/aggregate API。

2. 配置 API 密钥

请用一行向用户询问其 VideoDB API 密钥:可在 https://console.videodb.io 免费获取,含 $20 免费额度,无需信用卡。用户通过聊天或其他方式提供密钥后,替他们保存并继续操作:

  • 将 VIDEO_DB_API_KEY=<key> 写入项目的 .env 文件(如有需要则创建该文件),并确保 .env 已列在 .gitignore 中。
  • 切勿打印、回显、记录或提交该密钥,也切勿通过 SDK 以外的途径发送该密钥。
  • 如果用户想自行设置,也可以在终端中运行 export VIDEO_DB_API_KEY=<key>。

告知用户保存了密钥以及保存位置,但不要重复密钥。

3. 授权托管 MCP 服务(仅限 Claude Code 插件)

该插件捆绑了托管 MCP 服务 https://mcp.videodb.io/mcp,其授权与上述 SDK 密钥分开进行。请告知用户运行 /mcp,选择 videodb,并使用其 VideoDB 账号完成浏览器授权。通过“list my VideoDB collections”进行验证。

MCP 工具无需本地安装 Python,也无需 API 密钥。如果技能是通过 npx skills add 安装的,或者运行环境不是 Claude Code,则跳过此步骤——此时没有 MCP 服务,只有上述 SDK 方式可用。

快速参考

上传媒体
# URL
video = coll.upload(url="https://example.com/video.mp4")

# YouTube
video = coll.upload(url="https://www.youtube.com/watch?v=VIDEO_ID")

# Local file
video = coll.upload(file_path="/path/to/video.mp4")
理解 → 建立索引 → 检索(默认路径)

分为三个阶段。运行分析器以生成产物,为每个产物建立索引,然后进行检索。

import time

# 1. Understand. Naming each analyzer keeps `analyzer.name` meaningful downstream.
understanding = video.understand(
    analyzers=[
        {"type": "spoken_words", "name": "transcript"},
        {"type": "vlm", "name": "scene",
         "config": {"prompt": "Describe the scene and any on-screen text."}},
    ],
    segmentation={"type": "shot", "threshold": 30},
)

# A run with a failed or skipped analyzer ends `partial`, which the SDK does not
# treat as terminal — wait_until_complete() would poll to TimeoutError. Poll the
# analyzers instead. The `analyzers and` guard is load-bearing: a refresh can
# transiently return an empty list, and all([]) is True, which would exit the
# loop while the run is still going.
deadline = time.time() + 3600
while time.time() < deadline:
    analyzers = understanding.refresh().list_analyzers()
    if analyzers and all(a.is_complete for a in analyzers):
        break
    time.sleep(15)

# 2. Index each artifact that succeeded.
for analyzer in understanding.list_analyzers():
    if analyzer.is_successful:
        video.index(source=analyzer, name=analyzer.name).wait_until_complete()

# 3. Retrieve.
response = video.search("discussion about pricing")
for shot in response.shots:
    print(f"[{shot.start:.1f}s - {shot.end:.1f}s] {shot.text}")
if response.response_type in ("shots", "deepsearch") and len(response):
    stream_url = response.compile()   # raises SearchError otherwise

分析器类型:spoken_words(→ 产物 transcript)、vlm(→ scene)、object_detection(→ objects)、ocr、brand_detection(→ brands)、activity_recognition(→ activity)、location_detection(→ location)、faces、audio_event_detection。它们都是普通字符串——没有 SDK 枚举。

关于分段、采样、字段配置和成本调优,请参阅 reference/indexing.md。

检索

search(query) 是默认方式——它会规划检索并自行选择索引。需要特定内容时,可改用以下方法:

# Target a specific index, with a relevance floor
video.semantic_search("a customer holding the product", index_names=["scene"], score_threshold=0.7)

# Exact filtering, no natural-language interpretation
video.query(index_name="objects",
            filter=[{"field": "frames.detections.label", "op": "contains", "value": "car"}])

# Counts and facets — returns the raw server payload, not a SearchResult
video.aggregate(index_name="objects", group_by="frames.detections.label", metric="count")

# A written answer plus the moments it came from
answer = video.ask("What did they say about pricing?", include_sources=True)

这五种方法在 Collection 上也都可用,并会遍历其中所有已建立索引的视频。请参阅 reference/search.md。

search() 现在返回 SearchResponse,而非 SearchResult。 get_shots()、compile()、play() 和迭代都可正常使用,但它没有 .stream_url——请改用 .compile()。

转录文本 + 字幕
video.generate_transcript()          # returns the existing transcript if there is one; force=True re-runs it
text = video.get_transcript_text()
stream_url = video.add_subtitle()

add_subtitle() 和 CaptionAsset(src="auto") 会读取视频的转录文本。generate_transcript() 会创建转录文本,而从 understand() 运行 spoken_words 分析器也会创建转录文本。字幕或说明文字无需使用旧版 index_spoken_words()。

旧版索引(现有代码库)
# v1 API, legacy. Only for codebases that already use it; new code uses understand() + index() above.
from videodb import IndexType

video.index_spoken_words(force=True)
scene_index_id = video.index_scenes(prompt="Describe the visual content.")
results = video.legacy_search(
    "person writing on a whiteboard",
    index_type=IndexType.scene,
    scene_index_id=scene_index_id,
)

在现有仓库中识别这种模式,除非用户要求迁移,否则不要改动——它仍然有效。关于移植,请参阅 reference/migration.md;关于维护,请参阅 reference/legacy/search.md。

时间线编辑

使用 Editor API 合成视频、图像、音频和文本。完整工作流请参阅 reference/editor.md。

from videodb.editor import Timeline, Track, Clip, VideoAsset, ImageAsset, AudioAsset, Fit

timeline = Timeline(conn)
timeline.resolution = "1280x720"

video_track = Track()
video_track.add_clip(0, Clip(asset=VideoAsset(id=video.id, start=10), duration=20))

audio_track = Track()
audio_track.add_clip(0, Clip(asset=AudioAsset(id=music.id, volume=0.2), duration=20))

timeline.add_track(video_track)
timeline.add_track(audio_track)
stream_url = timeline.generate_stream()
转码视频(更改分辨率 / 画质)
from videodb import TranscodeMode, VideoConfig, AudioConfig

# Change resolution, quality, or aspect ratio server-side
job_id = conn.transcode(
    source="https://example.com/video.mp4",
    callback_url="https://example.com/webhook",
    mode=TranscodeMode.economy,
    video_config=VideoConfig(resolution=720, quality=23, aspect_ratio="16:9"),
    audio_config=AudioConfig(mute=False),
)
重新调整宽高比(适用于社交平台)

警告:reframe() 是一项耗时的服务端操作。对于较长的视频,可能需要几分钟,并且可能超时。最佳实践:

  • 尽可能始终使用 start/end 限定较短片段
  • 对于完整视频,使用 callback_url 进行异步处理
  • 先在 Timeline 上裁剪视频,再对较短的结果重新调整宽高比
from videodb import ReframeMode

# Always prefer reframing a short segment:
reframed = video.reframe(start=0, end=60, target="vertical", mode=ReframeMode.smart)

# Async reframe for full-length videos (returns None, result via webhook):
video.reframe(target="vertical", callback_url="https://example.com/webhook")

# Presets: "vertical" (9:16), "square" (1:1), "landscape" (16:9)
reframed = video.reframe(start=0, end=60, target="square")

# Custom dimensions
reframed = video.reframe(start=0, end=60, target={"width": 1280, "height": 720})
生成式媒体
image = coll.generate_image(
    prompt="a sunset over mountains",
    aspect_ratio="16:9",
)
沙盒计算(自托管/开放权重模型)

通过创建沙盒并将 sandbox_id 传递给受支持的任务,即可运行开放权重模型(Gemma、Qwen、Whisper、OmniVoice、FLUX、RT-DETR)。需要 videodb>=0.5.1。

from videodb import SandboxTier, SandboxModel

# 1. Create a sandbox sized for the largest model, then wait until active.
sandbox = conn.create_sandbox(
    tier=SandboxTier.medium,
    models=[SandboxModel.GEMMA_4_31B.value],   # exact ID, NO -FP8 suffix
)
sandbox.wait_for_ready(timeout=300, interval=5)

# 2. Understanding: set config.model + config.sandbox_id on the analyzer.
understanding = video.understand(analyzers=[{
    "type": "vlm", "name": "scene",
    "config": {"model": "google/gemma-4-31B-it", "sandbox_id": sandbox.id,
               "prompt": "Describe the scene."},
}])

# 2b. Generation: pass model_name + sandbox_id (jobs return GenerationJob → .wait()).
response = coll.generate_text(prompt="Summarize this.", model_name="Qwen/Qwen3.5-9B",
                             sandbox_id=sandbox.id, max_tokens=300)
job = coll.generate_image(prompt="a city at sunset", model_name="black-forest-labs/FLUX.1-dev",
                          sandbox_id=sandbox.id)
image = job.wait(timeout=900, interval=5)

# 3. Stop when done — provisioning/active/alert all count toward the tier limit.
sandbox.stop(); sandbox.wait_for_stop()

模型 ID 必须与目录完全一致(不能带 -FP8 后缀),否则 create_sandbox 会引发 Unsupported sandbox model。完整的模型目录、层级、类别、定价和注意事项,请参阅 reference/sandbox.md。

错误处理

from videodb.exceptions import AuthenticationError, InvalidRequestError

try:
    conn = videodb.connect()
except AuthenticationError:
    print("Check your VIDEO_DB_API_KEY")

try:
    video = coll.upload(url="https://example.com/video.mp4")
except InvalidRequestError as e:
    print(f"Upload failed: {e}")
常见注意事项
场景错误消息解决方案
搜索结果没有流 URLAttributeError: 'SearchResponse' object has no attribute 'stream_url'search() 在 0.5.0 中返回 SearchResponse。请使用 results.compile()
search(score_threshold=) 搜索了错误的索引无错误,但结果不符合预期score_threshold 不会路由到旧版索引。请使用 semantic_search(score_threshold=),或对 v1 索引使用 legacy_search()
在对象检测上使用语义索引use_for includes semantic but no scene has embeddable text对象产物没有顶层文本。请省略 use_for(它会自动降级),或传入 ["query", "aggregate"]
为不存在的字段编制索引fields.filter names not present in any scene's data错误会列出可用字段名,请查看该列表。也可检查 index.field_schema
搜索没有匹配项v2 返回空的 SearchResponse;只有 legacy_search() 会引发 InvalidRequestError: No results found检查 len(response)。仅对旧版调用使用 try/except
对已编制索引的视频(v1)调用旧版 index_spoken_words()Spoken word index for video already exists传入 force=True,或删除该调用:字幕和说明文字只需要 generate_transcript()
Reframe 超时处理较长视频时会无限期阻塞使用 start/end 限制片段,或传入 callback_url 以异步执行
Timeline 上的时间戳为负数会悄无声息地生成损坏的流创建 VideoAsset 前务必验证 start >= 0
generate_video()/create_collection() 失败Operation not allowed 或 maximum limit这些功能受套餐限制,请告知用户套餐限额

其他文档

参考文档位于 ${CLAUDE_SKILL_DIR}/reference/。请使用此前缀读取其中的文件;以下链接均相对于此 SKILL.md。

旧版 v1 索引与搜索。这些 API 仍然可用,且未弃用,但仅在维护现有 v1 代码时阅读:

屏幕录制(桌面捕获)

录制期间使用 ws_listener.py 捕获 WebSocket 事件。桌面捕获支持 macOS 和 Windows。

${CLAUDE_SKILL_DIR} 是此 skill 的安装目录,由 Claude Code 设置。对于未设置该变量的 Agent,请替换为存放此 SKILL.md 的目录。

快速开始
  1. 启动监听器:python "${CLAUDE_SKILL_DIR}/scripts/ws_listener.py" --cwd=<PROJECT_ROOT> &
  2. 获取 WebSocket ID:cat /tmp/videodb_ws_id
  3. 运行捕获代码(完整工作流请参阅 reference/capture.md)
  4. 事件写入位置:/tmp/videodb_events.jsonl
查询事件
import json
events = [json.loads(l) for l in open("/tmp/videodb_events.jsonl")]

# Get all transcripts
transcripts = [e["data"]["text"] for e in events if e.get("channel") == "transcript"]

# Get visual descriptions from last 5 minutes
import time
cutoff = time.time() - 300
recent_visual = [e for e in events 
                 if e.get("channel") == "visual_index" and e["unix_ts"] > cutoff]
实用脚本
  • ${CLAUDE_SKILL_DIR}/scripts/ws_listener.py - WebSocket 事件监听器(将数据写入 JSONL)

完整的捕获工作流请参阅 reference/capture.md。

VideoDB 支持相关操作时,请勿使用 ffmpeg、moviepy 或本地编码工具。以下操作均由 VideoDB 在服务端处理:剪辑、合并片段、叠加音频或音乐、添加字幕、文本/图像叠加、转码、更改分辨率、转换宽高比、按平台要求调整大小、转录、音量控制、淡入淡出过渡和媒体生成。仅当操作列在 reference/editor.md 的 Limitations 部分时,才使用本地工具作为后备方案(变速、裁剪/缩放、调色、关键帧动画)。

何时使用什么
问题VideoDB 解决方案
让视频可搜索video.understand(analyzers=[...]),然后执行 video.index(source=analyzer)
根据说过或展示的内容查找片段video.search(query),或使用 semantic_search(index_names=[...]) 指定索引
回答有关视频的问题video.ask(question, include_sources=True)
统计或分组视频中出现的内容video.aggregate(index_name=..., group_by=..., metric="count")
根据精确的字段值筛选片段video.query(index_name=..., filter={...})
平台拒绝视频的宽高比或分辨率使用 VideoConfig 执行 video.reframe() 或 conn.transcode()
需要调整视频尺寸以适配 Twitter/Instagram/TikTokvideo.reframe(target="vertical") 或 target="square"
需要更改分辨率(例如从 1080p 调整为 720p)使用 VideoConfig(resolution=720) 执行 conn.transcode()
需要在视频上叠加音频/音乐在 Editor Timeline 上使用 AudioAsset,并控制音量
需要添加字幕使用 video.add_subtitle(),或在 Editor Timeline 上使用 CaptionAsset
需要合并/剪辑片段在 Editor Timeline 上使用 VideoAsset
需要将图像与旁白合成在单独的 Editor 音轨上使用 ImageAsset + AudioAsset
需要生成旁白、音乐或音效coll.generate_voice()、generate_music()、generate_sound_effect()

评论

支持 Markdown