python
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseVideoDB Python Skill
VideoDB Python 技能指南
Use this skill for VideoDB Python SDK workflows: upload, transcript, subtitle, search, timeline editing, generative media, and real-time capture.
Do not use ffmpeg, moviepy, or local encoding tools when VideoDB supports the operation. The following are all handled server-side by VideoDB — trimming, combining clips, overlaying audio or music, adding subtitles, text/image overlays, transcoding, resolution changes, aspect-ratio conversion, resizing for platform requirements, transcription, and media generation. Only fall back to local tools for operations listed under Limitations in reference/editor.md (transitions, speed changes, crop/zoom, colour grading, volume mixing).
本技能适用于VideoDB Python SDK的各类工作流:上传、语音转文字、字幕生成、视频内搜索、时间轴编辑、生成式媒体以及实时采集。
当VideoDB支持对应操作时,请勿使用ffmpeg、moviepy或本地编码工具。以下所有操作均由VideoDB在云端完成:剪辑、合并片段、音频/音乐叠加、添加字幕、文本/图片叠加、转码、分辨率调整、宽高比转换、适配平台尺寸调整、语音转文字以及媒体生成。仅当操作属于reference/editor.md中列出的限制项(转场效果、变速、裁剪/缩放、色彩分级、音量混合)时,才需 fallback 到本地工具。
When to use what
场景与对应方案
| Problem | VideoDB solution |
|---|---|
| Platform rejects video aspect ratio or resolution | |
| Need to resize video for Twitter/Instagram/TikTok | |
| Need to change resolution (e.g. 1080p → 720p) | |
| Need to overlay audio/music on video | |
| Need to add subtitles | |
| Need to combine/trim clips | |
| Need to generate voiceover, music, or SFX | |
| 场景问题 | VideoDB解决方案 |
|---|---|
| 平台不支持视频的宽高比或分辨率 | |
| 需要调整视频尺寸适配Twitter/Instagram/TikTok | |
| 需要调整分辨率(如1080p → 720p) | 搭配 |
| 需要在视频上叠加音频/音乐 | 在 |
| 需要添加字幕 | |
| 需要合并/剪辑片段 | 在 |
| 需要生成旁白、音乐或音效 | |
Setup
环境搭建
Run setup from the plugin root using absolute paths so it works regardless of current directory:
bash
python "${CLAUDE_PLUGIN_ROOT}/python/scripts/setup_venv.py"
python "${CLAUDE_PLUGIN_ROOT}/python/scripts/check_connection.py"从插件根目录使用绝对路径执行以下命令完成搭建,确保无论当前目录如何都能正常运行:
bash
python "${CLAUDE_PLUGIN_ROOT}/python/scripts/setup_venv.py"
python "${CLAUDE_PLUGIN_ROOT}/python/scripts/check_connection.py"API Key
API密钥
An API key from https://console.videodb.io is required.
python
import videodb
from dotenv import load_dotenv
load_dotenv()
conn = videodb.connect()
coll = conn.get_collection()If is not set and no key is passed to , ask the user for it.
VIDEO_DB_API_KEYvideodb.connect()python
import videodb
from dotenv import load_dotenv
load_dotenv()
conn = videodb.connect()
coll = conn.get_collection()如果未设置且未向传入密钥,请向用户索要。
VIDEO_DB_API_KEYvideodb.connect()Quick Reference
快速参考
Upload media
媒体上传
python
undefinedpython
undefinedURL
URL链接
video = coll.upload(url="https://example.com/video.mp4")
video = coll.upload(url="https://example.com/video.mp4")
YouTube
YouTube视频
video = coll.upload(url="https://www.youtube.com/watch?v=VIDEO_ID")
video = coll.upload(url="https://www.youtube.com/watch?v=VIDEO_ID")
Local file
本地文件
video = coll.upload(file_path="/path/to/video.mp4")
undefinedvideo = coll.upload(file_path="/path/to/video.mp4")
undefinedTranscript + subtitle
语音转文字与字幕
python
undefinedpython
undefinedforce=True skips the error if the video is already indexed
force=True会跳过视频已索引时的错误
video.index_spoken_words(force=True)
text = video.get_transcript_text()
stream_url = video.add_subtitle()
undefinedvideo.index_spoken_words(force=True)
text = video.get_transcript_text()
stream_url = video.add_subtitle()
undefinedSearch inside videos
视频内内容搜索
python
from videodb.exceptions import InvalidRequestError
video.index_spoken_words(force=True)python
from videodb.exceptions import InvalidRequestError
video.index_spoken_words(force=True)search() raises InvalidRequestError when no results are found.
当无搜索结果时,search()会抛出InvalidRequestError。
Always wrap in try/except and treat "No results found" as empty.
始终使用try/except包裹,并将“No results found”视为空结果。
try:
results = video.search("product demo")
shots = results.get_shots()
stream_url = results.compile()
except InvalidRequestError as e:
if "No results found" in str(e):
shots = []
else:
raise
undefinedtry:
results = video.search("product demo")
shots = results.get_shots()
stream_url = results.compile()
except InvalidRequestError as e:
if "No results found" in str(e):
shots = []
else:
raise
undefinedScene search
场景搜索
python
import re
from videodb import SearchType, IndexType, SceneExtractionType
from videodb.exceptions import InvalidRequestErrorpython
import re
from videodb import SearchType, IndexType, SceneExtractionType
from videodb.exceptions import InvalidRequestErrorindex_scenes() has no force parameter — it raises an error if a scene
index_scenes()没有force参数——如果场景索引已存在,会直接抛出错误。需从错误信息中提取已有的索引ID。
index already exists. Extract the existing index ID from the error.
—
try:
scene_index_id = video.index_scenes(
extraction_type=SceneExtractionType.shot_based,
prompt="Describe the visual content in this scene.",
)
except Exception as e:
match = re.search(r"id\s+([a-f0-9]+)", str(e))
if match:
scene_index_id = match.group(1)
else:
raise
try:
scene_index_id = video.index_scenes(
extraction_type=SceneExtractionType.shot_based,
prompt="Describe the visual content in this scene.",
)
except Exception as e:
match = re.search(r"id\s+([a-f0-9]+)", str(e))
if match:
scene_index_id = match.group(1)
else:
raise
Use score_threshold to filter low-relevance noise (recommended: 0.3+)
使用score_threshold过滤低相关度结果(推荐值:0.3+)
try:
results = video.search(
query="person writing on a whiteboard",
search_type=SearchType.semantic,
index_type=IndexType.scene,
scene_index_id=scene_index_id,
score_threshold=0.3,
)
shots = results.get_shots()
stream_url = results.compile()
except InvalidRequestError as e:
if "No results found" in str(e):
shots = []
else:
raise
undefinedtry:
results = video.search(
query="person writing on a whiteboard",
search_type=SearchType.semantic,
index_type=IndexType.scene,
scene_index_id=scene_index_id,
score_threshold=0.3,
)
shots = results.get_shots()
stream_url = results.compile()
except InvalidRequestError as e:
if "No results found" in str(e):
shots = []
else:
raise
undefinedTimeline editing
时间轴编辑
Important: Always validate timestamps before building a timeline:
- must be >= 0 (negative values are silently accepted but produce broken output)
start - must be <
startend - must be <=
endvideo.length
python
from videodb.timeline import Timeline
from videodb.asset import VideoAsset, TextAsset, TextStyle
timeline = Timeline(conn)
timeline.add_inline(VideoAsset(asset_id=video.id, start=10, end=30))
timeline.add_overlay(0, TextAsset(text="The End", duration=3, style=TextStyle(fontsize=36)))
stream_url = timeline.generate_stream()注意: 在构建时间轴前务必验证时间戳:
- 必须 >= 0(负值会被静默接受,但会导致输出损坏)
start - 必须 <
startend - 必须 <=
endvideo.length
python
from videodb.timeline import Timeline
from videodb.asset import VideoAsset, TextAsset, TextStyle
timeline = Timeline(conn)
timeline.add_inline(VideoAsset(asset_id=video.id, start=10, end=30))
timeline.add_overlay(0, TextAsset(text="The End", duration=3, style=TextStyle(fontsize=36)))
stream_url = timeline.generate_stream()Transcode video (resolution / quality change)
视频转码(分辨率/画质调整)
python
from videodb import TranscodeMode, VideoConfig, AudioConfigpython
from videodb import TranscodeMode, VideoConfig, AudioConfigChange 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),
)
undefinedjob_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),
)
undefinedReframe aspect ratio (for social platforms)
宽高比适配(针对社交平台)
Warning: is a slow server-side operation. For long videos it can take
several minutes and may time out. Best practices:
reframe()- Always limit to a short segment using /
startwhen possibleend - For full-length videos, use for async processing
callback_url - Trim the video on a first, then reframe the shorter result
Timeline
python
from videodb import ReframeMode警告: 是一个较慢的云端操作。处理长视频可能需要数分钟,甚至超时。最佳实践:
reframe()- 尽可能使用/
start限制处理片段长度end - 处理全长度视频时,使用进行异步处理
callback_url - 先在上剪辑视频,再对较短的结果进行宽高比适配
Timeline
python
from videodb import ReframeModeAlways prefer reframing a short segment:
优先适配短片段:
reframed = video.reframe(start=0, end=60, target="vertical", mode=ReframeMode.smart)
reframed = video.reframe(start=0, end=60, target="vertical", mode=ReframeMode.smart)
Async reframe for full-length videos (returns None, result via webhook):
全长度视频异步适配(返回None,结果通过webhook接收):
video.reframe(target="vertical", callback_url="https://example.com/webhook")
video.reframe(target="vertical", callback_url="https://example.com/webhook")
Presets: "vertical" (9:16), "square" (1:1), "landscape" (16:9)
预设值:"vertical"(9:16)、"square"(1:1)、"landscape"(16:9)
reframed = video.reframe(start=0, end=60, target="square")
reframed = video.reframe(start=0, end=60, target="square")
Custom dimensions
自定义尺寸
reframed = video.reframe(start=0, end=60, target={"width": 1280, "height": 720})
undefinedreframed = video.reframe(start=0, end=60, target={"width": 1280, "height": 720})
undefinedGenerative media
生成式媒体
python
image = coll.generate_image(
prompt="a sunset over mountains",
aspect_ratio="16:9",
)python
image = coll.generate_image(
prompt="a sunset over mountains",
aspect_ratio="16:9",
)Error handling
错误处理
python
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}")python
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}")Common pitfalls
常见陷阱
| Scenario | Error message | Solution |
|---|---|---|
| Indexing an already-indexed video | | Use |
| Scene index already exists | | Extract the existing |
| Search finds no matches | | Catch the exception and treat as empty results ( |
| Reframe times out | Blocks indefinitely on long videos | Use |
| Negative timestamps on Timeline | Silently produces broken stream | Always validate |
| | Plan-gated features — inform the user about plan limits |
| 场景 | 错误信息 | 解决方案 |
|---|---|---|
| 为已索引的视频重复索引 | | 使用 |
| 场景索引已存在 | | 使用 |
| 搜索无匹配结果 | | 捕获异常并视为空结果( |
| Reframe操作超时 | 处理长视频时无限阻塞 | 使用 |
| 时间轴使用负时间戳 | 静默生成损坏的流 | 创建 |
| | 这些是受套餐限制的功能——告知用户套餐限制 |
Additional docs in this plugin
插件内附加文档
${CLAUDE_PLUGIN_ROOT}/python/reference/api-reference.md${CLAUDE_PLUGIN_ROOT}/python/reference/search.md${CLAUDE_PLUGIN_ROOT}/python/reference/editor.md${CLAUDE_PLUGIN_ROOT}/python/reference/generative.md${CLAUDE_PLUGIN_ROOT}/python/reference/meetings.md${CLAUDE_PLUGIN_ROOT}/python/reference/rtstream.md${CLAUDE_PLUGIN_ROOT}/python/reference/capture.md${CLAUDE_PLUGIN_ROOT}/python/reference/use-cases.md
${CLAUDE_PLUGIN_ROOT}/python/reference/api-reference.md${CLAUDE_PLUGIN_ROOT}/python/reference/search.md${CLAUDE_PLUGIN_ROOT}/python/reference/editor.md${CLAUDE_PLUGIN_ROOT}/python/reference/generative.md${CLAUDE_PLUGIN_ROOT}/python/reference/meetings.md${CLAUDE_PLUGIN_ROOT}/python/reference/rtstream.md${CLAUDE_PLUGIN_ROOT}/python/reference/capture.md${CLAUDE_PLUGIN_ROOT}/python/reference/use-cases.md