Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.videodb.io/llms.txt

Use this file to discover all available pages before exploring further.

Capture sessions can optionally persist media for later search and playback. Control storage per-channel and access exported assets.
Desktop capture currently supports macOS and Windows.

Quick Example

# After capture_session.exported webhook
cap = conn.get_capture_session("cap-xxx")

# Get the muxed video
video_id = cap.exported_video_id
video = coll.get_video(video_id)

# Search the captured content
video.index_spoken_words()
results = video.search("budget discussion")
for shot in results.shots:
    print(f"{shot.start}s: {shot.text}")
    shot.play()

Storage Control

Per-Channel Storage

Enable/disable storage for each channel:
# In desktop client
await client.start_session(
    capture_session_id=cap_id,
    channels=[
        {"name": "mic:default", "store": True},      # Will persist
        {"name": "display:1", "store": True},        # Will persist
        {"name": "system_audio:default", "store": False}  # Ephemeral
    ]
)
SettingBehavior
store: trueMedia persisted, available for search and playback
store: falseEphemeral - real-time processing only, no persistence
Export only runs if at least one channel has store: true.

What Gets Exported

Muxed Video

The default “playable recording” containing:
  • Video: Primary display (set via primary_video_channel_id)
  • Audio: All recorded audio channels mixed together
Use for:
  • Playback and sharing
  • Downstream indexing and search
  • Simple “trim and publish” workflows

Raw Channel Assets

Individual assets for each stored channel:
ChannelAsset Type
display:1Raw video
mic:defaultRaw audio
system_audio:defaultRaw audio
Use for:
  • Separate audio stems (mic vs system audio)
  • Multi-track editing
  • Custom muxing strategies
  • Picture-in-picture composites

Accessing Exports

Via Webhook

The capture_session.exported webhook includes the muxed video ID:
{
  "event": "capture_session.exported",
  "capture_session_id": "cap-xxx",
  "status": "exported",
  "data": {
    "exported_video_id": "m-xxx"
  }
}

Via RTStream

Each RTStream has an exported_asset_id after export:
def on_exported(payload: dict):
    cap = conn.get_capture_session(payload["capture_session_id"])

    # Muxed video
    video_id = payload["data"]["exported_video_id"]

    # Raw channel assets
    mics = cap.get_rtstream("mic")
    if mics:
        mic_asset_id = mics[0].exported_asset_id

    displays = cap.get_rtstream("display")
    if displays:
        display_asset_id = displays[0].exported_asset_id

Using cap.export()

You can trigger or check an export programmatically with cap.export():
Python
cap = conn.get_capture_session("cap-xxx")

result = cap.export(
    video_channel_id=None,      # Optional — defaults to primary video channel
    ws_connection_id=None,       # Optional — for push notification on completion
)
ParameterTypeDescription
video_channel_idstr or NoneThe video channel to export. Defaults to the primary video channel when omitted.
ws_connection_idstr or NoneA WebSocket connection ID. When provided, VideoDB sends a push notification over that connection when the export finishes.
The returned dict contains:
FieldDescription
session_idThe capture session ID
video_channel_idThe video channel being exported
export_statusCurrent status (exporting, exported, failed)
video_idAvailable once export completes
stream_urlPlayback stream URL (available once exported)
player_urlEmbeddable player URL (available once exported)

Multi-Screen Export

When capturing multiple displays, each display can be exported individually by passing its video_channel_id. Use cap.displays to discover available video channels:
Python
cap = conn.get_capture_session("cap-xxx")

for d in cap.displays:
    print(f"{d.channel_id}  primary={d.is_primary}")

# Export a specific (non-primary) display
result = cap.export(video_channel_id="display:2")
print(result)
# {
#   "session_id": "cap-xxx",
#   "video_channel_id": "display:2",
#   "export_status": "exporting"
# }

Checking Export Status

You can track export completion via webhook or by polling:
Python
# Option 1: Webhook — your callback_url receives:
# {
#   "event": "capture_session.exported",
#   "capture_session_id": "cap-xxx",
#   "data": { "exported_video_id": "m-xxx" }
# }

# Option 2: Push notification via WebSocket
result = cap.export(ws_connection_id="ws-conn-xxx")

# Option 3: Poll export status
result = cap.export(video_channel_id="display:1")
while result["export_status"] == "exporting":
    time.sleep(5)
    result = cap.export(video_channel_id="display:1")

print(result["video_id"])       # "m-xxx"
print(result["stream_url"])     # Playback URL
print(result["player_url"])     # Embeddable player URL

Editing with Raw Assets

Use raw assets when you need control over individual tracks.

Display Video + Mic Audio Only

from videodb.editor import Timeline, Track, Clip, VideoAsset, AudioAsset

cap = conn.get_capture_session("cap-xxx")
display_asset_id = cap.get_rtstream("display")[0].exported_asset_id
mic_asset_id = cap.get_rtstream("mic")[0].exported_asset_id

timeline = Timeline(conn)
timeline.resolution = "1280x720"

# Video track
video_track = Track()
video_track.add_clip(0, Clip(asset=VideoAsset(id=display_asset_id), duration=60))
timeline.add_track(video_track)

# Audio track (mic only)
audio_track = Track()
audio_track.add_clip(0, Clip(asset=AudioAsset(id=mic_asset_id, volume=1.0), duration=60))
timeline.add_track(audio_track)

stream_url = timeline.generate_stream()

After export, captured content is searchable:
video = coll.get_video(exported_video_id)

# Index for search
video.index_spoken_words()

# Search
results = video.search("action items from the meeting")
for shot in results.shots:
    print(f"{shot.start}s: {shot.text}")
    shot.play()

Which Asset to Use?

Use CaseAsset
Quick playback, sharingMuxed video (exported_video_id)
Separate mic vs system audioRaw channel assets
Multi-track editingRaw channel assets
Custom audio mixRaw channel assets
Picture-in-pictureRaw channel assets

Next Steps

Privacy Controls

Consent and redaction patterns

Capture Overview

Architecture and quickstart