Quick Example
import videodb
conn = videodb.connect()
coll = conn.get_collection()
video = coll.get_video("m-xxx")
# Stream from search results
results = video.search("product demo")
stream_url = results.compile()
# Stream from timestamps
stream_url = video.generate_stream([(10, 30), (45, 60)])
# Get download URL
download_url = video.download(name="sample video")
import { connect } from 'videodb';
const conn = connect();
const coll = await conn.getCollection();
const video = await coll.getVideo("m-xxx");
// Stream from search results
const results = await video.semanticSearch("product demo", {
topK: 10,
});
const streamUrl = await results.compile();
// Stream from timestamps
const streamUrl2 = await video.generateStream([[10, 30], [45, 60]]);
// Get download URL
const downloadUrl = await video.download("sample video");
Stream Generation
From Search Results
Search returns matching segments. Generate a stream to play them as a single video.# Search for content
results = video.search("key moments")
# Generate playable stream
stream_url = results.compile()
# https://stream.videodb.io/v3/published/manifests/{id}.m3u8
# Play in browser
results.play()
// Search for content
const results = await video.semanticSearch("key moments", {
topK: 10,
});
// Generate playable stream
const streamUrl = await results.compile();
// https://stream.videodb.io/v3/published/manifests/{id}.m3u8
// Play in browser
await results.play();
From Timestamps
Create streams from specific time ranges.# Define time segments (start, end) in seconds
timestamps = [
(0, 15), # Intro
(120, 180), # Main content
(300, 330) # Conclusion
]
stream_url = video.generate_stream(timestamps)
// Define time segments [start, end] in seconds
const timestamps = [
[0, 15], // Intro
[120, 180], // Main content
[300, 330] // Conclusion
];
const streamUrl = await video.generateStream(timestamps);
From Timeline
Export composed timelines as streams.from videodb.editor import Clip, Timeline, Track, VideoAsset
# Build timeline
timeline = Timeline(conn)
track = Track()
track.add_clip(0, Clip(asset=VideoAsset(id=video.id, start=10), duration=20))
track.add_clip(20, Clip(asset=VideoAsset(id=video.id, start=60), duration=30))
timeline.add_track(track)
# Generate stream
stream_url = timeline.generate_stream()
import { Timeline, VideoAsset } from 'videodb';
// Build timeline
const timeline = new Timeline(conn);
timeline.addInline(new VideoAsset(video.id, { start: 10, end: 30 }));
timeline.addInline(new VideoAsset(video.id, { start: 60, end: 90 }));
// Generate stream
const streamUrl = await timeline.generateStream();
Stream URL Format
All generated streams use HLS format:https://stream.videodb.io/v3/published/manifests/{manifest-id}.m3u8
| Property | Value |
|---|---|
| Format | HLS (HTTP Live Streaming) |
| Container | .m3u8 manifest with .ts segments |
| Compatibility | All modern browsers, native apps |
Download and Export
Get Video URL
# Full video download URL
download_url = video.download(name="sample video")
# https://cdn.videodb.io/v3/{collection}/{video}.mp4
// Full video download URL
const downloadUrl = await video.download("sample video");
// https://cdn.videodb.io/v3/{collection}/{video}.mp4
Get Audio URL
# Audio-only download
audio_url = audio.generate_url()
// Audio-only download
const audioUrl = await audio.generateUrl();
Get Image URL
# Generated image URL
image_url = image.generate_url()
// Generated image URL
const imageUrl = await image.generateUrl();
Embedding Streams
HTML5 Video
<video controls>
<source
src="https://stream.videodb.io/v3/published/manifests/{id}.m3u8"
type="application/x-mpegURL"
>
</video>
With HLS.js
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<video id="video" controls></video>
<script>
const video = document.getElementById('video');
const streamUrl = 'https://stream.videodb.io/v3/...';
if (Hls.isSupported()) {
const hls = new Hls();
hls.loadSource(streamUrl);
hls.attachMedia(video);
}
</script>
React Component
import Hls from 'hls.js';
import { useRef, useEffect } from 'react';
function VideoPlayer({ streamUrl }) {
const videoRef = useRef(null);
useEffect(() => {
if (Hls.isSupported()) {
const hls = new Hls();
hls.loadSource(streamUrl);
hls.attachMedia(videoRef.current);
return () => hls.destroy();
}
}, [streamUrl]);
return <video ref={videoRef} controls />;
}
VideoDB Console Player
Use the built-in player:https://console.videodb.io/player?url={encoded_stream_url}
Clip Export Patterns
Export Search Results as Clips
results = video.search("highlight moments")
# Export each match as separate stream
clips = []
for shot in results.get_shots():
clip_url = shot.generate_stream()
clips.append({
"start": shot.start,
"end": shot.end,
"url": clip_url,
"text": shot.text
})
const results = await video.search("highlight moments");
// Export each match as separate stream
const clips = [];
for (const shot of results.shots) {
const clipUrl = await shot.generateStream();
clips.push({
start: shot.start,
end: shot.end,
url: clipUrl,
text: shot.text
});
}
Batch Export
def export_clips(video, timestamps, prefix="clip"):
"""Export multiple clips from a video"""
exports = []
for i, (start, end) in enumerate(timestamps):
stream_url = video.generate_stream([(start, end)])
exports.append({
"name": f"{prefix}_{i+1}",
"start": start,
"end": end,
"duration": end - start,
"url": stream_url
})
return exports
# Export intro, middle, outro
clips = export_clips(video, [
(0, 30),
(120, 180),
(300, 330)
])
async function exportClips(video, timestamps, prefix = "clip") {
const exports = [];
for (let i = 0; i < timestamps.length; i++) {
const [start, end] = timestamps[i];
const streamUrl = await video.generateStream([[start, end]]);
exports.push({
name: `${prefix}_${i + 1}`,
start,
end,
duration: end - start,
url: streamUrl
});
}
return exports;
}
// Export intro, middle, outro
const clips = await exportClips(video, [
[0, 30],
[120, 180],
[300, 330]
]);
Combine Multiple Videos
Merge Clips from Different Videos
from videodb.editor import Clip, Timeline, Track, VideoAsset
video1 = coll.get_video("m-first")
video2 = coll.get_video("m-second")
video3 = coll.get_video("m-third")
# Create combined timeline
timeline = Timeline(conn)
track = Track()
track.add_clip(0, Clip(asset=VideoAsset(id=video1.id, start=0), duration=30))
track.add_clip(30, Clip(asset=VideoAsset(id=video2.id, start=10), duration=30))
track.add_clip(60, Clip(asset=VideoAsset(id=video3.id, start=0), duration=20))
timeline.add_track(track)
# Generate merged stream
merged_url = timeline.generate_stream()
import { Timeline, VideoAsset } from 'videodb';
const video1 = await coll.getVideo("m-first");
const video2 = await coll.getVideo("m-second");
const video3 = await coll.getVideo("m-third");
// Create combined timeline
const timeline = new Timeline(conn);
timeline.addInline(new VideoAsset(video1.id, { start: 0, end: 30 }));
timeline.addInline(new VideoAsset(video2.id, { start: 10, end: 40 }));
timeline.addInline(new VideoAsset(video3.id, { start: 0, end: 20 }));
// Generate merged stream
const mergedUrl = await timeline.generateStream();
Collection Highlights
from videodb.editor import Timeline, VideoAsset
# Search across collection
results = coll.search("best moments")
# Build highlight reel from top results
timeline = Timeline(conn)
for shot in results.get_shots()[:10]: # Top 10
video_asset = VideoAsset(id=shot.video_id, start=shot.start)
clip = Clip(asset=video_asset, duration=shot.end - shot.start)
track = Track()
track.add_clip(0, clip)
timeline.add_track(track)
highlight_url = timeline.generate_stream()
import { EditorTimeline, Track, Clip, EditorVideoAsset } from 'videodb';
// Search across collection
const results = await coll.search("best moments");
// Build highlight reel from top results
const timeline = new EditorTimeline(conn);
for (const shot of results.shots.slice(0, 10)) { // Top 10
const videoAsset = new EditorVideoAsset({ id: shot.videoId, start: shot.start });
const clip = new Clip({ asset: videoAsset, duration: shot.end - shot.start });
const track = new Track();
track.addClip(0, clip);
timeline.addTrack(track);
}
const highlightUrl = await timeline.generateStream();
URL Lifecycle
| Stage | Duration | Notes |
|---|---|---|
| Generation | Instant | Stream URL returned immediately |
| Regeneration | Anytime | Call generate_stream again for new URL |
Reuse Generated URLs
def get_stream(video, timestamps, cache={}):
"""Get or reuse a stream URL"""
cache_key = f"{video.id}:{timestamps}"
# Check cache
if cache_key in cache:
return cache[cache_key]
# Generate URL
url = video.generate_stream(timestamps)
cache[cache_key] = url
return url
const cache = new Map();
async function getStream(video, timestamps) {
const cacheKey = `${video.id}:${JSON.stringify(timestamps)}`;
// Check cache
if (cache.has(cacheKey)) {
return cache.get(cacheKey);
}
// Generate URL
const url = await video.generateStream(timestamps);
cache.set(cacheKey, url);
return url;
}
Reframe and Aspect Ratio Conversion
reframe()
Convert a video to a different aspect ratio. Useful for repurposing landscape content to vertical formats for social media.
# Reframe to vertical (9:16) for social media
vertical_video = video.reframe(target="vertical", mode="smart")
# Custom aspect ratio (square)
square_video = video.reframe(target={"width": 1, "height": 1})
# Reframe a specific time range
clip = video.reframe(start=10.0, end=60.0, target="vertical")
# Async with callback
video.reframe(
start=10.0,
end=60.0,
target="vertical",
callback_url="https://example.com/webhook"
)
| Parameter | Type | Description |
|---|---|---|
target | str or dict | "vertical", "square", "landscape", or {"width": int, "height": int} |
mode | str | "simple" or "smart" (default). Smart mode uses object-aware tracking. |
start | float | Optional start time in seconds |
end | float | Optional end time in seconds |
callback_url | str | Optional URL for async completion callback |
smart_vertical_reframe()
Convenience method that reframes to vertical (9:16) with smart object tracking in a single call:
vertical = video.smart_vertical_reframe()
Next Steps
Publishing Patterns
Embed players and share content
Timeline Architecture
Build complex compositions