Communitygithub.com

Jamkris/everything-gemini-code

能夠對影片和音訊進行感知、理解與操作:從本地檔案、URL、RTSP/即時串流或桌面錄製進行擷取,回傳即時情境與可播放的串流連結;提取影格、建立視覺/語意/時間索引,並搜尋附有時間戳記與自動剪輯的瞬間;進行轉碼與正規化(編碼、FPS、解析度、長寬比)、時間軸編輯(字幕、文字/圖片疊加、品牌標示、音訊疊加、配音、翻譯)、產生媒體素材(圖片、音訊、影片),以及為即時串流或桌面擷取的事件建立即時警示。

everything-gemini-code 是什麼?

此技能將 VideoDB 轉變為一個全面的影片與音訊代理,能夠進行感知(透過擷取與即時串流)、記憶(透過索引、搜尋、時間戳記與自動剪輯)以及行動(透過轉碼、時間軸編輯與媒體生成)。它支援多種平台,包括 Claude Code、Gemini 及 Cursor,且涵蓋桌面擷取、RTSP 即時串流監控及批次影片處理等使用情境。開發人員可以透過 Python SDK 將影片上傳、轉碼、搜尋特定場景或口語詞彙、使用時間軸操作(如疊加字幕、音樂或文字)編輯影片,以及產生新媒體。該技能強調伺服器端處理,避免使用本機工具(如 ffmpeg),並提供完整的錯誤處理指南及常見陷阱的解決方案。其運作方式包括:設定 SDK、設定 API 金鑰、使用簡潔的 Python 程式碼區塊執行各項操作,並參考 `reference/` 目錄中的詳盡文件以取得更高階的用法。

相容平台✓Claude Code~Codex CLI~Cursor✓Gemini CLI
npx skills add https://github.com/Jamkris/everything-gemini-code/tree/HEAD/skills/videodb

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

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:

  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

如果 videodb[capture] 在 Linux 上安裝失敗,請安裝不含 capture 擴充功能的版本:

pip install videodb python-dotenv

2. 設定 API 金鑰

使用者必須使用任一方法設定 VIDEO_DB_API_KEY:

  • 在終端機中匯出(在啟動 Gemini 之前):export VIDEO_DB_API_KEY=你-的金鑰
  • 專案 .env 檔案:在專案的 .env 檔案中儲存 VIDEO_DB_API_KEY=你-的金鑰

在 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 包裹,並將「找不到結果」視為空值。
try:
    results = video.search("產品示範")
    shots = results.get_shots()
    stream_url = results.compile()
except InvalidRequestError as e:
    if "找不到結果" 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 "找不到結果" 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 修剪影片,再調整較短結果的長寬比
from videodb import ReframeMode

# 優先調整短片段的長寬比:
reframed = video.reframe(start=0, end=60, target="vertical", mode=ReframeMode.smart)

# 針對完整長度影片的非同步調整(回傳 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}")

常見陷阱

情境錯誤訊息解決方案
對已索引的影片進行索引影片的口語單字索引已存在使用 video.index_spoken_words(force=True) 在已索引時跳過
場景索引已存在場景索引 id XXXX 已存在使用 re.search(r"id\s+([a-f0-9]+)", str(e)) 從錯誤中擷取現有的 scene_index_id
搜尋未找到相符項目InvalidRequestError:找不到結果捕捉例外狀況,並將其視為空結果(shots = [])
調整長寬比超時長影片會無限期阻塞使用 start/end 限制片段,或傳入 callback_url 進行非同步處理
時間軸上的負值時間戳記靜默產生損壞的串流在建立 VideoAsset 之前務必驗證 start >= 0
generate_video() / create_collection() 失敗不允許的操作 或 達到上限方案限制的功能 — 告知使用者方案限制

範例

典型提示

  • 「啟動桌面擷取,並在出現密碼欄位時發出警示。」
  • 「錄製我的會話,並在結束時產生可行的摘要。」
  • 「擷取此檔案,並回傳可播放的串流連結。」
  • 「索引此資料夾,並找出所有包含人物的場景,回傳時間戳記。」
  • 「產生字幕、燒錄進去,並加入輕柔的背景音樂。」
  • 「連接此 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 ID:cat "$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() 或 conn.transcode() 搭配 VideoConfig
需要調整影片大小以符合 Twitter/Instagram/TikTokvideo.reframe(target="vertical") 或 target="square"
需要變更解析度(例如 1080p → 720p)conn.transcode() 搭配 VideoConfig(resolution=720)
需要在影片上疊加音訊/音樂在 Timeline 上使用 AudioAsset
需要加入字幕video.add_subtitle() 或 CaptionAsset
需要合併/修剪剪輯在 Timeline 上使用 VideoAsset
需要產生旁白、音樂或音效coll.generate_voice()、generate_music()、generate_sound_effect()

來源

此技能的參考資料位於本機的 skills/videodb/reference/ 目錄下。 請使用上述的本機副本,而非在執行時跟隨外部儲存庫連結。

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

相關技能