Communitygithub.com

DekaPrayoga/AurixAgent

동영상 및 오디오를 보고, 이해하고, 행동합니다. 보기 – 로컬 파일, URL, RTSP/라이브 피드 또는 데스크톱 녹화에서 수집하여 실시간 컨텍스트와 재생 가능한 스트림 링크를 반환합니다. 이해하기 – 프레임을 추출하고 시각/의미/시간 인덱스를 구축하며 타임스탬프와 자동 클립으로 순간을 검색합니다. 행동하기 – 트랜스코딩 및 정규화(코덱, FPS, 해상도, 화면비), 타임라인 편집(자막, 텍스트/이미지 오버레이, 브랜딩, 오디오 오버레이, 더빙, 번역), 미디어 자산(이미지, 오디오, 비디오) 생성, 라이브 스트림 또는 데스크톱 캡처의 이벤트에 대한 실시간 알림을 생성합니다.

AurixAgent란 무엇인가요?

이 스킬은 비디오, 라이브 스트림, 데스크톱 세션에 대한 지각, 메모리, 작업을 제공하는 VideoDB 플랫폼을 기반으로 합니다. 개발자는 로컬 파일, URL, RTSP/라이브 피드 또는 데스크톱 캡처를 통해 미디어를 수집하고, 실시간 컨텍스트와 재생 가능한 스트림 링크를 얻을 수 있습니다. 또한 자막 생성/번역/burn-in, 텍스트/이미지 오버레이, 배경 음악, 더빙과 같은 타임라인 편집 기능과 시각, 음성, 키워드 인덱싱을 통한 정밀 검색을 지원합니다. 라이브 스트림 모니터링을 위한 실시간 이벤트/알림 시스템도 포함되어 있어 데스크톱 세션 요약, 검색 가능한 타임라인, 증거 링크를 제공합니다. Claude Code, Cursor, Codex 등 다양한 AI 에이전트 플랫폼에서 사용할 수 있으며, Python SDK를 통해 모든 기능을 API로 호출합니다.

지원 대상✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/DekaPrayoga/AurixAgent/tree/HEAD/skills/videodb

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

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를 다음에서 읽습니다:

  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"Videos: {len(coll.get_videos())}")
EOF

설정

사용자가 "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 키를 직접 읽거나, 쓰거나, 처리하지 마세요. 항상 사용자가 설정하도록 하세요.

빠른 참조

미디어 업로드

# 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는 < 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 반환, 결과는 웹훅으로 전달):
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 existsvideo.index_spoken_words(force=True)를 사용하여 이미 인덱싱된 경우 건너뛰기
장면 인덱스가 이미 존재Scene index with id XXXX already existsre.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요금제 제한 기능 — 사용자에게 요금제 제한에 대해 알림

예제

표준 프롬프트

  • "데스크톱 캡처를 시작하고 비밀번호 필드가 나타나면 알림을 보내."
  • "내 세션을 녹화하고 종료 시 실행 가능한 요약을 생성해."
  • "이 파일을 수집하고 재생 가능한 스트림 링크를 반환해."
  • "이 폴더를 인덱싱하고 사람이 있는 모든 장면을 찾아 타임스탬프를 반환해."
  • "자막을 생성하고 burn-in 처리한 후 가벼운 배경 음악을 추가해."
  • "이 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() 또는 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/ 아래에 로컬로 제공됩니다. 런타임에 외부 저장소 링크를 따르는 대신 위의 로컬 복사본을 사용하세요.


이 문서는 AI 에이전트 사용을 위해 현지화되었습니다.

Individual skills in this repo

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

관련 스킬