VideoDB Skill
Wahrnehmung + Gedächtnis + Aktionen für Videos, Live-Streams und Desktop-Sitzungen.
Wann verwenden
Desktop-Wahrnehmung
- Starten/Stoppen einer Desktop-Sitzung zum Erfassen von Bildschirm, Mikrofon und Systemaudio
- Streamen von Live-Kontext und Speichern von episodischem Sitzungsgedächtnis
- Ausführen von Echtzeit-Warnungen/Triggern zu Gesprochenem und Bildschirminhalten
- Erstellen von Sitzungszusammenfassungen, einer durchsuchbaren Zeitleiste und abspielbaren Beweislinks
Video-Import + Stream
- Importieren einer Datei oder URL und Rückgabe eines abspielbaren Web-Stream-Links
- Transkodieren/Normalisieren: Codec, Bitrate, fps, Auflösung, Seitenverhältnis
Index + Suche (Zeitstempel + Beweise)
- Aufbau von visuellen, gesprochenen und Schlüsselwort-Indizes
- Suche und Rückgabe genauer Momente mit Zeitstempeln und abspielbaren Beweisen
- Automatische Erstellung von Clips aus Suchergebnissen
Timeline-Bearbeitung + Generierung
- Untertitel: generieren, übersetzen, einbrennen
- Overlays: Text/Bild/Branding, Bewegtuntertitel
- Audio: Hintergrundmusik, Voiceover, Synchronisation (Dubbing)
- Programmatische Komposition und Exporte über Timeline-Operationen
Live-Streams (RTSP) + Überwachung
- Verbinden von RTSP/Live-Feeds
- Ausführen von visuellem und gesprochenem Echtzeit-Verständnis und Auslösen von Ereignissen/Warnungen für Überwachungsworkflows
Funktionsweise
Häufige Eingaben
- Lokaler Dateipfad, öffentliche URL oder RTSP-URL
- Desktop-Aufnahmeanfrage: Sitzung starten / stoppen / zusammenfassen
- Gewünschte Operationen: Kontext für Verständnis, Transkodierungsvorgabe, Indexspezifikation, Suchanfrage, Clip-Bereiche, Timeline-Bearbeitungen, Alarmregeln
Häufige Ausgaben
- Stream-URL
- Suchergebnisse mit Zeitstempeln und Beweislinks
- Generierte Assets: Untertitel, Audio, Bilder, Clips
- Ereignis-/Alarm-Payloads für Live-Streams
- Sitzungszusammenfassungen und Gedächtniseinträge vom Desktop
Python-Code ausführen
Vor der Ausführung von VideoDB-Code in das Projektverzeichnis wechseln und Umgebungsvariablen laden:
from dotenv import load_dotenv
load_dotenv(".env")
import videodb
conn = videodb.connect()
Dies liest VIDEO_DB_API_KEY aus:
- Umgebung (falls bereits exportiert)
.env-Datei des Projekts im aktuellen Verzeichnis
Wenn der Schlüssel fehlt, löst videodb.connect() automatisch AuthenticationError aus.
Keine Skriptdatei schreiben, wenn ein kurzer Inline-Befehl ausreicht.
Beim Schreiben von Inline-Python (python -c "...") immer korrekt formatierten Code verwenden – Semikolons zur Trennung von Anweisungen nutzen und lesbar halten. Für mehr als ~3 Anweisungen stattdessen einen Heredoc verwenden:
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
Einrichtung
Wenn der Benutzer „videodb einrichten“ oder ähnliches sagt:
1. SDK installieren
pip install "videodb[capture]" python-dotenv
Wenn videodb[capture] unter Linux fehlschlägt, ohne das capture-Extra installieren:
pip install videodb python-dotenv
2. API-Schlüssel konfigurieren
Der Benutzer muss VIDEO_DB_API_KEY mit einer der folgenden Methoden setzen:
- Im Terminal exportieren (vor dem Start von Claude):
export VIDEO_DB_API_KEY=dein-schlüssel - Projekt-
.env-Datei:VIDEO_DB_API_KEY=dein-schlüsselin der.env-Datei des Projekts speichern
Einen kostenlosen API-Schlüssel unter console.videodb.io erhalten (50 kostenlose Uploads, keine Kreditkarte erforderlich).
Den API-Schlüssel NICHT selbst lesen, schreiben oder verwalten. Immer den Benutzer das erledigen lassen.
Kurzreferenz
Medien hochladen
# URL
video = coll.upload(url="https://example.com/video.mp4")
# YouTube
video = coll.upload(url="https://www.youtube.com/watch?v=VIDEO_ID")
# Lokale Datei
video = coll.upload(file_path="/pfad/zum/video.mp4")
Transkript + Untertitel
# force=True überspringt den Fehler, falls das Video bereits indiziert ist
video.index_spoken_words(force=True)
text = video.get_transcript_text()
stream_url = video.add_subtitle()
In Videos suchen
from videodb.exceptions import InvalidRequestError
video.index_spoken_words(force=True)
# search() löst InvalidRequestError aus, wenn keine Ergebnisse gefunden werden.
# Immer in try/except packen und „Keine Ergebnisse gefunden“ als leeres Ergebnis behandeln.
try:
results = video.search("Produktdemo")
shots = results.get_shots()
stream_url = results.compile()
except InvalidRequestError as e:
if "No results found" in str(e):
shots = []
else:
raise
Szenensuche
import re
from videodb import SearchType, IndexType, SceneExtractionType
from videodb.exceptions import InvalidRequestError
# index_scenes() hat keinen force-Parameter – es löst einen Fehler aus, wenn ein
# Szenen-Index bereits existiert. Die vorhandene Index-ID aus dem Fehler extrahieren.
try:
scene_index_id = video.index_scenes(
extraction_type=SceneExtractionType.shot_based,
prompt="Beschreibe den visuellen Inhalt dieser Szene.",
)
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 verwenden, um Rauschen mit niedriger Relevanz zu filtern (empfohlen: 0,3+)
try:
results = video.search(
query="Person schreibt auf 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
Timeline-Bearbeitung
Wichtig: Vor dem Erstellen einer Timeline immer die Zeitstempel validieren:
startmuss >= 0 sein (negative Werte werden stillschweigend akzeptiert, erzeugen aber defekte Ausgaben)startmuss <endseinendmuss <=video.lengthsein
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="Das Ende", duration=3, style=TextStyle(fontsize=36)))
stream_url = timeline.generate_stream()
Video transkodieren (Auflösung / Qualität ändern)
from videodb import TranscodeMode, VideoConfig, AudioConfig
# Auflösung, Qualität oder Seitenverhältnis serverseitig ändern
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),
)
Seitenverhältnis ändern (für soziale Plattformen)
Warnung: reframe() ist eine langsame serverseitige Operation. Für lange Videos kann sie
mehrere Minuten dauern und möglicherweise ein Timeout auslösen. Best Practices:
- Nach Möglichkeit immer auf ein kurzes Segment mit
start/endbeschränken - Für vollständige Videos
callback_urlfür asynchrone Verarbeitung verwenden - Das Video zunächst auf einem
Timelinezuschneiden, dann das kürzere Ergebnis reframen
from videodb import ReframeMode
# Immer ein kurzes Segment reframen:
reframed = video.reframe(start=0, end=60, target="vertical", mode=ReframeMode.smart)
# Asynchrones Reframe für vollständige Videos (gibt None zurück, Ergebnis via Webhook):
video.reframe(target="vertical", callback_url="https://example.com/webhook")
# Voreinstellungen: "vertical" (9:16), "square" (1:1), "landscape" (16:9)
reframed = video.reframe(start=0, end=60, target="square")
# Benutzerdefinierte Abmessungen
reframed = video.reframe(start=0, end=60, target={"width": 1280, "height": 720})
Generative Medien
image = coll.generate_image(
prompt="ein Sonnenuntergang über den Bergen",
aspect_ratio="16:9",
)
Fehlerbehandlung
from videodb.exceptions import AuthenticationError, InvalidRequestError
try:
conn = videodb.connect()
except AuthenticationError:
print("Überprüfe deinen VIDEO_DB_API_KEY")
try:
video = coll.upload(url="https://example.com/video.mp4")
except InvalidRequestError as e:
print(f"Upload fehlgeschlagen: {e}")
Häufige Fallstricke
| Szenario | Fehlermeldung | Lösung |
|---|---|---|
| Indizieren eines bereits indizierten Videos | Spoken word index for video already exists | video.index_spoken_words(force=True) verwenden, um bei bereits indiziertem Video zu überspringen |
| Szenen-Index existiert bereits | Scene index with id XXXX already exists | Die vorhandene scene_index_id aus dem Fehler extrahieren mit re.search(r"id\s+([a-f0-9]+)", str(e)) |
| Suche findet keine Treffer | InvalidRequestError: No results found | Exception abfangen und als leeres Ergebnis behandeln (shots = []) |
| Reframe erhält Timeout | Blockiert bei langen Videos unbegrenzt | start/end verwenden, um das Segment zu begrenzen, oder callback_url für asynchrone Verarbeitung übergeben |
| Negative Zeitstempel in Timeline | Erzeugt stillschweigend defekte Streams | Vor Erstellung von VideoAsset immer start >= 0 validieren |
generate_video() / create_collection() schlägt fehl | Operation not allowed oder maximum limit | Planabhängige Funktionen – Benutzer über Planlimits informieren |
Beispiele
Kanonische Aufforderungen
- „Starte die Desktop-Aufnahme und warne mich, wenn ein Passwortfeld erscheint.“
- „Nimm meine Sitzung auf und erstelle eine umsetzbare Zusammenfassung, wenn sie endet.“
- „Importiere diese Datei und gib einen abspielbaren Stream-Link zurück.“
- „Indiziere diesen Ordner und finde jede Szene mit Personen, gib Zeitstempel zurück.“
- „Generiere Untertitel, brenne sie ein und füge leichte Hintergrundmusik hinzu.“
- „Verbinde diese RTSP-URL und alarmiere, wenn eine Person die Zone betritt.“
Bildschirmaufnahme (Desktop Capture)
Verwenden Sie ws_listener.py, um WebSocket-Ereignisse während Aufnahmesitzungen zu erfassen. Desktop-Aufnahmen werden nur unter macOS unterstützt.
Schnellstart
- State-Verzeichnis wählen:
STATE_DIR="${VIDEODB_EVENTS_DIR:-$HOME/.local/state/videodb}" - Listener starten:
VIDEODB_EVENTS_DIR="$STATE_DIR" python scripts/ws_listener.py --clear "$STATE_DIR" & - WebSocket-ID abrufen:
cat "$STATE_DIR/videodb_ws_id" - Capture-Code ausführen (siehe reference/capture.md für den vollständigen Workflow)
- Ereignisse werden geschrieben in:
$STATE_DIR/videodb_events.jsonl
--clear immer verwenden, wenn eine neue Aufnahme gestartet wird, damit keine alten Transkript- und visuellen Ereignisse in die neue Sitzung gelangen.
Ereignisse abfragen
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
]
Zusätzliche Dokumentation
Die Referenzdokumentation befindet sich im reference/-Verzeichnis neben dieser SKILL.md-Datei. Verwenden Sie das Glob-Tool, um sie bei Bedarf zu finden.
- reference/api-reference.md – Vollständige VideoDB Python SDK API-Referenz
- reference/search.md – Ausführlicher Leitfaden zur Videosuche (gesprochenes Wort und szenenbasiert)
- reference/editor.md – Timeline-Bearbeitung, Assets und Komposition
- reference/streaming.md – HLS-Streaming und sofortige Wiedergabe
- reference/generative.md – KI-gestützte Mediengenerierung (Bilder, Videos, Audio)
- reference/rtstream.md – Live-Stream-Import-Workflow (RTSP/RTMP)
- reference/rtstream-reference.md – RTStream SDK-Methoden und KI-Pipelines
- reference/capture.md – Desktop-Aufnahme-Workflow
- reference/capture-reference.md – Capture SDK und WebSocket-Ereignisse
- reference/use-cases.md – Häufige Videoverarbeitungsmuster und Beispiele
ffmpeg, moviepy oder lokale Codierungswerkzeuge NICHT verwenden, wenn VideoDB die Operation unterstützt. Folgendes wird alles serverseitig von VideoDB erledigt – Trimmen, Kombinieren von Clips, Überlagern von Audio oder Musik, Hinzufügen von Untertiteln, Text-/Bild-Overlays, Transkodierung, Auflösungsänderungen, Seitenverhältnis-Konvertierung, Größenänderung für Plattformanforderungen, Transkription und Mediengenerierung. Nur für Operationen, die unter „Einschränkungen“ in reference/editor.md aufgeführt sind (Übergänge, Geschwindigkeitsänderungen, Zuschneiden/Zoomen, Farbkorrektur, Lautstärkemischung), auf lokale Werkzeuge zurückgreifen.
Wann was verwenden
| Problem | VideoDB-Lösung |
|---|---|
| Plattform lehnt Seitenverhältnis oder Auflösung des Videos ab | video.reframe() oder conn.transcode() mit VideoConfig |
| Video für Twitter/Instagram/TikTok zuschneiden | video.reframe(target="vertical") oder target="square" |
| Auflösung ändern (z.B. 1080p → 720p) | conn.transcode() mit VideoConfig(resolution=720) |
| Audio/Musik auf Video überlagern | AudioAsset auf einem Timeline |
| Untertitel hinzufügen | video.add_subtitle() oder CaptionAsset |
| Clips kombinieren/trimmen | VideoAsset auf einem Timeline |
| Voiceover, Musik oder Soundeffekte generieren | coll.generate_voice(), generate_music(), generate_sound_effect() |
Herkunft
Referenzmaterial für diesen Skill wird lokal unter skills/videodb/reference/ bereitgestellt.
Verwenden Sie die lokalen Kopien, anstatt zur Laufzeit externen Repository-Links zu folgen.