Skip to main content
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>

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