VideoDB Skill
Wahrnehmung + Speicher + Aktionen für Video, Live-Streams und Desktop-Sitzungen.
Wann verwenden
Desktop-Wahrnehmung
- Starte/Stoppe eine Desktop-Sitzung und erfasse Bildschirm, Mikrofon und Systemaudio
- Streame Live-Kontext und speichere episodisches Sitzungsgedächtnis
- Führe Echtzeit-Alarme/Trigger basierend auf Gesprochenem und dem Bildschirmgeschehen aus
- Erstelle Sitzungszusammenfassungen, eine durchsuchbare Zeitleiste und abspielbare Beweislinks
Videoerfassung + Stream
- Erfasse eine Datei oder URL und gib einen abspielbaren Web-Stream-Link zurück
- Transkodiere/normalisiere: Codec, Bitrate, fps, Auflösung, Seitenverhältnis
Indizieren + Suchen (Zeitstempel + Nachweise)
- Erstelle visuelle, gesprochene und Schlüsselwort-Indizes
- Durchsuche und gib genaue Momente mit Zeitstempeln und abspielbaren Nachweisen zurück
- Erstelle automatisch Clips aus Suchergebnissen
Timeline-Editierung + Generierung
- Untertitel: generieren, übersetzen, einbrennen
- Überlagerungen: Text/Bild/Marken, Bewegungsuntertitel
- Audio: Hintergrundmusik, Voiceover, Synchronisation
- Programmgesteuerte Komposition und Exporte über Timeline-Operationen
Live-Streams (RTSP) + Überwachung
- Verbinde RTSP/Live-Feeds
- Führe visuelles und gesprochenes Echtzeitverständnis aus und sende Ereignisse/Alarme für Überwachungsworkflows
Wie es funktioniert
Häufige Eingaben
- Lokaler Dateipfad, öffentliche URL oder RTSP-URL
- Desktop-Aufnahmeanforderung: Sitzung starten / stoppen / zusammenfassen
- Gewünschte Operationen: Kontext für Verständnis, Transkodierungsspezifikation, Indizierungsspezifikation, Suchanfrage, Clip-Bereiche, Timeline-Änderungen, 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 Speichereinträge
Python-Code ausführen
Bevor du VideoDB-Code ausführst, wechsle in das Projektverzeichnis und lade Umgebungsvariablen:
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
Fehlt der Schlüssel, löst videodb.connect() automatisch AuthenticationError aus.
Schreibe KEINE Skriptdatei, wenn ein kurzer Inline-Befehl ausreicht.
Wenn du Python inline schreibst (python -c "..."), verwende immer korrekt formatierten Code – trenne Anweisungen mit Semikolons und halte es lesbar. Für mehr als ~3 Anweisungen verwende stattdessen einen Heredoc:
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
Falls videodb[capture] unter Linux fehlschlägt, installiere ohne das Capture-Extra:
pip install videodb python-dotenv
2. API-Schlüssel konfigurieren
Der Benutzer muss VIDEO_DB_API_KEY über eine der folgenden Methoden setzen:
- Im Terminal exportieren (vor dem Start von Claude):
export VIDEO_DB_API_KEY=dein-schluessel - Projekt-
.env-Datei: SpeichereVIDEO_DB_API_KEY=dein-schluesselin der.env-Datei des Projekts
Hole einen kostenlosen API-Schlüssel unter console.videodb.io (50 kostenlose Uploads, keine Kreditkarte erforderlich).
Lese, schreibe oder verarbeite den API-Schlüssel NICHT selbst. Überlasse es immer dem Benutzer, ihn zu setzen.
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/zu/video.mp4")
Transkript + Untertitel
# force=True überspringt den Fehler, wenn 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 „No results found“ als leer 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 Szenenindex
# bereits existiert. Extrahiere die vorhandene Index-ID aus dem Fehler.
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
# Verwende score_threshold, 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-Editierung
Wichtig: Überprüfe immer Zeitstempel, bevor du eine Timeline erstellst:
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ösungs-/Qualitätsänderung)
from videodb import TranscodeMode, VideoConfig, AudioConfig
# Ändere Auflösung, Qualität oder Seitenverhältnis serverseitig
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 anpassen (für soziale Plattformen)
Warnung: reframe() ist eine langsame serverseitige Operation. Bei langen Videos kann dies
mehrere Minuten dauern und einen Timeout verursachen. Best Practices:
- Beschränke die Operation immer auf ein kurzes Segment mit
start/end, wenn möglich - Verwende bei vollständigen Videos
callback_urlfür die asynchrone Verarbeitung - Schneide das Video zuerst auf einer
Timelinezu und passe dann das kürzere Ergebnis an
from videodb import ReframeMode
# Bevorzuge immer das Anpassen eines kurzen Segments:
reframed = video.reframe(start=0, end=60, target="vertical", mode=ReframeMode.smart)
# Asynchrones Reframing für vollständige Videos (gibt None zurück, Ergebnis über 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="Sonnenuntergang über 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 | Verwende video.index_spoken_words(force=True), um bei bereits indiziertem zu überspringen |
| Szenenindex existiert bereits | Scene index with id XXXX already exists | Extrahiere die vorhandene scene_index_id aus dem Fehler mit re.search(r"id\s+([a-f0-9]+)", str(e)) |
| Suche findet keine Treffer | InvalidRequestError: No results found | Fange die Ausnahme und behandle sie als leere Ergebnisse (shots = []) |
| Reframing-Zeitüberschreitung | Blockiert unbegrenzt bei langen Videos | Verwende start/end, um das Segment zu begrenzen, oder übergib callback_url für asynchrone Verarbeitung |
| Negative Zeitstempel in Timeline | Erzeugt stillschweigend defekten Stream | Überprüfe immer start >= 0 vor dem Erstellen von VideoAsset |
generate_video() / create_collection() schlägt fehl | Operation not allowed oder maximum limit | Funktionen abhängig vom Tarif – informiere den Benutzer über Tarifgrenzen |
Beispiele
Kanonische Eingabeaufforderungen
- „Starte Desktop-Aufnahme und alarmiere, wenn ein Passwortfeld erscheint.“
- „Zeichne meine Sitzung auf und erstelle eine umsetzbare Zusammenfassung, wenn sie endet.“
- „Erfasse 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-Aufnahme)
Verwende ws_listener.py, um WebSocket-Ereignisse während Aufnahmesitzungen zu erfassen. Desktop-Aufnahme wird nur unter macOS unterstützt.
Schnellstart
- Wähle ein Zustandsverzeichnis:
STATE_DIR="${VIDEODB_EVENTS_DIR:-$HOME/.local/state/videodb}" - Starte den Listener:
VIDEODB_EVENTS_DIR="$STATE_DIR" python scripts/ws_listener.py --clear "$STATE_DIR" & - Hole die WebSocket-ID:
cat "$STATE_DIR/videodb_ws_id" - Führe den Aufnahmecode aus (siehe reference/capture.md für den vollständigen Workflow)
- Ereignisse werden geschrieben nach:
$STATE_DIR/videodb_events.jsonl
Verwende --clear, wenn du eine neue Aufnahme startest, damit veraltete Transkript- und visuelle Ereignisse nicht in die neue Sitzung einfließen.
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 Verzeichnis reference/ neben dieser SKILL.md-Datei. Verwende 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 (gesprochene Wörter und szenenbasiert)
- reference/editor.md - Timeline-Editierung, Assets und Komposition
- reference/streaming.md - HLS-Streaming und sofortige Wiedergabe
- reference/generative.md - KI-gestützte Mediengenerierung (Bilder, Video, Audio)
- reference/rtstream.md - Workflow zur Live-Stream-Erfassung (RTSP/RTMP)
- reference/rtstream-reference.md - RTStream SDK-Methoden und KI-Pipelines
- reference/capture.md - Workflow zur Desktop-Aufnahme
- reference/capture-reference.md - Capture SDK und WebSocket-Ereignisse
- reference/use-cases.md - Häufige Videoverarbeitungsmuster und Beispiele
Verwende keine ffmpeg, moviepy oder lokale Kodierungswerkzeuge, wenn VideoDB die Operation unterstützt. Die folgenden Operationen werden alle serverseitig von VideoDB durchgeführt: Trimmen, Kombinieren von Clips, Überlagern von Audio oder Musik, Hinzufügen von Untertiteln, Text-/Bildüberlagerungen, Transkodierung, Auflösungsänderungen, Seitenverhältniskonvertierung, Größenänderung für Plattformanforderungen, Transkription und Mediengenerierung. Greife nur dann auf lokale Werkzeuge zurück, wenn die Operation unter den Einschränkungen in reference/editor.md aufgeführt ist (Übergänge, Geschwindigkeitsänderungen, Zuschneiden/Zoomen, Farbkorrektur, Lautstärkemischung).
Wann was verwenden
| Problem | VideoDB-Lösung |
|---|---|
| Plattform lehnt Seitenverhältnis oder Auflösung ab | video.reframe() oder conn.transcode() mit VideoConfig |
| Video für Twitter/Instagram/TikTok zuschneiden müssen | video.reframe(target="vertical") oder target="square" |
| Auflösung ändern müssen (z.B. 1080p → 720p) | conn.transcode() mit VideoConfig(resolution=720) |
| Audio/Musik auf Video überlagern müssen | AudioAsset auf einer Timeline |
| Untertitel hinzufügen müssen | video.add_subtitle() oder CaptionAsset |
| Clips kombinieren/trimmen müssen | VideoAsset auf einer Timeline |
| Voiceover, Musik oder SFX generieren müssen | coll.generate_voice(), generate_music(), generate_sound_effect() |
Herkunft
Referenzmaterial für diesen Skill wird lokal unter skills/videodb/reference/ bereitgestellt.
Verwende die lokalen Kopien oben anstelle von externen Repository-Links zur Laufzeit.