diff --git a/.github/workflows/generate-from-spec.yml b/.github/workflows/generate-from-spec.yml new file mode 100644 index 0000000..d093e79 --- /dev/null +++ b/.github/workflows/generate-from-spec.yml @@ -0,0 +1,167 @@ +name: Generate SDK from OpenAPI Spec + +on: + push: + paths: + - 'openapi.yaml' + + # Manual trigger for testing + workflow_dispatch: + +jobs: + generate: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + + steps: + - name: Checkout Python SDK + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Get branch and diff info + id: info + run: | + # Get the branch name this workflow is running on + BRANCH_NAME="${GITHUB_REF#refs/heads/}" + echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT + + # Get commit SHAs for diff + BEFORE_SHA="${{ github.event.before }}" + AFTER_SHA="${{ github.sha }}" + + # Handle new branch case + if [[ "$BEFORE_SHA" == "0000000000000000000000000000000000000000" ]]; then + BEFORE_SHA=$(git rev-parse HEAD~1 2>/dev/null || echo "") + fi + + echo "before_sha=$BEFORE_SHA" >> $GITHUB_OUTPUT + echo "after_sha=$AFTER_SHA" >> $GITHUB_OUTPUT + + # Generate diff for the spec file + if [[ -n "$BEFORE_SHA" ]]; then + git diff "$BEFORE_SHA" "$AFTER_SHA" -- openapi.yaml > spec.diff || touch spec.diff + else + touch spec.diff + fi + + echo "Diff size: $(wc -l < spec.diff) lines" + echo "Running on branch: $BRANCH_NAME" + + - name: Fetch prompt and build context + run: | + # Fetch static prompt from agent-toolkit + curl -sL https://raw.githubusercontent.com/video-db/agent-toolkit/main/context/prompts/spec-to-python-sdk.txt > static_prompt.txt + + # Build full prompt with dynamic content + cat > codex_prompt.md << 'PROMPT_EOF' + ## Git Diff of OpenAPI Spec Changes + + The following diff shows what changed in the API specification: + + ```diff + PROMPT_EOF + + cat spec.diff >> codex_prompt.md + + cat >> codex_prompt.md << 'PROMPT_EOF' + ``` + + ## Current OpenAPI Spec + + If you need to reference the full spec for context, it's available at: openapi.yaml + + --- + + PROMPT_EOF + + # Append static instructions + cat static_prompt.txt >> codex_prompt.md + + echo "Prompt built successfully" + + - name: Run Codex + uses: openai/codex-action@v1 + with: + openai-api-key: ${{ secrets.OPENAI_API_KEY }} + model: o4-mini + sandbox: workspace-write + prompt-file: codex_prompt.md + + - name: Check for changes and create PR + id: create_pr + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # Configure git + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + # Check if there are changes + if git diff --quiet && git diff --staged --quiet; then + echo "No changes generated by Codex" + echo "has_changes=false" >> $GITHUB_OUTPUT + exit 0 + fi + + echo "has_changes=true" >> $GITHUB_OUTPUT + + # Clean up temporary files - DO NOT commit these + rm -f spec.diff static_prompt.txt codex_prompt.md + + # Get the base branch name + BASE_BRANCH="${{ steps.info.outputs.branch_name }}" + + # Create work branch from the current branch + WORK_BRANCH="auto/spec-sync-$(date +%Y%m%d-%H%M%S)" + git checkout -b "$WORK_BRANCH" + git add -A + + # Commit + git commit -m "feat: sync with OpenAPI spec changes + + Source branch: ${BASE_BRANCH} + + Generated by OpenAI Codex" + + # Push + git push origin "$WORK_BRANCH" + + echo "work_branch=$WORK_BRANCH" >> $GITHUB_OUTPUT + echo "base_branch=$BASE_BRANCH" >> $GITHUB_OUTPUT + + # Create PR targeting the original branch + gh pr create \ + --base "$BASE_BRANCH" \ + --title "feat: sync with OpenAPI spec" \ + --body "## Summary + + Automated SDK update based on OpenAPI spec changes. + + **Base branch**: \`$BASE_BRANCH\` + + ## Review Checklist + + - [ ] Generated code follows SDK conventions + - [ ] Method signatures are correct + - [ ] No breaking changes introduced + - [ ] Tests pass locally + + --- + *Generated by [OpenAI Codex](https://github.com/openai/codex)*" + + - name: Trigger Node SDK Generation + if: steps.create_pr.outputs.has_changes == 'true' + uses: peter-evans/repository-dispatch@v3 + with: + token: ${{ secrets.SDK_SYNC_PAT }} + repository: ${{ github.repository_owner }}/videodb-node + event-type: python-updated + client-payload: | + { + "source_branch": "${{ steps.create_pr.outputs.work_branch }}", + "target_branch": "${{ steps.create_pr.outputs.base_branch }}", + "trigger_type": "spec_change" + } diff --git a/.github/workflows/notify-node-sdk.yml b/.github/workflows/notify-node-sdk.yml new file mode 100644 index 0000000..e83ba3a --- /dev/null +++ b/.github/workflows/notify-node-sdk.yml @@ -0,0 +1,91 @@ +name: Notify Node SDK on Python Code Changes + +on: + push: + paths: + - 'videodb/*.py' + - 'videodb/**/*.py' + - '!videodb/__about__.py' + - '!videodb/__init__.py' + +jobs: + notify: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Check if spec also changed + id: check_spec + run: | + BEFORE_SHA="${{ github.event.before }}" + AFTER_SHA="${{ github.sha }}" + + # Handle new branch case + if [[ "$BEFORE_SHA" == "0000000000000000000000000000000000000000" ]]; then + BEFORE_SHA=$(git rev-parse HEAD~1 2>/dev/null || echo "") + fi + + # Check if openapi.yaml changed in this push + if [[ -n "$BEFORE_SHA" ]]; then + SPEC_CHANGED=$(git diff --name-only "$BEFORE_SHA" "$AFTER_SHA" -- openapi.yaml | wc -l) + else + SPEC_CHANGED=0 + fi + + if [[ "$SPEC_CHANGED" -gt 0 ]]; then + echo "spec_changed=true" >> $GITHUB_OUTPUT + echo "Spec also changed - skipping (generate-from-spec.yml will handle this)" + else + echo "spec_changed=false" >> $GITHUB_OUTPUT + echo "Only Python code changed - will notify Node SDK" + fi + + - name: Get branch and changed files + if: steps.check_spec.outputs.spec_changed == 'false' + id: info + run: | + # Get the branch name + BRANCH_NAME="${GITHUB_REF#refs/heads/}" + echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT + + BEFORE_SHA="${{ github.event.before }}" + AFTER_SHA="${{ github.sha }}" + + # Handle new branch case + if [[ "$BEFORE_SHA" == "0000000000000000000000000000000000000000" ]]; then + BEFORE_SHA=$(git rev-parse HEAD~1 2>/dev/null || echo "") + fi + + # Get changed Python files (comma-separated for JSON) + if [[ -n "$BEFORE_SHA" ]]; then + FILES=$(git diff --name-only "$BEFORE_SHA" "$AFTER_SHA" -- 'videodb/*.py' 'videodb/**/*.py' | grep -v '__about__\|__init__' | tr '\n' ',' | sed 's/,$//' || true) + else + FILES="" + fi + + echo "changed_files=$FILES" >> $GITHUB_OUTPUT + echo "before_sha=$BEFORE_SHA" >> $GITHUB_OUTPUT + echo "after_sha=$AFTER_SHA" >> $GITHUB_OUTPUT + + echo "Branch: $BRANCH_NAME" + echo "Changed files: $FILES" + + - name: Trigger Node SDK Generation + if: steps.check_spec.outputs.spec_changed == 'false' && steps.info.outputs.changed_files != '' + uses: peter-evans/repository-dispatch@v3 + with: + token: ${{ secrets.SDK_SYNC_PAT }} + repository: ${{ github.repository_owner }}/videodb-node + event-type: python-updated + client-payload: | + { + "source_branch": "${{ steps.info.outputs.branch_name }}", + "target_branch": "${{ steps.info.outputs.branch_name }}", + "trigger_type": "code_change", + "changed_files": "${{ steps.info.outputs.changed_files }}", + "before_sha": "${{ steps.info.outputs.before_sha }}", + "after_sha": "${{ steps.info.outputs.after_sha }}" + } diff --git a/README.md b/README.md index a3ab4a1..97eddcc 100644 --- a/README.md +++ b/README.md @@ -36,207 +36,678 @@ # VideoDB Python SDK -VideoDB Python SDK allows you to interact with the VideoDB serverless database. Manage videos as intelligent data, not files. It's scalable, cost-efficient & optimized for AI applications and LLM integration. - - - - - +VideoDB Python SDK provides programmatic access to VideoDB's serverless video infrastructure. Build AI applications that understand and process video as structured data with support for semantic search, scene extraction, transcript generation, and multimodal content generation. + +## 📑 Table of Contents + +- [Installation](#installation) +- [Quick Start](#quick-start) + - [Establishing a Connection](#establishing-a-connection) + - [Uploading Media](#uploading-media) + - [Viewing and Streaming Videos](#viewing-and-streaming-videos) + - [Searching Inside Videos](#searching-inside-videos) + - [Working with Transcripts](#working-with-transcripts) + - [Scene Extraction and Indexing](#scene-extraction-and-indexing) + - [Adding Subtitles](#adding-subtitles) + - [Generating Thumbnails](#generating-thumbnails) +- [Working with Collections](#working-with-collections) + - [Audio and Image Management](#audio-and-image-management) +- [Advanced Features](#advanced-features) + - [Realtime Video Editor](#realtime-video-editor) + - [Real-Time Streams (RTStream)](#real-time-streams-rtstream) + - [Meeting Recording](#meeting-recording) + - [Generative Media](#generative-media) + - [Video Dubbing and Translation](#video-dubbing-and-translation) + - [Transcoding](#transcoding) + - [YouTube Integration](#youtube-integration) + - [Billing and Usage](#billing-and-usage) + - [Download Streams](#download-streams) +- [Configuration Options](#configuration-options) + - [Subtitle Customization](#subtitle-customization) + - [Text Overlay Styling](#text-overlay-styling) +- [Error Handling](#error-handling) +- [API Reference](#api-reference) +- [Examples and Tutorials](#examples-and-tutorials) +- [Contributing](#contributing) +- [Resources](#resources) +- [License](#license) ## Installation -To install the package, run the following command in your terminal: - -``` +```bash pip install videodb ``` - +**Requirements:** +- Python 3.8 or higher +- Dependencies: `requests>=2.25.1`, `backoff>=2.2.1`, `tqdm>=4.66.1` ## Quick Start -### Creating a Connection +### Establishing a Connection -Get an API key from the [VideoDB console](https://console.videodb.io). Free for first 50 uploads _(No credit card required)_. +Get your API key from [VideoDB Console](https://console.videodb.io). Free for first 50 uploads (no credit card required). ```python import videodb + +# Connect using API key conn = videodb.connect(api_key="YOUR_API_KEY") + +# Or set environment variable VIDEO_DB_API_KEY +# conn = videodb.connect() ``` -## Working with a Single Video +### Uploading Media ---- +Upload videos, audio files, or images from various sources: -### ⬆️ Uploading a Video +```python +# Upload video from YouTube URL +video = conn.upload(url="https://www.youtube.com/watch?v=VIDEO_ID") + +# Upload from public URL +video = conn.upload(url="https://example.com/video.mp4") + +# Upload from local file +video = conn.upload(file_path="./my_video.mp4") -Now that you have established a connection to VideoDB, you can upload your videos using `conn.upload()`. -You can directly upload from `youtube`, `any public url`, `S3 bucket` or a `local file path`. A default collection is created when you create your first connection. +# Upload with metadata +video = conn.upload( + file_path="./video.mp4", + name="My Video", + description="Video description" +) +``` + +The `upload()` method returns `Video`, `Audio`, or `Image` objects based on the media type. -`upload` method returns a `Video` object. You can simply pass a single string -representing either a local file path or a URL. +### Viewing and Streaming Videos ```python -# Upload a video by url -video = conn.upload("https://www.youtube.com/watch?v=WDv4AWk0J3U") +# Generate stream URL +stream_url = video.generate_stream() -# Upload a video from file system -video_f = conn.upload("./my_video.mp4") +# Play stream using VideoDB player +videodb.play_stream(stream_url) +# Play in browser/notebook +video.play() ``` -### 📺 View your Video +### Searching Inside Videos -Once uploaded, your video is immediately available for viewing in 720p resolution. ⚡️ +Index and search video content semantically: -- Generate a streamable url for the video using video.generate_stream() -- Preview the video using video.play(). This will open the video in your default browser/notebook +```python +from videodb import SearchType, IndexType + +# Index spoken words for semantic search +video.index_spoken_words() + +# Search for content +results = video.search("morning sunlight") + +# Access search results +shots = results.get_shots() +for shot in shots: + print(f"Found at {shot.start}s - {shot.end}s: {shot.text}") + +# Play compiled results +results.play() +``` + +**Search Types:** +- `SearchType.semantic` - Semantic search (default) +- `SearchType.keyword` - Keyword-based search +- `SearchType.scene` - Visual scene search + +### Working with Transcripts ```python -video.generate_stream() -video.play() +# Generate transcript +video.generate_transcript() + +# Get transcript with timestamps +transcript = video.get_transcript() + +# Get plain text transcript +text = video.get_transcript_text() + +# Get transcript for specific time range +transcript = video.get_transcript(start=10, end=60) + +# Translate transcript +translated = video.translate_transcript( + language="Spanish", + additional_notes="Formal tone" +) ``` -### ⛓️ Stream Specific Sections of Videos +**Segmentation Options:** +- `videodb.Segmenter.word` - Word-level timestamps +- `videodb.Segmenter.sentence` - Sentence-level timestamps +- `videodb.Segmenter.time` - Time-based segments + +### Scene Extraction and Indexing -You can easily clip specific sections of a video by passing a timeline of the start and end timestamps (in seconds) as a parameter. -For example, this will generate and play a compilation of the first `10 seconds` and the clip between the `120th` and the `140th` second. +Extract and analyze scenes from videos: ```python -stream_link = video.generate_stream(timeline=[[0,10], [120,140]]) -play_stream(stream_link) +from videodb import SceneExtractionType + +# Extract scenes using shot detection +scene_collection = video.extract_scenes( + extraction_type=SceneExtractionType.shot_based, + extraction_config={"threshold": 20, "frame_count": 1} +) + +# Extract scenes at time intervals +scene_collection = video.extract_scenes( + extraction_type=SceneExtractionType.time_based, + extraction_config={ + "time": 10, + "frame_count": 1, + "select_frames": ["first"] + } +) + +# Index scenes for semantic search +scene_index_id = video.index_scenes( + extraction_type=SceneExtractionType.shot_based, + prompt="Describe the visual content of this scene" +) + +# Search within scenes +results = video.search( + query="outdoor landscape", + search_type=SearchType.scene, + index_type=IndexType.scene +) + +# List scene indexes +scene_indexes = video.list_scene_index() + +# Get specific scene index +scenes = video.get_scene_index(scene_index_id) + +# Delete scene collection +video.delete_scene_collection(scene_collection.id) ``` -### 🔍 Search Inside a Video +### Adding Subtitles + +```python +from videodb import SubtitleStyle + +# Add subtitles with default style +stream_url = video.add_subtitle() + +# Customize subtitle appearance +style = SubtitleStyle( + font_name="Arial", + font_size=24, + primary_colour="&H00FFFFFF", + bold=True +) +stream_url = video.add_subtitle(style=style) +``` -To search bits inside a video, you have to `index` the video first. This can be done by a simple command. -_P.S. Indexing may take some time for longer videos._ +### Generating Thumbnails ```python -video.index_spoken_words() -result = video.search("Morning Sunlight") -result.play() -video.get_transcript() +# Get default thumbnail +thumbnail_url = video.generate_thumbnail() + +# Generate thumbnail at specific timestamp +thumbnail_image = video.generate_thumbnail(time=30.5) + +# Get all thumbnails +thumbnails = video.get_thumbnails() ``` -`Videodb` is launching more indexing options in upcoming versions. As of now you can try the `semantic` index - Index by spoken words. +## Working with Collections -In the future you'll be able to index videos using: +Organize and search across multiple videos: -1. **Scene** - Visual concepts and events. -2. **Faces**. -3. **Specific domain Index** like Football, Baseball, Drone footage, Cricket etc. +```python +# Get default collection +coll = conn.get_collection() -### Viewing Search Results +# Create new collection +coll = conn.create_collection( + name="My Collection", + description="Collection description", + is_public=False +) -`video.search()` returns a `SearchResults` object, which contains the sections or as we call them, `shots` of videos which semantically match your search query. +# List all collections +collections = conn.get_collections() -- `result.get_shots()` Returns a list of Shot(s) that matched the search query. -- `result.play()` Returns a playable url for the video (similar to video.play(); you can open this link in the browser, or embed it into your website using an iframe). +# Update collection +coll = conn.update_collection( + id="collection_id", + name="Updated Name", + description="Updated description" +) -## RAG: Search inside Multiple Videos +# Upload to collection +video = coll.upload(url="https://example.com/video.mp4") ---- +# Get videos in collection +videos = coll.get_videos() +video = coll.get_video(video_id) -`VideoDB` can store and search inside multiple videos with ease. By default, videos are uploaded to your default collection. +# Search across collection +results = coll.search(query="specific content") -### 🔄 Using Collection to Upload Multiple Videos +# Search by title +results = coll.search_title("video title") + +# Make collection public/private +coll.make_public() +coll.make_private() + +# Delete collection +coll.delete() +``` + +### Audio and Image Management ```python -# Get the default collection -coll = conn.get_collection() +# Get audio files +audios = coll.get_audios() +audio = coll.get_audio(audio_id) + +# Generate audio URL +audio_url = audio.generate_url() + +# Get images +images = coll.get_images() +image = coll.get_image(image_id) -# Upload Videos to a collection -coll.upload("https://www.youtube.com/watch?v=lsODSDmY4CY") -coll.upload("https://www.youtube.com/watch?v=vZ4kOr38JhY") -coll.upload("https://www.youtube.com/watch?v=uak_dXHh6s4") +# Generate image URL +image_url = image.generate_url() + +# Delete media +audio.delete() +image.delete() ``` -- `conn.get_collection()` : Returns a Collection object; the default collection. -- `coll.get_videos()` : Returns a list of Video objects; all videos in the collections. -- `coll.get_video(video_id)`: Returns a Video object, corresponding video from the provided `video_id`. -- `coll.delete_video(video_id)`: Deletes the video from the Collection. +## Advanced Features + +### Realtime Video Editor -### 📂 Search Inside Collection +Build multi-track video compositions programmatically using VideoDB's 4-layer architecture: **Assets** (raw media), **Clips** (how assets appear), **Tracks** (timeline lanes), and **Timeline** (final canvas). -You can simply Index all the videos in a collection and use the search method to find relevant results. -Here we are indexing the spoken content of a collection and performing semantic search. +**Example: Video with background music** ```python -# Index all videos in collection -for video in coll.get_videos(): - video.index_spoken_words() +from videodb import connect +from videodb.editor import Timeline, Track, Clip, VideoAsset, AudioAsset + +conn = connect(api_key="YOUR_API_KEY") +video = conn.upload(url="https://www.youtube.com/watch?v=VIDEO_ID") +audio = conn.upload(file_path="./music.mp3") + +# Create timeline +timeline = Timeline(conn) + +# Video track +video_track = Track() +video_asset = VideoAsset(id=video.id, start=10) +video_clip = Clip(asset=video_asset, duration=30) +video_track.add_clip(0, video_clip) + +# Audio track +audio_track = Track() +audio_asset = AudioAsset(id=audio.id, start=0, volume=0.3) +audio_clip = Clip(asset=audio_asset, duration=30) +audio_track.add_clip(0, audio_clip) + +# Compose and render +timeline.add_track(video_track) +timeline.add_track(audio_track) +stream_url = timeline.generate_stream() +``` -# search in the collection of videos -results = coll.search(query = "What is Dopamine?") -results.play() +**Asset Types:** +- `VideoAsset` - Video clips with trim control (`start`, `volume`) +- `AudioAsset` - Background music, voiceovers, sound effects +- `ImageAsset` - Logos, watermarks, static overlays +- `TextAsset` - Custom text with typography (`Font`, `Background`, `Alignment`) +- `CaptionAsset` - Auto-generated subtitles synced to speech + +**Clip Controls:** +- **Position & Scale**: `position=Position.topRight`, `scale=0.5`, `offset=Offset(x=0.1, y=-0.2)` +- **Visual Effects**: `opacity=0.8`, `fit=Fit.cover`, `filter=Filter.greyscale` +- **Transitions**: `transition=Transition(in_="fade", out="fade", duration=1)` + +**Track Layering:** +- Clips on the same track play sequentially +- Clips on different tracks at the same time play simultaneously (overlays) + +For advanced patterns (picture-in-picture, multi-audio layers, auto-captions), see the [Editor SDK documentation](https://docs.videodb.io/realtime-video-editor-sdk-44). + +### Real-Time Streams (RTStream) + +Process live video streams in real-time: + +```python +from videodb import SceneExtractionType + +# Connect to real-time stream +rtstream = coll.connect_rtstream( + url="rtsp://example.com/stream", + name="Live Stream" +) + +# Start or Stop processing +rtstream.stop() +rtstream.start() + +# Index scenes from stream +scene_index = rtstream.index_scenes( + extraction_type=SceneExtractionType.time_based, + extraction_config={"time": 2, "frame_count": 5}, + prompt="Describe the scene" +) + +# Start or Stop scene indexing +scene_index.stop() +scene_index.start() + +# Get scenes +scenes = scene_index.get_scenes(page=1, page_size=100) + +# Create alerts for events +alert_id = scene_index.create_alert( + event_id=event_id, + callback_url="https://example.com/callback" +) + +# Enable/disable alerts + +scene_index.disable_alert(alert_id) +scene_index.enable_alert(alert_id) + + +# List streams +streams = coll.list_rtstreams() ``` -The result here has all the matching bits in a single stream from your collection. You can use these results in your application right away. +### Meeting Recording -### 🌟 Explore the Video object +Record and process virtual meetings: -There are multiple methods available on a Video Object, that can be helpful for your use-case. +```python +# Start meeting recording +meeting = conn.record_meeting( + meeting_url="https://meet.google.com/xxx-yyyy-zzz", + bot_name="Recorder Bot", + meeting_title="Team Meeting", + callback_url="https://example.com/callback" +) + +# Check meeting status +meeting.refresh() +print(meeting.status) # initializing, processing, or done + +# Wait for completion +meeting.wait_for_status("done", timeout=14400, interval=120) + +# Get meeting details +if meeting.is_completed: + video_id = meeting.video_id + video = coll.get_video(video_id) + +# Get meeting from video +meeting_info = video.get_meeting() +``` -**Get the Transcript** +### Generative Media + +Generate images, audio, and videos using AI: ```python -# words with timestamps -text_json = video.get_transcript() -text = video.get_transcript_text() -print(text) +# Generate image +image = coll.generate_image( + prompt="A beautiful sunset over mountains", + aspect_ratio="16:9" +) + +# Generate music +audio = coll.generate_music( + prompt="Upbeat electronic music", + duration=30 +) + +# Generate sound effects +audio = coll.generate_sound_effect( + prompt="Door closing sound", + duration=2 +) + +# Generate voice from text +audio = coll.generate_voice( + text="Hello, welcome to VideoDB", + voice_name="Default" +) + +# Generate video +video = coll.generate_video( + prompt="A cat playing with a ball", + duration=5 +) + +# Generate text using LLM +response = coll.generate_text( + prompt="Summarize this content", + model_name="pro", # basic, pro, or ultra + response_type="text" # text or json +) +``` + +### Video Dubbing and Translation + +```python +# Dub video to another language +dubbed_video = coll.dub_video( + video_id=video.id, + language_code="es", + callback_url="https://example.com/callback" +) +``` + +### Transcoding + +```python +from videodb import TranscodeMode, VideoConfig, AudioConfig + +# Start transcoding job +job_id = conn.transcode( + source="https://example.com/video.mp4", + callback_url="https://example.com/callback", + mode=TranscodeMode.economy, + video_config=VideoConfig(resolution=1080, quality=23), + audio_config=AudioConfig(mute=False) +) + +# Check transcode status +status = conn.get_transcode_details(job_id) ``` -**Add Subtitles to a video** +### YouTube Integration + +```python +# Search YouTube +results = conn.youtube_search( + query="machine learning tutorial", + result_threshold=10, + duration="medium" +) + +for result in results: + print(result["title"], result["url"]) +``` -It returns a new stream instantly with subtitles added to the video. +### Billing and Usage ```python -new_stream = video.add_subtitle() -play_stream(new_stream) +# Check usage +usage = conn.check_usage() + +# Get invoices +invoices = conn.get_invoices() ``` -**Get Thumbnail of a Video:** +### Download Streams -`video.generate_thumbnail()`: Returns a thumbnail image of video. +```python +# Download compiled stream +download_info = conn.download( + stream_link="https://stream.videodb.io/...", + name="my_compilation" +) +``` -**Delete a video:** +## Configuration Options -`video.delete()`: Deletes the video. +### Subtitle Customization -Checkout more examples and tutorials 👉 [Build with VideoDB](https://docs.videodb.io/build-with-videodb-35) to explore what you can build with `VideoDB`. +```python +from videodb import SubtitleStyle, SubtitleAlignment, SubtitleBorderStyle + +style = SubtitleStyle( + font_name="Arial", + font_size=18, + primary_colour="&H00FFFFFF", # White + secondary_colour="&H000000FF", # Blue + outline_colour="&H00000000", # Black + back_colour="&H00000000", # Black + bold=False, + italic=False, + underline=False, + strike_out=False, + scale_x=1.0, + scale_y=1.0, + spacing=0, + angle=0, + border_style=SubtitleBorderStyle.outline, + outline=1.0, + shadow=0.0, + alignment=SubtitleAlignment.bottom_center, + margin_l=10, + margin_r=10, + margin_v=10 +) +``` ---- +### Text Overlay Styling + +```python +from videodb import TextStyle + +style = TextStyle( + fontsize=24, + fontcolor="black", + font="Sans", + box=True, + boxcolor="white", + boxborderw="10" +) +``` - +## Error Handling -## Roadmap +```python +from videodb.exceptions import ( + VideodbError, + AuthenticationError, + InvalidRequestError, + SearchError +) + +try: + conn = videodb.connect(api_key="invalid_key") +except AuthenticationError as e: + print(f"Authentication failed: {e}") + +try: + video = conn.upload(url="invalid_url") +except InvalidRequestError as e: + print(f"Invalid request: {e}") + +try: + results = video.search("query") +except SearchError as e: + print(f"Search error: {e}") +``` -- Adding More Indexes : `Face`, `Scene`, `Security`, `Events`, and `Sports` -- Give prompt support to generate thumbnails using GenAI. -- Give prompt support to access content. -- Give prompt support to edit videos. -- See the [open issues](https://github.com/video-db/videodb-python/issues) for a list of proposed features (and known issues). +## API Reference ---- +### Core Objects + +- **Connection**: Main client for API interaction +- **Collection**: Container for organizing media +- **Video**: Video file with processing methods +- **Audio**: Audio file representation +- **Image**: Image file representation +- **Timeline**: Multi-track video editor +- **SearchResult**: Search results with shots +- **Shot**: Time-segmented video clip +- **Scene**: Visual scene with frames +- **SceneCollection**: Collection of extracted scenes +- **Meeting**: Meeting recording session +- **RTStream**: Real-time stream processor + +### Constants and Enums + +- `IndexType`: `spoken_word`, `scene` +- `SearchType`: `semantic`, `keyword`, `scene` +- `SceneExtractionType`: `shot_based`, `time_based` +- `Segmenter`: `word`, `sentence`, `time` +- `TranscodeMode`: `lightning`, `economy` +- `MediaType`: `video`, `audio`, `image` + +For detailed API documentation, visit [docs.videodb.io](https://docs.videodb.io). - +## Examples and Tutorials + +Explore practical examples and use cases in the [VideoDB Cookbook](https://github.com/video-db/videodb-cookbook): + +- Semantic video search +- Scene-based indexing and retrieval +- Custom video compilations +- Meeting transcription and analysis +- Real-time stream processing +- Multi-language video dubbing ## Contributing -Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. +Contributions are welcome! To contribute: -1. Fork the Project -2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`) -3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`) -4. Push to the Branch (`git push origin feature/AmazingFeature`) +1. Fork the repository +2. Create your feature branch (`git checkout -b feature/AmazingFeature`) +3. Commit your changes (`git commit -m 'Add AmazingFeature'`) +4. Push to the branch (`git push origin feature/AmazingFeature`) 5. Open a Pull Request +## Resources + +- **Documentation**: [docs.videodb.io](https://docs.videodb.io) +- **Console**: [console.videodb.io](https://console.videodb.io) +- **Examples**: [github.com/video-db/videodb-cookbook](https://github.com/video-db/videodb-cookbook) +- **Community**: [Discord](https://discord.gg/py9P639jGz) +- **Issues**: [GitHub Issues](https://github.com/video-db/videodb-python/issues) + +## License + +Apache License 2.0 - see [LICENSE](LICENSE) file for details. + --- - [pypi-shield]: https://img.shields.io/pypi/v/videodb?style=for-the-badge [pypi-url]: https://pypi.org/project/videodb/ diff --git a/openapi.yaml b/openapi.yaml new file mode 100644 index 0000000..5a0aa0b --- /dev/null +++ b/openapi.yaml @@ -0,0 +1,2806 @@ +openapi: 3.0.3 +info: + title: VideoDB Server API + description: | + VideoDB Server API for video, audio, and image processing with AI capabilities. + This API provides comprehensive video management, search, indexing, and AI-powered features. + version: 1.0.0 + contact: + name: VideoDB Support + url: https://videodb.io + license: + name: MIT + url: https://opensource.org/licenses/MIT + +servers: + - url: https://api.videodb.io + description: Production server + - url: https://staging-api.videodb.io + description: Staging server + +security: + - ApiKeyAuth: [] + +components: + securitySchemes: + ApiKeyAuth: + type: apiKey + in: header + name: x-access-token + description: API key for authentication (sk-xxx format) + + schemas: + Error: + type: object + properties: + success: + type: boolean + example: false + message: + type: string + example: "Error message" + error_code: + type: string + example: "ERROR_CODE" + + SuccessResponse: + type: object + properties: + success: + type: boolean + example: true + message: + type: string + example: "Operation successful" + + AsyncResponse: + type: object + properties: + success: + type: boolean + example: true + status: + type: string + enum: [processing, done, failed] + example: "processing" + data: + type: object + properties: + id: + type: string + example: "job-123" + output_url: + type: string + example: "https://api.videodb.io/async-response/job-123" + + User: + type: object + properties: + user_id: + type: string + example: "u-12345" + user_name: + type: string + example: "John Doe" + user_email: + type: string + example: "john@example.com" + collections: + type: array + items: + type: string + example: ["default", "c-67890"] + default_collection: + type: string + example: "default" + + Collection: + type: object + properties: + id: + type: string + example: "default" + name: + type: string + example: "My Collection" + description: + type: string + example: "Collection description" + is_public: + type: boolean + example: false + owner: + type: string + example: "u-12345" + created_at: + type: string + format: date-time + + Video: + type: object + properties: + id: + type: string + example: "m-12345" + name: + type: string + example: "video.mp4" + description: + type: string + example: "Video description" + collection_id: + type: string + example: "default" + length: + type: number + example: 120.5 + size: + type: number + example: 1048576 + stream_url: + type: string + example: "https://stream.videodb.io/v/12345" + player_url: + type: string + example: "https://console.videodb.io/player/12345" + thumbnail_url: + type: string + example: "https://assets.videodb.io/thumb/12345.jpg" + created_at: + type: string + format: date-time + + Audio: + type: object + properties: + id: + type: string + example: "a-12345" + name: + type: string + example: "audio.mp3" + collection_id: + type: string + example: "default" + length: + type: number + example: 60.0 + size: + type: number + example: 524288 + created_at: + type: string + format: date-time + + Image: + type: object + properties: + id: + type: string + example: "img-12345" + name: + type: string + example: "image.jpg" + collection_id: + type: string + example: "default" + width: + type: number + example: 1920 + height: + type: number + example: 1080 + size: + type: number + example: 262144 + url: + type: string + example: "https://assets.videodb.io/img/12345.jpg" + created_at: + type: string + format: date-time + + SearchResult: + type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + query: + type: string + example: "search query" + results: + type: array + items: + type: object + properties: + video_id: + type: string + example: "m-12345" + start: + type: number + example: 10.5 + end: + type: number + example: 20.3 + text: + type: string + example: "matched content" + score: + type: number + example: 0.95 + + Timeline: + type: object + properties: + video_id: + type: string + example: "m-12345" + clips: + type: array + items: + type: object + properties: + start: + type: number + example: 0 + end: + type: number + example: 30 + volume: + type: number + example: 1.0 + + BillingUsage: + type: object + properties: + credit_balance: + type: number + example: 100.50 + usage_this_month: + type: number + example: 25.75 + breakdown: + type: object + additionalProperties: + type: number + +paths: + /: + get: + summary: Get service information + description: Returns basic service information + responses: + '200': + description: Service information + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + service: + type: string + example: "VideoDB Server" + + /user: + get: + summary: Get user information + security: + - ApiKeyAuth: [] + responses: + '200': + description: User information + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + $ref: '#/components/schemas/User' + '401': + description: Unauthorized + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /user/api_key: + get: + summary: Get user API keys + security: + - ApiKeyAuth: [] + responses: + '200': + description: List of API keys + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: array + items: + type: object + properties: + key: + type: string + example: "sk-xxx" + created_at: + type: string + format: date-time + + post: + summary: Create new API key + security: + - ApiKeyAuth: [] + responses: + '200': + description: API key created + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + api_key: + type: string + example: "sk-xxx" + + /user/api_key/{api_key}: + delete: + summary: Delete API key + security: + - ApiKeyAuth: [] + parameters: + - name: api_key + in: path + required: true + schema: + type: string + example: "sk-xxx" + responses: + '200': + description: API key deleted + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + + /collection: + get: + summary: Get user collections + security: + - ApiKeyAuth: [] + responses: + '200': + description: List of collections + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + collections: + type: array + items: + $ref: '#/components/schemas/Collection' + default_collection: + type: string + example: "default" + + post: + summary: Create new collection + security: + - ApiKeyAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + example: "My New Collection" + description: + type: string + example: "Collection for my videos" + is_public: + type: boolean + example: false + responses: + '200': + description: Collection created + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + $ref: '#/components/schemas/Collection' + + /collection/{collection_id}: + get: + summary: Get collection details + security: + - ApiKeyAuth: [] + parameters: + - name: collection_id + in: path + required: true + schema: + type: string + example: "default" + responses: + '200': + description: Collection details + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + $ref: '#/components/schemas/Collection' + + patch: + summary: Update collection + security: + - ApiKeyAuth: [] + parameters: + - name: collection_id + in: path + required: true + schema: + type: string + example: "default" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + example: "Updated Collection Name" + description: + type: string + example: "Updated description" + is_public: + type: boolean + example: true + responses: + '200': + description: Collection updated + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + $ref: '#/components/schemas/Collection' + + delete: + summary: Delete collection + security: + - ApiKeyAuth: [] + parameters: + - name: collection_id + in: path + required: true + schema: + type: string + example: "default" + responses: + '200': + description: Collection deleted + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + + /collection/{collection_id}/upload: + post: + summary: Upload media to collection + security: + - ApiKeyAuth: [] + parameters: + - name: collection_id + in: path + required: true + schema: + type: string + example: "default" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - url + properties: + url: + type: string + example: "https://example.com/video.mp4" + name: + type: string + example: "My Video" + media_type: + type: string + enum: [video, audio, image] + example: "video" + callback_url: + type: string + example: "https://webhook.example.com/callback" + responses: + '200': + description: Upload initiated + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/AsyncResponse' + - type: object + properties: + success: + type: boolean + example: true + data: + $ref: '#/components/schemas/Video' + + /collection/{collection_id}/search/: + post: + summary: Search within collection + security: + - ApiKeyAuth: [] + parameters: + - name: collection_id + in: path + required: true + schema: + type: string + example: "default" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - query + properties: + query: + type: string + example: "search query" + index_type: + type: string + enum: [spoken_word, scene] + example: "spoken_word" + search_type: + type: string + enum: [semantic, custom] + example: "semantic" + score_threshold: + type: number + example: 0.2 + result_threshold: + type: integer + example: 10 + stitch: + type: boolean + example: true + rerank: + type: boolean + example: false + filter: + type: array + items: + type: object + responses: + '200': + description: Search results + content: + application/json: + schema: + $ref: '#/components/schemas/SearchResult' + + /video/: + get: + summary: List videos + security: + - ApiKeyAuth: [] + parameters: + - name: collection_id + in: query + schema: + type: string + example: "default" + - name: page_index + in: query + schema: + type: integer + example: 0 + - name: count + in: query + schema: + type: integer + maximum: 5000 + example: 50 + responses: + '200': + description: List of videos + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + videos: + type: array + items: + $ref: '#/components/schemas/Video' + + /video/{video_id}: + get: + summary: Get video details + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + - name: collection_id + in: query + schema: + type: string + example: "default" + responses: + '200': + description: Video details + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + $ref: '#/components/schemas/Video' + + delete: + summary: Delete video + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + responses: + '200': + description: Video deleted + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + + /video/{video_id}/storage/: + delete: + summary: Delete video storage + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + responses: + '200': + description: Video storage deleted + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + + /video/{video_id}/stream/: + post: + summary: Create video stream + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + format: + type: string + enum: [mp4, webm, hls] + example: "mp4" + quality: + type: string + enum: [low, medium, high] + example: "high" + responses: + '200': + description: Stream created + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + stream_url: + type: string + example: "https://stream.videodb.io/v/12345" + + /video/{video_id}/thumbnail/: + get: + summary: Get video thumbnail + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + - name: timestamp + in: query + schema: + type: number + example: 10.5 + responses: + '200': + description: Thumbnail URL + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + thumbnail_url: + type: string + example: "https://assets.videodb.io/thumb/12345.jpg" + + post: + summary: Generate custom thumbnail + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + timestamp: + type: number + example: 10.5 + width: + type: integer + example: 320 + height: + type: integer + example: 180 + responses: + '200': + description: Thumbnail generated + content: + application/json: + schema: + $ref: '#/components/schemas/AsyncResponse' + + /video/{video_id}/thumbnails/: + get: + summary: Get all video thumbnails + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + responses: + '200': + description: List of thumbnails + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: array + items: + type: object + properties: + timestamp: + type: number + example: 10.5 + url: + type: string + example: "https://assets.videodb.io/thumb/12345_10.jpg" + + /video/{video_id}/transcription/: + get: + summary: Get video transcription + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + - name: engine + in: query + schema: + type: string + default: "AAI" + example: "AAI" + - name: start + in: query + schema: + type: number + default: 0 + example: 10.5 + - name: end + in: query + schema: + type: number + default: -1 + example: 60.0 + - name: segmenter + in: query + schema: + type: string + default: "word" + example: "word" + - name: length + in: query + schema: + type: integer + default: 1 + example: 1 + responses: + '200': + description: Transcription data + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + status: + type: string + enum: [completed, processing, failed] + example: "completed" + data: + type: object + properties: + transcript: + type: array + items: + type: object + properties: + text: + type: string + example: "Hello world" + start: + type: number + example: 1.5 + end: + type: number + example: 3.2 + + post: + summary: Generate video transcription + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + engine: + type: string + default: "AAI" + example: "AAI" + force: + type: boolean + example: false + language_code: + type: string + example: "en-US" + callback_url: + type: string + example: "https://webhook.example.com/callback" + callback_data: + type: object + responses: + '200': + description: Transcription job started + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/AsyncResponse' + - type: object + properties: + success: + type: boolean + example: true + message: + type: string + example: "transcription already exists" + + /video/{video_id}/index/: + get: + summary: Get video index status + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + - name: index_type + in: query + required: true + schema: + type: string + enum: [spoken_word, scene] + example: "spoken_word" + - name: engine + in: query + schema: + type: string + default: "AAI" + example: "AAI" + responses: + '200': + description: Index status + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + status: + type: string + enum: [done, processing, failed] + example: "done" + message: + type: string + example: "Index is available" + + post: + summary: Create video index + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + index_type: + type: string + enum: [spoken_word, scene] + default: "spoken_word" + example: "spoken_word" + engine: + type: string + default: "AAI" + example: "AAI" + force: + type: boolean + example: false + language_code: + type: string + example: "en-US" + segmentation_type: + type: string + default: "sentence" + example: "sentence" + callback_url: + type: string + example: "https://webhook.example.com/callback" + responses: + '200': + description: Index job started + content: + application/json: + schema: + $ref: '#/components/schemas/AsyncResponse' + + /video/{video_id}/search/: + post: + summary: Search within video + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - query + properties: + query: + type: string + example: "search query" + index_type: + type: string + enum: [spoken_word, scene] + example: "spoken_word" + search_type: + type: string + enum: [semantic, keyword] + example: "semantic" + score_threshold: + type: number + example: 0.2 + result_threshold: + type: integer + example: 10 + stitch: + type: boolean + example: true + scene_index_id: + type: string + example: "idx-12345" + filter: + type: array + items: + type: object + responses: + '200': + description: Search results + content: + application/json: + schema: + $ref: '#/components/schemas/SearchResult' + + /video/{video_id}/scenes/: + get: + summary: Get video scenes + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + responses: + '200': + description: List of scenes + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: array + items: + type: object + properties: + scene_id: + type: string + example: "scene-123" + start_time: + type: number + example: 10.5 + end_time: + type: number + example: 25.3 + description: + type: string + example: "Scene description" + thumbnail_url: + type: string + example: "https://assets.videodb.io/scene/123.jpg" + + post: + summary: Create video scenes + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + scene_type: + type: string + enum: [shot, time_based] + example: "shot" + callback_url: + type: string + example: "https://webhook.example.com/callback" + responses: + '200': + description: Scene creation started + content: + application/json: + schema: + $ref: '#/components/schemas/AsyncResponse' + + /video/{video_id}/scene/{scene_id}/describe/: + post: + summary: Describe video scene + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + - name: scene_id + in: path + required: true + schema: + type: string + example: "scene-123" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + prompt: + type: string + example: "Describe what happens in this scene" + model_name: + type: string + example: "gpt-4" + responses: + '200': + description: Scene description generated + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + description: + type: string + example: "Scene description text" + + /video/{video_id}/frame/{frame_id}/describe/: + post: + summary: Describe video frame + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + - name: frame_id + in: path + required: true + schema: + type: string + example: "frame-123" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + prompt: + type: string + example: "Describe this frame" + model_name: + type: string + example: "gpt-4-vision" + responses: + '200': + description: Frame description generated + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + description: + type: string + example: "Frame description text" + + /video/{video_id}/clip: + post: + summary: Generate video clip + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - prompt + properties: + prompt: + type: string + example: "Create a clip about the introduction" + content_type: + type: string + default: "spoken" + example: "spoken" + model_name: + type: string + default: "basic" + example: "basic" + scene_index_id: + type: string + example: "idx-12345" + callback_url: + type: string + example: "https://webhook.example.com/callback" + responses: + '200': + description: Clip generation started + content: + application/json: + schema: + $ref: '#/components/schemas/AsyncResponse' + + /video/{video_id}/workflow/: + post: + summary: Execute video workflow + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - workflow_type + properties: + workflow_type: + type: string + enum: [transcribe, index, analyze] + example: "transcribe" + config: + type: object + properties: + language: + type: string + example: "en" + model: + type: string + example: "gpt-4" + responses: + '200': + description: Workflow started + content: + application/json: + schema: + $ref: '#/components/schemas/AsyncResponse' + + /audio/: + get: + summary: List audios + security: + - ApiKeyAuth: [] + parameters: + - name: collection_id + in: query + schema: + type: string + example: "default" + responses: + '200': + description: List of audios + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + audios: + type: array + items: + $ref: '#/components/schemas/Audio' + + /audio/{audio_id}: + get: + summary: Get audio details + security: + - ApiKeyAuth: [] + parameters: + - name: audio_id + in: path + required: true + schema: + type: string + pattern: "^a-" + example: "a-12345" + - name: collection_id + in: query + schema: + type: string + example: "default" + responses: + '200': + description: Audio details + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + $ref: '#/components/schemas/Audio' + + delete: + summary: Delete audio + security: + - ApiKeyAuth: [] + parameters: + - name: audio_id + in: path + required: true + schema: + type: string + pattern: "^a-" + example: "a-12345" + responses: + '200': + description: Audio deleted + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + + /audio/{audio_id}/generate_url: + post: + summary: Generate audio stream URL + security: + - ApiKeyAuth: [] + parameters: + - name: audio_id + in: path + required: true + schema: + type: string + pattern: "^a-" + example: "a-12345" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + format: + type: string + enum: [mp3, wav, flac] + example: "mp3" + quality: + type: string + enum: [low, medium, high] + example: "high" + responses: + '200': + description: Stream URL generated + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + stream_url: + type: string + example: "https://stream.videodb.io/a/12345" + + /image/: + get: + summary: List images + security: + - ApiKeyAuth: [] + parameters: + - name: collection_id + in: query + schema: + type: string + example: "default" + responses: + '200': + description: List of images + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + images: + type: array + items: + $ref: '#/components/schemas/Image' + + /image/{image_id}: + get: + summary: Get image details + security: + - ApiKeyAuth: [] + parameters: + - name: image_id + in: path + required: true + schema: + type: string + pattern: "^img-" + example: "img-12345" + - name: collection_id + in: query + schema: + type: string + example: "default" + responses: + '200': + description: Image details + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + $ref: '#/components/schemas/Image' + + delete: + summary: Delete image + security: + - ApiKeyAuth: [] + parameters: + - name: image_id + in: path + required: true + schema: + type: string + pattern: "^img-" + example: "img-12345" + responses: + '200': + description: Image deleted + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + + /image/{image_id}/generate_url: + post: + summary: Generate image URL + security: + - ApiKeyAuth: [] + parameters: + - name: image_id + in: path + required: true + schema: + type: string + pattern: "^img-" + example: "img-12345" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + format: + type: string + enum: [jpg, png, webp] + example: "jpg" + quality: + type: integer + minimum: 1 + maximum: 100 + example: 90 + width: + type: integer + example: 1024 + height: + type: integer + example: 768 + responses: + '200': + description: Image URL generated + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + image_url: + type: string + example: "https://assets.videodb.io/img/12345.jpg" + + /collection/{collection_id}/generate/image/: + post: + summary: Generate image using AI + security: + - ApiKeyAuth: [] + parameters: + - name: collection_id + in: path + required: true + schema: + type: string + example: "default" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - prompt + properties: + prompt: + type: string + example: "A beautiful sunset over mountains" + aspect_ratio: + type: string + example: "16:9" + callback_url: + type: string + example: "https://webhook.example.com/callback" + responses: + '200': + description: Image generation started + content: + application/json: + schema: + $ref: '#/components/schemas/AsyncResponse' + + /collection/{collection_id}/generate/video/: + post: + summary: Generate video using AI + security: + - ApiKeyAuth: [] + parameters: + - name: collection_id + in: path + required: true + schema: + type: string + example: "default" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - prompt + properties: + prompt: + type: string + example: "A cat playing with a ball" + duration: + type: number + example: 5 + callback_url: + type: string + example: "https://webhook.example.com/callback" + responses: + '200': + description: Video generation started + content: + application/json: + schema: + $ref: '#/components/schemas/AsyncResponse' + + /collection/{collection_id}/generate/audio/: + post: + summary: Generate audio using AI + security: + - ApiKeyAuth: [] + parameters: + - name: collection_id + in: path + required: true + schema: + type: string + example: "default" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - prompt + - audio_type + properties: + prompt: + type: string + example: "Generate upbeat background music" + audio_type: + type: string + enum: [speech, sound_effect, music] + example: "music" + callback_url: + type: string + example: "https://webhook.example.com/callback" + responses: + '200': + description: Audio generation started + content: + application/json: + schema: + $ref: '#/components/schemas/AsyncResponse' + + /collection/{collection_id}/generate/text/: + post: + summary: Generate text using AI + security: + - ApiKeyAuth: [] + parameters: + - name: collection_id + in: path + required: true + schema: + type: string + example: "default" + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - prompt + properties: + prompt: + type: string + example: "Summarize the content of this video" + video_id: + type: string + example: "m-12345" + model_name: + type: string + example: "gpt-4" + max_tokens: + type: integer + example: 500 + temperature: + type: number + example: 0.7 + callback_url: + type: string + example: "https://webhook.example.com/callback" + responses: + '200': + description: Text generation started or completed + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/AsyncResponse' + - type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + output: + type: string + example: "Generated text content" + + /timeline: + post: + summary: Compile timeline + security: + - ApiKeyAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request_type + - timeline + properties: + request_type: + type: string + enum: [compile] + example: "compile" + timeline: + type: array + items: + $ref: '#/components/schemas/Timeline' + responses: + '200': + description: Timeline compilation result + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + stream_url: + type: string + example: "https://stream.videodb.io/compiled/12345" + + /billing/usage: + get: + summary: Get billing usage information + security: + - ApiKeyAuth: [] + responses: + '200': + description: Billing usage data + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + $ref: '#/components/schemas/BillingUsage' + + /billing/checkout: + post: + summary: Create billing checkout session + security: + - ApiKeyAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + mode: + type: string + enum: [payment, subscription] + example: "payment" + plan_id: + type: string + example: "plan-basic" + amount: + type: number + example: 100 + responses: + '200': + description: Checkout URL + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + url: + type: string + example: "https://checkout.stripe.com/pay/xxx" + + /billing/checkouts: + get: + summary: Get billing checkout history + security: + - ApiKeyAuth: [] + parameters: + - name: limit + in: query + schema: + type: integer + example: 10 + - name: offset + in: query + schema: + type: integer + example: 0 + responses: + '200': + description: Checkout history + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: array + items: + type: object + properties: + id: + type: string + example: "cs_test_xxx" + amount: + type: number + example: 100 + currency: + type: string + example: "usd" + status: + type: string + example: "completed" + created_at: + type: string + format: date-time + + /billing/invoices: + get: + summary: Get billing invoices + security: + - ApiKeyAuth: [] + parameters: + - name: limit + in: query + schema: + type: integer + example: 10 + - name: offset + in: query + schema: + type: integer + example: 0 + responses: + '200': + description: Invoice list + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: array + items: + type: object + properties: + id: + type: string + example: "in_xxx" + amount: + type: number + example: 100 + currency: + type: string + example: "usd" + status: + type: string + example: "paid" + pdf_url: + type: string + example: "https://invoice.stripe.com/pdf/xxx" + created_at: + type: string + format: date-time + + /billing/topup: + post: + summary: Create topup payment + security: + - ApiKeyAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - amount + properties: + amount: + type: number + example: 50 + currency: + type: string + example: "usd" + responses: + '200': + description: Topup checkout URL + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + url: + type: string + example: "https://checkout.stripe.com/pay/xxx" + + /billing/auto_recharge: + get: + summary: Get auto recharge settings + security: + - ApiKeyAuth: [] + responses: + '200': + description: Auto recharge settings + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + enabled: + type: boolean + example: true + threshold: + type: number + example: 10 + amount: + type: number + example: 50 + + post: + summary: Update auto recharge settings + security: + - ApiKeyAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + enabled: + type: boolean + example: true + threshold: + type: number + example: 10 + amount: + type: number + example: 50 + responses: + '200': + description: Auto recharge updated + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + message: + type: string + example: "Auto recharge settings updated" + + /async-response/{response_id}: + get: + summary: Get async operation result + parameters: + - name: response_id + in: path + required: true + schema: + type: string + example: "job-12345" + responses: + '200': + description: Operation result + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + status: + type: string + enum: [processing, done, failed] + example: "done" + data: + type: object + description: "Result data varies by operation type" + '404': + description: Response not found + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + + /download: + get: + summary: List download entries + security: + - ApiKeyAuth: [] + parameters: + - name: page_index + in: query + schema: + type: integer + example: 0 + - name: count + in: query + schema: + type: integer + maximum: 5000 + example: 50 + responses: + '200': + description: List of downloads + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + downloads: + type: array + items: + type: object + properties: + id: + type: string + example: "download-12345" + name: + type: string + example: "video_download.mp4" + status: + type: string + enum: [processing, done, error] + example: "done" + created_at: + type: string + format: date-time + download_url: + type: string + example: "https://example.com/download/video.mp4" + + post: + summary: Create download request + security: + - ApiKeyAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - stream_link + properties: + stream_link: + type: string + example: "https://stream.videodb.io/v/12345" + name: + type: string + example: "my_download.mp4" + responses: + '200': + description: Download initiated + content: + application/json: + schema: + $ref: '#/components/schemas/AsyncResponse' + + delete: + summary: Delete download entry + security: + - ApiKeyAuth: [] + parameters: + - name: download_id + in: query + required: true + schema: + type: string + example: "download-12345" + responses: + '200': + description: Download deleted + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + + /download/{download_id}: + get: + summary: Get download status/details + security: + - ApiKeyAuth: [] + parameters: + - name: download_id + in: path + required: true + schema: + type: string + example: "download-12345" + responses: + '200': + description: Download status + content: + application/json: + schema: + oneOf: + - $ref: '#/components/schemas/AsyncResponse' + - type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + id: + type: string + example: "download-12345" + name: + type: string + example: "video_download.mp4" + status: + type: string + enum: [processing, done, error] + example: "done" + download_url: + type: string + example: "https://example.com/download/video.mp4" + created_at: + type: string + format: date-time + + post: + summary: Retry download + security: + - ApiKeyAuth: [] + parameters: + - name: download_id + in: path + required: true + schema: + type: string + example: "download-12345" + responses: + '200': + description: Download retry initiated + content: + application/json: + schema: + $ref: '#/components/schemas/AsyncResponse' + + /chat/completions: + post: + summary: OpenAI-compatible chat completions proxy + description: Proxy endpoint for OpenAI chat completions API with VideoDB billing + security: + - ApiKeyAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - model + - messages + properties: + model: + type: string + enum: [gpt-4o-2024-11-20] + example: "gpt-4o-2024-11-20" + messages: + type: array + items: + type: object + properties: + role: + type: string + enum: [system, user, assistant] + example: "user" + content: + type: string + example: "Hello, how are you?" + max_tokens: + type: integer + example: 100 + temperature: + type: number + example: 0.7 + stream: + type: boolean + example: false + responses: + '200': + description: Chat completion response + content: + application/json: + schema: + type: object + properties: + id: + type: string + example: "chatcmpl-123" + object: + type: string + example: "chat.completion" + created: + type: integer + example: 1677652288 + model: + type: string + example: "gpt-4o-2024-11-20" + choices: + type: array + items: + type: object + properties: + index: + type: integer + example: 0 + message: + type: object + properties: + role: + type: string + example: "assistant" + content: + type: string + example: "Hello! I'm doing well, thank you for asking." + finish_reason: + type: string + example: "stop" + usage: + type: object + properties: + prompt_tokens: + type: integer + example: 10 + completion_tokens: + type: integer + example: 15 + total_tokens: + type: integer + example: 25 + + /timeline_v2: + post: + summary: Compile timeline (v2) + security: + - ApiKeyAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - request_type + - timeline + properties: + request_type: + type: string + enum: [compile] + example: "compile" + timeline: + type: array + items: + $ref: '#/components/schemas/Timeline' + output_format: + type: string + enum: [mp4, webm, hls] + example: "mp4" + quality: + type: string + enum: [low, medium, high] + example: "high" + responses: + '200': + description: Timeline compilation result + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + stream_url: + type: string + example: "https://stream.videodb.io/compiled/12345" + duration: + type: number + example: 120.5 + format: + type: string + example: "mp4" + + /timeline_v2/download: + post: + summary: Download compiled timeline + security: + - ApiKeyAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - timeline_id + properties: + timeline_id: + type: string + example: "timeline-12345" + format: + type: string + enum: [mp4, webm, avi] + example: "mp4" + quality: + type: string + enum: [low, medium, high] + example: "high" + responses: + '200': + description: Download initiated + content: + application/json: + schema: + $ref: '#/components/schemas/AsyncResponse' + + /compile/: + post: + summary: Compile media content + security: + - ApiKeyAuth: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - inputs + properties: + inputs: + type: array + items: + type: object + properties: + media_id: + type: string + example: "m-12345" + start_time: + type: number + example: 10.0 + end_time: + type: number + example: 30.0 + output_format: + type: string + enum: [mp4, webm, hls] + example: "mp4" + callback_url: + type: string + example: "https://webhook.example.com/callback" + responses: + '200': + description: Compilation started + content: + application/json: + schema: + $ref: '#/components/schemas/AsyncResponse' + + /video/{video_id}/index/scene/: + get: + summary: Get video scene index status + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + responses: + '200': + description: Scene index status + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + status: + type: string + enum: [done, processing, failed] + example: "done" + data: + type: object + properties: + scene_count: + type: integer + example: 25 + total_duration: + type: number + example: 120.5 + last_updated: + type: string + format: date-time + + post: + summary: Create video scene index + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + scene_type: + type: string + enum: [shot, time_based] + example: "shot" + segmentation_threshold: + type: number + example: 0.8 + callback_url: + type: string + example: "https://webhook.example.com/callback" + responses: + '200': + description: Scene index creation started + content: + application/json: + schema: + $ref: '#/components/schemas/AsyncResponse' + + /video/{video_id}/index/scene/{scene_index_id}: + get: + summary: Get scene index details + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + - name: scene_index_id + in: path + required: true + schema: + type: string + example: "scene-idx-12345" + responses: + '200': + description: Scene index details + content: + application/json: + schema: + type: object + properties: + success: + type: boolean + example: true + data: + type: object + properties: + id: + type: string + example: "scene-idx-12345" + video_id: + type: string + example: "m-12345" + scene_type: + type: string + example: "shot" + status: + type: string + enum: [done, processing, failed] + example: "done" + scenes: + type: array + items: + type: object + properties: + start_time: + type: number + example: 10.5 + end_time: + type: number + example: 25.3 + confidence: + type: number + example: 0.85 + + delete: + summary: Delete scene index + security: + - ApiKeyAuth: [] + parameters: + - name: video_id + in: path + required: true + schema: + type: string + pattern: "^m-" + example: "m-12345" + - name: scene_index_id + in: path + required: true + schema: + type: string + example: "scene-idx-12345" + responses: + '200': + description: Scene index deleted + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + +tags: + - name: Authentication + description: User authentication and API key management + - name: Collections + description: Collection management operations + - name: Videos + description: Video upload, processing, and management + - name: Audio + description: Audio management operations + - name: Images + description: Image management operations + - name: Search + description: Content search and indexing + - name: AI Generation + description: AI-powered content generation + - name: Billing + description: Billing and usage management + - name: RTStream + description: Real-time streaming operations + - name: Utilities + description: Utility endpoints + - name: Meeting + description: Meeting recording and management \ No newline at end of file