對影片和音訊進行「觀看、理解、行動」。觀看:從本機檔案、URL、RTSP/即時串流或桌面即時錄製擷取內容;回傳即時上下文和可播放的串流連結。理解:擷取影格、建立視覺/語意/時間索引,並搜尋帶有時間戳記和自動剪輯的時刻。行動:轉碼和標準化(編碼格式、FPS、解析度、長寬比)、執行時間軸編輯(字幕、文字/圖片疊加、品牌標示、音訊疊加、配音、翻譯)、生成媒體資產(圖片、音訊、影片),以及為即時串流或桌面擷取的事件建立即時警示。
VideoDB 技能
感知 + 記憶 + 行動,適用於影片、即時串流和桌面工作階段。
使用時機
桌面感知
- 開始/停止桌面工作階段,擷取螢幕、麥克風和系統音訊
- 串流即時上下文並儲存情節性工作階段記憶
- 對螢幕上說的話和發生的事情執行即時警示/觸發
- 產生工作階段摘要、可搜尋的時間軸,以及可播放的證據連結
影片擷取 + 串流
- 擷取檔案或 URL 並回傳可播放的網路串流連結
- 轉碼/標準化:編碼格式、位元率、FPS、解析度、長寬比
索引 + 搜尋(時間戳記 + 證據)
- 建立視覺、語音和關鍵字索引
- 搜尋並回傳帶有時間戳記和可播放證據的確切時刻
- 從搜尋結果自動建立剪輯
時間軸編輯 + 生成
- 字幕:生成、翻譯、燒錄
- 疊加:文字/圖片/品牌標示、動態字幕
- 音訊:背景音樂、旁白、配音
- 透過時間軸操作進行程式化組合和匯出
即時串流(RTSP)+ 監控
- 連接RTSP/即時來源
- 執行即時視覺和語音理解,並為監控工作流程發出事件/警示
運作方式
常見輸入
- 本機檔案路徑、公開URL 或 RTSP URL
- 桌面擷取請求:開始 / 停止 / 摘要工作階段
- 所需操作:取得理解上下文、轉碼規格、索引規格、搜尋查詢、剪輯範圍、時間軸編輯、警示規則
常見輸出
- 串流 URL
- 帶有時間戳記和證據連結的搜尋結果
- 生成的資產:字幕、音訊、圖片、剪輯
- 即時串流的事件/警示負載
- 桌面工作階段摘要和記憶條目
執行 Python 程式碼
在執行任何 VideoDB 程式碼之前,切換到專案目錄並載入環境變數:
from dotenv import load_dotenv
load_dotenv(".env")
import videodb
conn = videodb.connect()
這會從以下位置讀取 VIDEO_DB_API_KEY:
- 環境變數(如果已匯出)
- 目前目錄中專案的
.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
如果 videodb[capture] 在 Linux 上失敗,請不安裝 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必須 <endend必須 <=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 allowed 或 maximum limit |
方案限制功能 — 告知使用者方案限制 |
範例
典型提示
- "開始桌面擷取,並在密碼欄位出現時發出警示。"
- "錄製我的工作階段,並在結束時產生可操作的摘要。"
- "擷取此檔案並回傳可播放的串流連結。"
- "索引此資料夾,找出所有有人物的場景,回傳時間戳記。"
- "生成字幕,燒錄進去,並加入輕柔的背景音樂。"
- "連接此 RTSP URL,並在有人進入區域時發出警示。"
螢幕錄製(桌面擷取)
使用 ws_listener.py 在錄製工作階段期間擷取 WebSocket 事件。桌面擷取僅支援 macOS。
快速開始
- 選擇狀態目錄:
STATE_DIR="${VIDEODB_EVENTS_DIR:-$HOME/.local/state/videodb}" - 啟動監聽器:
VIDEODB_EVENTS_DIR="$STATE_DIR" python scripts/ws_listener.py --clear "$STATE_DIR" & - 取得 WebSocket ID:
cat "$STATE_DIR/videodb_ws_id" - 執行擷取程式碼(完整工作流程請參閱 reference/capture.md)
- 事件寫入:
$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 工具定位。
- reference/api-reference.md - 完整的 VideoDB Python SDK API 參考
- reference/search.md - 影片搜尋深入指南(語音和場景式)
- reference/editor.md - 時間軸編輯、資產和組合
- reference/streaming.md - HLS 串流和即時播放
- reference/generative.md - AI 驅動的媒體生成(圖片、影片、音訊)
- reference/rtstream.md - 即時串流擷取工作流程(RTSP/RTMP)
- reference/rtstream-reference.md - RTStream SDK 方法和 AI 管線
- reference/capture.md - 桌面擷取工作流程
- reference/capture-reference.md - 擷取 SDK 和 WebSocket 事件
- reference/use-cases.md - 常見影片處理模式和範例
當 VideoDB 支援該操作時,請勿使用 ffmpeg、moviepy 或本機編碼工具。以下所有操作均由 VideoDB 在伺服器端處理:修剪、合併剪輯、疊加音訊或音樂、新增字幕、文字/圖片疊加、轉碼、解析度變更、長寬比轉換、依平台需求調整大小、轉錄和媒體生成。僅在 reference/editor.md 中「限制」一節所列的操作(轉場、速度變更、裁切/縮放、調色、音量混合)才回退到本機工具。
何時使用何種工具
| 問題 | VideoDB 解決方案 |
|---|---|
| 平台拒絕影片長寬比或解析度 | video.reframe() 或搭配 VideoConfig 的 conn.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/ 目錄下。
請使用上述本機副本,而非在執行時期追蹤外部儲存庫連結。






