videodb

videodb

热门

对视频和音频进行查看、理解与操作。查看——从本地文件、URL、RTSP/直播源或桌面录制中摄取内容;返回实时上下文和可播放的流链接。理解——提取帧,构建视觉/语义/时间索引,并搜索带有时间戳和自动剪辑的时刻。操作——转码和标准化(编解码器、帧率、分辨率、宽高比),执行时间线编辑(字幕、文字/图像叠加、品牌标识、音频叠加、配音、翻译),生成媒体资产(图像、音频、视频),并为直播流或桌面捕获的事件创建实时告警。

23万Star
3.5万Fork
更新于 2026/7/17
SKILL.md
readonly只读
name
videodb
description

对视频和音频进行查看、理解与操作。查看——从本地文件、URL、RTSP/直播源或桌面录制中摄取内容;返回实时上下文和可播放的流链接。理解——提取帧,构建视觉/语义/时间索引,并搜索带有时间戳和自动剪辑的时刻。操作——转码和标准化(编解码器、帧率、分辨率、宽高比),执行时间线编辑(字幕、文字/图像叠加、品牌标识、音频叠加、配音、翻译),生成媒体资产(图像、音频、视频),并为直播流或桌面捕获的事件创建实时告警。

VideoDB 技能

感知 + 记忆 + 操作,适用于视频、直播流和桌面会话。

何时使用

桌面感知

  • 启动/停止桌面会话,捕获屏幕、麦克风和系统音频
  • 流式传输实时上下文并存储情景会话记忆
  • 对屏幕上的语音和内容运行实时告警/触发器
  • 生成会话摘要、可搜索的时间线和可播放的证据链接

视频摄取 + 流

  • 摄取文件或URL并返回可播放的网页流链接
  • 转码/标准化:编解码器、比特率、帧率、分辨率、宽高比

索引 + 搜索(时间戳 + 证据)

  • 构建视觉语音关键词索引
  • 搜索并返回带有时间戳可播放证据的精确时刻
  • 从搜索结果自动创建剪辑

时间线编辑 + 生成

  • 字幕:生成翻译烧录
  • 叠加:文字/图像/品牌标识、动态字幕
  • 音频:背景音乐画外音配音
  • 通过时间线操作进行编程式合成和导出

直播流(RTSP)+ 监控

  • 连接RTSP/直播源
  • 运行实时视觉和语音理解,并发出事件/告警用于监控工作流

工作原理

常见输入

  • 本地文件路径、公共URLRTSP URL
  • 桌面捕获请求:启动 / 停止 / 总结会话
  • 所需操作:获取上下文以理解、转码规格、索引规格、搜索查询、剪辑范围、时间线编辑、告警规则

常见输出

  • 流URL
  • 带有时间戳证据链接的搜索结果
  • 生成的资产:字幕、音频、图像、剪辑
  • 直播流的事件/告警负载
  • 桌面会话摘要和记忆条目

运行Python代码

在运行任何VideoDB代码之前,切换到项目目录并加载环境变量:

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"视频数量: {len(coll.get_videos())}")
EOF

设置

当用户要求“设置videodb”或类似内容时:

1. 安装SDK

pip install "videodb[capture]" python-dotenv

如果在Linux上videodb[capture]安装失败,请安装不带capture扩展的版本:

pip install videodb python-dotenv

2. 配置API密钥

用户必须使用任一方法设置VIDEO_DB_API_KEY

  • 在终端中导出(在启动Claude之前):export VIDEO_DB_API_KEY=your-key
  • 项目.env文件:将VIDEO_DB_API_KEY=your-key保存在项目的.env文件中

console.videodb.io获取免费API密钥(50次免费上传,无需信用卡)。

不要自行读取、写入或处理API密钥。始终让用户设置。

快速参考

上传媒体

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

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

# 本地文件
video = coll.upload(file_path="/path/to/video.mp4")

转录 + 字幕

# force=True 跳过视频已索引时的错误
video.index_spoken_words(force=True)
text = video.get_transcript_text()
stream_url = video.add_subtitle()

在视频内搜索

from videodb.exceptions import InvalidRequestError

video.index_spoken_words(force=True)

# search() 在未找到结果时抛出 InvalidRequestError。
# 始终使用 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

场景搜索

import re
from videodb import SearchType, IndexType, SceneExtractionType
from videodb.exceptions import InvalidRequestError

# index_scenes() 没有 force 参数——如果场景索引已存在则会抛出错误。
# 从错误中提取现有的索引ID。
try:
    scene_index_id = video.index_scenes(
        extraction_type=SceneExtractionType.shot_based,
        prompt="描述此场景中的视觉内容。",
    )
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

# 使用 score_threshold 过滤低相关噪声(推荐:0.3以上)
try:
    results = video.search(
        query="在白板上写字的人",
        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

时间线编辑

重要: 在构建时间线之前始终验证时间戳:

  • start 必须 >= 0(负值会被静默接受但会产生损坏的输出)
  • start 必须 < end
  • end 必须 <= video.length
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="结束", duration=3, style=TextStyle(fontsize=36)))
stream_url = timeline.generate_stream()

转码视频(分辨率/质量更改)

from videodb import TranscodeMode, VideoConfig, AudioConfig

# 在服务端更改分辨率、质量或宽高比
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 上裁剪视频,然后对较短的结果进行 reframe
from videodb import ReframeMode

# 始终优先对短片段进行 reframe:
reframed = video.reframe(start=0, end=60, target="vertical", mode=ReframeMode.smart)

# 全长视频的异步 reframe(返回 None,结果通过 webhook):
video.reframe(target="vertical", callback_url="https://example.com/webhook")

# 预设:"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={"width": 1280, "height": 720})

生成式媒体

image = coll.generate_image(
    prompt="山上的日落",
    aspect_ratio="16:9",
)

错误处理

from videodb.exceptions import AuthenticationError, InvalidRequestError

try:
    conn = videodb.connect()
except AuthenticationError:
    print("检查您的 VIDEO_DB_API_KEY")

try:
    video = coll.upload(url="https://example.com/video.mp4")
except InvalidRequestError as e:
    print(f"上传失败: {e}")

常见陷阱

场景 错误信息 解决方案
索引已索引的视频 Spoken word index for video already exists 使用 video.index_spoken_words(force=True) 跳过已索引的情况
场景索引已存在 Scene index with id XXXX already exists 使用 re.search(r"id\s+([a-f0-9]+)", str(e)) 从错误中提取现有的 scene_index_id
搜索无匹配 InvalidRequestError: No results found 捕获异常并视为空结果(shots = []
Reframe 超时 长视频上无限阻塞 使用 start/end 限制片段,或传递 callback_url 进行异步处理
时间线上的负时间戳 静默产生损坏的流 在创建 VideoAsset 之前始终验证 start >= 0
generate_video() / create_collection() 失败 Operation not allowedmaximum limit 计划限制功能——告知用户计划限制

示例

典型提示

  • "启动桌面捕获,并在密码字段出现时发出告警。"
  • "录制我的会话,并在结束时生成可操作的摘要。"
  • "摄取此文件并返回可播放的流链接。"
  • "索引此文件夹并找到每个有人的场景,返回时间戳。"
  • "生成字幕,烧录进去,并添加轻柔的背景音乐。"
  • "连接此RTSP URL,并在有人进入区域时发出告警。"

屏幕录制(桌面捕获)

使用 ws_listener.py 在录制会话期间捕获 WebSocket 事件。桌面捕获仅支持 macOS

快速开始
  1. 选择状态目录STATE_DIR="${VIDEODB_EVENTS_DIR:-$HOME/.local/state/videodb}"
  2. 启动监听器VIDEODB_EVENTS_DIR="$STATE_DIR" python scripts/ws_listener.py --clear "$STATE_DIR" &
  3. 获取 WebSocket IDcat "$STATE_DIR/videodb_ws_id"
  4. 运行捕获代码(参见 reference/capture.md 获取完整工作流)
  5. 事件写入$STATE_DIR/videodb_events.jsonl

每次开始新的捕获运行时使用 --clear,以防止过时的转录和视觉事件泄漏到新会话中。

查询事件
import json
import os
import time
from pathlib import Path

events_dir = Path(os.environ.get("VIDEODB_EVENTS_DIR", Path.home() / ".local" / "state" / "videodb"))
events_file = events_dir / "videodb_events.jsonl"
events = []

if events_file.exists():
    with events_file.open(encoding="utf-8") as handle:
        for line in handle:
            try:
                events.append(json.loads(line))
            except json.JSONDecodeError:
                continue

transcripts = [e["data"]["text"] for e in events if e.get("channel") == "transcript"]
cutoff = time.time() - 300
recent_visual = [
    e for e in events
    if e.get("channel") == "visual_index" and e["unix_ts"] > cutoff
]

附加文档

参考文档位于此 SKILL.md 文件旁边的 reference/ 目录中。如有需要,使用 Glob 工具定位。

当 VideoDB 支持该操作时,不要使用 ffmpeg、moviepy 或本地编码工具。以下操作均由 VideoDB 在服务端处理——裁剪、合并剪辑、叠加音频或音乐、添加字幕、文字/图像叠加、转码、分辨率更改、宽高比转换、根据平台要求调整大小、转录和媒体生成。仅对 reference/editor.md 中“限制”部分列出的操作(转场、速度变化、裁剪/缩放、色彩分级、音量混合)回退到本地工具。

何时使用什么

问题 VideoDB 解决方案
平台拒绝视频宽高比或分辨率 video.reframe() 或带 VideoConfigconn.transcode()
需要为 Twitter/Instagram/TikTok 调整视频大小 video.reframe(target="vertical")target="square"
需要更改分辨率(例如 1080p → 720p) VideoConfig(resolution=720)conn.transcode()
需要在视频上叠加音频/音乐 Timeline 上的 AudioAsset
需要添加字幕 video.add_subtitle()CaptionAsset
需要合并/裁剪剪辑 Timeline 上的 VideoAsset
需要生成画外音、音乐或音效 coll.generate_voice()generate_music()generate_sound_effect()

来源

此技能的参考材料本地存储在 skills/videodb/reference/ 下。
请使用上述本地副本,而不是在运行时遵循外部仓库链接。