Quick Example
Copy
Ask AI
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
Copy
Ask AI
<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
Copy
Ask AI
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
Copy
Ask AI
<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
Copy
Ask AI
# 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
Copy
Ask AI
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)
Share Links
VideoDB Console Player
Generate shareable links using the console player:Copy
Ask AI
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
Copy
Ask AI
# 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
Copy
Ask AI
<!-- 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
Copy
Ask AI
<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
Copy
Ask AI
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:Copy
Ask AI
https://stream.videodb.io/v3/published/manifests/{manifest-id}.m3u8
| Endpoint | Purpose |
|---|---|
stream.videodb.io | HLS streaming |
cdn.videodb.io | Direct file downloads |
URL Caching Strategy
Copy
Ask AI
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
Copy
Ask AI
<video
id="player"
autoplay
muted
playsinline
poster="{thumbnail_url}"
>
<source src="{stream_url}" type="application/x-mpegURL">
</video>
Loop Playback
Copy
Ask AI
<video id="player" loop controls>
<source src="{stream_url}" type="application/x-mpegURL">
</video>
Custom Controls
Copy
Ask AI
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
Copy
Ask AI
.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%;
}
Copy
Ask AI
<div class="video-container">
<video controls>
<source src="{stream_url}" type="application/x-mpegURL">
</video>
</div>
Multiple Aspect Ratios
Copy
Ask AI
.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
| Practice | Reason |
|---|---|
| Cache stream URLs | Avoid regenerating on every request |
| Use thumbnails | Improve perceived load time |
| Preload metadata | preload="metadata" for faster starts |
| Lazy load off-screen | Defer loading until visible |
| Handle errors | Show fallback on stream failure |
Error Handling
Copy
Ask AI
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>
);
}