| name | videodb |
| description | 비디오와 오디오를 보고, 이해하고, 행동합니다. 보기- 로컬 파일, URL, RTSP/라이브 피드 또는 데스크톱 라이브 녹화에서 수집하고 실시간 컨텍스트와 재생 가능한 스트림 링크를 반환합니다. 이해하기- 프레임을 추출하고, 시각적/의미적/시간적 인덱스를 빌드하며, 타임스탬프와 자동 클립으로 순간을 검색합니다. 행동하기- 트랜스코딩 및 정규화(코덱, fps, 해상도, 가로세로비), 타임라인 편집(자막, 텍스트/이미지 오버레이, 브랜딩, 오디오 오버레이, 더빙, 번역), 미디어 자산 생성(이미지, 오디오, 비디오), 라이브 스트림이나 데스크톱 캡처 이벤트에 대한 실시간 알림을 생성합니다. |
| origin | ECC |
| allowed-tools | Read Grep Glob Bash(python:*) |
| argument-hint | [작업 설명] |
VideoDB 스킬
비디오, 라이브 스트림, 데스크톱 세션을 위한 인식 + 메모 + 액션.
사용 시점
데스크톱 인식
- 화면, 마이크, 시스템 오디오를 캡처하는 데스크톱 세션 시작/중지
- 실시간 컨텍스트 스트리밍 및 에피소드 세션 메모리 저장
- 화면에서 일어나는 일과 말소리에 대한 실시간 알림/트리거 실행
- 세션 요약, 검색 가능한 타임라인, 재생 가능한 증거 링크 생성
비디오 수집 + 스트림
- 파일 또는 URL을 수집하고 재생 가능한 웹 스트림 링크 반환
- 트랜스코딩/정규화: 코덱, 비트레이트, fps, 해상도, 가로세로비
인덱스 + 검색 (타임스탬프 + 증거)
- 시각적, 음성, 키워드 인덱스 빌드
- 타임스탬프와 재생 가능한 증거와 함께 정확한 순간 검색 및 반환
- 검색 결과에서 클립 자동 생성
타임라인 편집 + 생성
- 자막: 생성, 번역, 번인(burn-in)
- 오버레이: 텍스트/이미지/브랜딩, 모션 캡션
- 오디오: 배경 음악, 음성 해설, 더빙
- 타임라인 작업을 통한 프로그래밍 방식의 구성 및 내보내기
라이브 스트림 (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"Videos: {len(coll.get_videos())}")
EOF
설정
사용자가 "setup videodb" 등을 요청할 때:
1. SDK 설치
pip install "videodb[capture]" python-dotenv
Linux에서 videodb[capture]가 실패하면 캡처 익스트라 없이 설치하세요.
pip install videodb python-dotenv
2. API 키 구성
사용자는 다음 중 한 가지 방법을 사용하여 VIDEO_DB_API_KEY를 설정해야 합니다.
- 터미널에서 내보내기 (Claude를 시작하기 전):
export VIDEO_DB_API_KEY=your-key
- 프로젝트
.env 파일: 프로젝트의 .env 파일에 VIDEO_DB_API_KEY=your-key 저장
console.videodb.io에서 무료 API 키를 받으세요 (신용카드 없이 50개 무료 업로드 가능).
직접 API 키를 읽거나 쓰고 처리하지 마세요. 항상 사용자가 설정하도록 하세요.
빠른 참조
미디어 업로드
video = coll.upload(url="https://example.com/video.mp4")
video = coll.upload(url="https://www.youtube.com/watch?v=VIDEO_ID")
video = coll.upload(file_path="/path/to/video.mp4")
트랜스크립트 + 자막
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)
try:
results = video.search("제품 데모")
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
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
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에서 비디오를 트리밍한 다음 짧아진 결과를 리프레임하세요.
from videodb import ReframeMode
reframed = video.reframe(start=0, end=60, target="vertical", mode=ReframeMode.smart)
video.reframe(target="vertical", callback_url="https://example.com/webhook")
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 = [])로 처리 |
| 리프레임 시간 초과 | 긴 비디오에서 무기한 차단됨 | start/end를 사용하여 구간을 제한하거나 비동기를 위해 callback_url 전달 |
| 타임라인의 음수 타임스탬프 | 암시적으로 손상된 스트림 생성 | VideoAsset을 생성하기 전에 항상 start >= 0 검증 |
generate_video() / create_collection() 실패 | Operation not allowed 또는 maximum limit | 플랜 제한 기능 — 사용자에게 플랜 제한에 대해 알림 |
예시
표준 프롬프트
- "데스크톱 캡처를 시작하고 비밀번호 필드가 나타나면 알림을 보내줘."
- "내 세션을 녹화하고 종료되면 실행 가능한 요약을 만들어줘."
- "이 파일을 수집하고 재생 가능한 스트림 링크를 반환해줘."
- "이 폴더를 인덱싱하고 사람이 있는 모든 장면을 찾아 타임스탬프를 반환해줘."
- "자막을 생성하고 번인한 뒤 가벼운 배경 음악을 추가해줘."
- "이 RTSP URL을 연결하고 사람이 구역에 들어오면 알림을 보내줘."
화면 녹화 (데스크톱 캡처)
녹화 세션 중 WebSocket 이벤트를 캡처하려면 ws_listener.py를 사용하세요. 데스크톱 캡처는 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 도구를 사용하여 찾으세요.
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 |
| 음성 해설, 음악 또는 SFX 생성 필요 | coll.generate_voice(), generate_music(), generate_sound_effect() |
출처
이 스킬의 참조 자료는 skills/videodb/reference/ 아래에 로컬로 제공됩니다. 실행 시 외부 저장소 링크를 따라가는 대신 위의 로컬 복사본을 사용하세요.