Skip to main content

Personalized streaming

data (video) transform stream

A reference technical solution for composing per-user HLS feeds from indexed moments. Retrieve clips by query, compose them on a chunk-level timeline, apply branding and subtitles as overlay tracks, publish as an HLS manifest. No re-encode step.

Architecture

The composition pipeline.

Request resolves against the indexes already built on your collection. Selected moments are composed on a Timeline; overlays apply at the manifest layer; output is an HLS m3u8 URL with per-segment caching.

solution.personalize() · architecture

REQUEST

match_final.mp4
user_
Create highlights of this match

MEMORY

Scanning 00:42 / 96:00
2 moments detected

TRANSFORM

Create clips
Add logo
Add subtitles
Change aspect ratio

NEW STREAM

LOGO 00:42
hls://highlights.m3u8
The three stages

Retrieve. Compose. Stream.

Each stage is a method on the SDK. No infrastructure to operate. No re-encoding pipelines to run.

01

Retrieve from memory

Query the indexes you've already built. Filters, semantic recall, and structured constraints in one call. Returns ranked moments with playable clip URLs.

# search moments
results = video.search(
  "goals by player_42",
  type="deepsearch",
)
shots = results.get_shots()
02

Compose the timeline

Merge the moments. Lay overlays on top. Add multilingual subtitles. Reframe for the target aspect ratio. All chunk-level operations. No re-encode.

# compose
timeline = Timeline(conn)
timeline.resolution = "608x1080"
video_track.add_clip(0, highlight_clip)
brand_track.add_clip(0, logo_clip)
caption_track.add_clip(0, caption_clip)
03

Stream the result

Output is an HLS stream URL. Embeddable in any player, cacheable at the CDN edge, addressable per-user. Generated fresh, on demand.

# publish

timeline.add_track(track)
stream_url = timeline.generate_stream()
Full implementation

A complete personalized highlight reel in under 20 lines.

from videodb import connect
from videodb.editor import Timeline, Track, Clip, VideoAsset, ImageAsset, CaptionAsset

conn = connect()
coll = conn.get_collection()
video = coll.get_video("match_final")
logo = coll.upload(file_path="brand.png")

# 1. Retrieve. Query the indexes you already built.
results = video.search("goals scored by player_42", type="deepsearch")
moment = results.get_shots()[0]

# 2. Compose. Add branding, captions, and mobile framing.
timeline = Timeline(conn)
timeline.resolution = "608x1080"  # vertical for mobile
video_track, brand_track, caption_track = Track(), Track(), Track()
video_track.add_clip(0, Clip(asset=VideoAsset(id=video.id, start=moment.start), duration=12))
brand_track.add_clip(0, Clip(asset=ImageAsset(id=logo.id), duration=12, opacity=0.85))
caption_track.add_clip(0, Clip(asset=CaptionAsset(src="auto"), duration=12))

# 3. Stream. Fresh HLS URL, cacheable per-user.
timeline.add_track(video_track)
timeline.add_track(brand_track)
timeline.add_track(caption_track)
stream_url = timeline.generate_stream()
print(stream_url)
# → https://cdn.videodb.io/u/42/highlights.m3u8
personalized_streaming.py
Data flow

What actually happens between request and stream.

The whole pipeline executes inside VideoDB. No round-trip to your services. No re-encoding step.
<1 s for first segment. End-to-end budget.

QUERY user_42 + context REQUEST INDEX SCAN scenes · speech embeddings · tags ~90 ms RETRIEVE TIMELINE cut · merge overlay · caption chunk-level COMPOSE MANIFEST HLS playlist + overlay layer 0 re-encode RENDER CDN EDGE segment cache per-user TTL multi-region SERVE PLAYER .m3u8 embedded CLIENT QUERY user_42 + context INDEX SCAN scenes · speech embeddings · tags ~90 ms TIMELINE cut · merge overlay · caption chunk-level MANIFEST HLS playlist + overlay layer 0 re-encode CDN EDGE segment cache per-user TTL multi-region PLAYER .m3u8 embedded

What to know before you ship

01 Latency

Sub-second to first segment

Retrieve is ~120 ms p95. Compose is chunk-pointer math. No re-encode. First HLS segment is served while later segments resolve in the background.

02 Caching

Per-user TTL at the edge

Each personalized manifest gets a unique URL; CDN segments shared across users are deduplicated. Per-user TTL keeps invalidation cheap.

03 Overlays

Burned at the manifest layer

Brand marks, subtitles, and reframes are applied as overlay tracks on the HLS manifest. Same source bits; new visual surface.

04 Cost

Usage-based, not minute-based

Pay for retrievals + unique segments served. No charge for compose-time CPU. The format makes the cuts free.

Use cases

What teams ship with
this solution.

Sports highlight reels

Sports highlight reels

Per-fan highlights composed from live games and seasons of archive. Crowd-peak audio detection, player tracking, scoreboard overlay rendering at the manifest layer.

Episodic recap for OTT

Episodic recap for OTT

"Previously on" cuts generated per viewer based on the last episode watched and which character arcs they're following. Composed inline; output is a per-user HLS manifest.

Dynamic ad insertion

Dynamic ad insertion

Slot ads at scene boundaries, not on a fixed clock. Brand-safety and audience filters apply at compose time so the same source produces different manifests per viewer.

Agent-generated explainers

Agent-generated explainers

An agent pulls source clips from a knowledge base, composes them with synchronized subtitles, and streams the result back to the user. The agent owns the query; VideoDB owns the render.

Sports highlight reels
Episodic recap for OTT
Dynamic ad insertion
Agent-generated explainers
Machine