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.

Deliver video content to end users through embedded players, shareable links, and social media integrations.

Quick Example

import videodb

conn = videodb.connect()
coll = conn.get_collection()
video = coll.get_video("m-xxx")

# Get streaming URL
stream_url = video.generate_stream()

# Get thumbnail
thumbnail_url = video.generate_thumbnail()

# Get download link
download_url = video.download(name="sample video")

Embed Player

Basic HTML Embed

<video
  id="player"
  controls
  width="100%"
  poster="{thumbnail_url}"
>
  <source
    src="{stream_url}"
    type="application/x-mpegURL"
  >
</video>

<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script>
  const video = document.getElementById('player');
  const src = video.querySelector('source').src;

  if (Hls.isSupported()) {
    const hls = new Hls();
    hls.loadSource(src);
    hls.attachMedia(video);
  }
</script>

React Component

import Hls from 'hls.js';
import { useRef, useEffect } from 'react';

function VideoPlayer({ streamUrl, thumbnailUrl, title }) {
  const videoRef = useRef(null);

  useEffect(() => {
    const video = videoRef.current;
    if (!video) return;

    if (Hls.isSupported()) {
      const hls = new Hls();
      hls.loadSource(streamUrl);
      hls.attachMedia(video);

      return () => hls.destroy();
    } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
      // Safari native HLS
      video.src = streamUrl;
    }
  }, [streamUrl]);

  return (
    <video
      ref={videoRef}
      controls
      poster={thumbnailUrl}
      title={title}
      style={{ width: '100%' }}
    />
  );
}

Vue Component

<template>
  <video
    ref="videoPlayer"
    controls
    :poster="thumbnailUrl"
    style="width: 100%"
  />
</template>

<script setup>
import Hls from 'hls.js';
import { ref, onMounted, onUnmounted } from 'vue';

const props = defineProps(['streamUrl', 'thumbnailUrl']);
const videoPlayer = ref(null);
let hls = null;

onMounted(() => {
  if (Hls.isSupported()) {
    hls = new Hls();
    hls.loadSource(props.streamUrl);
    hls.attachMedia(videoPlayer.value);
  }
});

onUnmounted(() => {
  if (hls) hls.destroy();
});
</script>

Embed Code Generation

get_embed_code()

Generate an HTML iframe embed string directly from SDK objects. Available on Video, Shot, SearchResult, Timeline, RTStream, RTStreamShot, RTStreamExportResult, and Editor Timeline.
embed_html = obj.get_embed_code(
    width="100%",             # iframe width
    height=405,               # iframe height in pixels
    title="VideoDB Player",   # iframe title attribute
    allow_fullscreen=True,    # allow fullscreen
    auto_generate=True        # auto-call generate_stream() if player_url missing
)
Returns an HTML <iframe> string. Raises ValueError if player_url is not available and cannot be auto-generated.

Video Embed

video = coll.get_video("m-xxx")

# Auto-generates stream URL if needed
embed_html = video.get_embed_code()
print(embed_html)
# <iframe src="https://console.videodb.io/player?url=..." width="100%" height="405" ...></iframe>

# Custom dimensions
embed_html = video.get_embed_code(width="640px", height=360, title="My Video")

Search Result Embed

results = video.search("product demo")

# Embed the compiled search results
embed_html = results.get_embed_code(height=480)

RTStream Note

RTStream does not support auto_generate. You must call generate_stream(start, end) explicitly before calling get_embed_code():
rt_stream.generate_stream(start=0, end=120)
embed_html = rt_stream.get_embed_code(auto_generate=False)

build_iframe_embed_code() Utility

A standalone helper when you already have a player URL:
from videodb import build_iframe_embed_code

embed_html = build_iframe_embed_code(player_url, width="100%", height=405)

Thumbnail Generation

Get Video Thumbnail

# Default thumbnail (first frame)
thumbnail_url = video.generate_thumbnail()

# Thumbnail at specific time
thumbnail_url = video.generate_thumbnail(time=30.5)

Multiple Thumbnails for Preview

def generate_preview_thumbnails(video, count=5):
    """Generate evenly spaced thumbnails across video"""
    duration = video.duration
    interval = duration / (count + 1)

    thumbnails = []
    for i in range(1, count + 1):
        time = interval * i
        url = video.generate_thumbnail(time=time)
        thumbnails.append({
            "time": time,
            "url": url
        })

    return thumbnails

previews = generate_preview_thumbnails(video, count=5)

VideoDB Console Player

Generate shareable links using the console player:
import urllib.parse

stream_url = video.generate_stream()
encoded_url = urllib.parse.quote(stream_url, safe='')

share_link = f"https://console.videodb.io/player?url={encoded_url}"

Share Specific Clips

# Share a specific segment
clip_url = video.generate_stream([(120, 180)])
share_clip = f"https://console.videodb.io/player?url={urllib.parse.quote(clip_url)}"

Social Media Metadata

Open Graph Tags

<!-- Video metadata for social sharing -->
<meta property="og:type" content="video.other" />
<meta property="og:title" content="{video_title}" />
<meta property="og:description" content="{video_description}" />
<meta property="og:image" content="{thumbnail_url}" />
<meta property="og:video" content="{stream_url}" />
<meta property="og:video:type" content="application/x-mpegURL" />
<meta property="og:video:width" content="1920" />
<meta property="og:video:height" content="1080" />

Twitter Card

<meta name="twitter:card" content="player" />
<meta name="twitter:title" content="{video_title}" />
<meta name="twitter:description" content="{video_description}" />
<meta name="twitter:image" content="{thumbnail_url}" />
<meta name="twitter:player" content="{embed_url}" />
<meta name="twitter:player:width" content="1280" />
<meta name="twitter:player:height" content="720" />

Generate Metadata Object

def generate_social_metadata(video, title, description):
    """Generate metadata for social sharing"""
    stream_url = video.generate_stream()
    thumbnail_url = video.generate_thumbnail()

    return {
        "title": title,
        "description": description,
        "thumbnail": thumbnail_url,
        "video_url": stream_url,
        "og": {
            "type": "video.other",
            "title": title,
            "description": description,
            "image": thumbnail_url,
            "video": stream_url
        },
        "twitter": {
            "card": "player",
            "title": title,
            "description": description,
            "image": thumbnail_url
        }
    }

CDN Delivery

Stream URL Structure

VideoDB serves content through a global CDN:
https://stream.videodb.io/v3/published/manifests/{manifest-id}.m3u8
EndpointPurpose
stream.videodb.ioHLS streaming
cdn.videodb.ioDirect file downloads

URL Caching Strategy

import time
from functools import lru_cache

class VideoURLCache:
    def __init__(self, ttl=23 * 3600):  # 23 hours
        self.cache = {}
        self.ttl = ttl

    def get_stream_url(self, video, timestamps=None):
        key = f"{video.id}:{timestamps}"

        if key in self.cache:
            url, expires = self.cache[key]
            if time.time() < expires:
                return url

        # Generate new URL
        if timestamps:
            url = video.generate_stream(timestamps)
        else:
            url = video.generate_stream()

        self.cache[key] = (url, time.time() + self.ttl)
        return url

# Usage
url_cache = VideoURLCache()
stream_url = url_cache.get_stream_url(video)

Player Features

Autoplay with Mute

<video
  id="player"
  autoplay
  muted
  playsinline
  poster="{thumbnail_url}"
>
  <source src="{stream_url}" type="application/x-mpegURL">
</video>

Loop Playback

<video id="player" loop controls>
  <source src="{stream_url}" type="application/x-mpegURL">
</video>

Custom Controls

function CustomPlayer({ streamUrl }) {
  const videoRef = useRef(null);
  const [playing, setPlaying] = useState(false);
  const [progress, setProgress] = useState(0);

  const togglePlay = () => {
    if (playing) {
      videoRef.current.pause();
    } else {
      videoRef.current.play();
    }
    setPlaying(!playing);
  };

  return (
    <div className="player-container">
      <video
        ref={videoRef}
        onTimeUpdate={(e) => {
          const pct = (e.target.currentTime / e.target.duration) * 100;
          setProgress(pct);
        }}
      />
      <div className="controls">
        <button onClick={togglePlay}>
          {playing ? 'Pause' : 'Play'}
        </button>
        <div className="progress-bar" style={{ width: `${progress}%` }} />
      </div>
    </div>
  );
}

Responsive Embed

Aspect Ratio Container

.video-container {
  position: relative;
  width: 100%;
  padding-bottom: 56.25%; /* 16:9 aspect ratio */
}

.video-container video {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
<div class="video-container">
  <video controls>
    <source src="{stream_url}" type="application/x-mpegURL">
  </video>
</div>

Multiple Aspect Ratios

.video-16-9 { padding-bottom: 56.25%; }
.video-4-3 { padding-bottom: 75%; }
.video-1-1 { padding-bottom: 100%; }
.video-9-16 { padding-bottom: 177.78%; }

Best Practices

PracticeReason
Cache stream URLsAvoid regenerating on every request
Use thumbnailsImprove perceived load time
Preload metadatapreload="metadata" for faster starts
Lazy load off-screenDefer loading until visible
Handle errorsShow fallback on stream failure

Error Handling

function VideoPlayer({ streamUrl, fallbackUrl }) {
  const [error, setError] = useState(false);

  if (error && fallbackUrl) {
    return <img src={fallbackUrl} alt="Video unavailable" />;
  }

  return (
    <video
      controls
      onError={() => setError(true)}
    >
      <source src={streamUrl} type="application/x-mpegURL" />
    </video>
  );
}

Next Steps

Streams and Exports

Generate clips and export video

Timeline Architecture

Compose video programmatically