OpenVibe.Live/Docs
Source on GitHub

VODs & Clips#

Recording System#

OpenVibe.Live automatically records your streams as VODs (Video on Demand).

Protocol-Specific Recording#

ProtocolRecording MethodFormat
WebRTC (Browser)Browser-side MediaRecorder, chunks uploaded to serverWebM (VP8/VP9 + Opus)
RTMPServer-side FFmpeg captureWebM (VP8 + Vorbis)
JSMPEGServer-side FFmpeg via WebSocket relayWebM (VP8 + Vorbis)

Recording Lifecycle#

  1. Start: Recording begins when the stream goes live
  2. Live DVR: A seekable sidecar file is generated periodically (every 60s for server-side, every 2 chunks for browser uploads) so viewers can rewind
  3. Finalize: When the stream ends, the recording is remuxed for proper seeking, duration is probed, and a thumbnail is generated
  4. Auto-cleanup: Recordings shorter than 10 seconds are automatically deleted (test streams, accidental go-lives)

Browser Tab Close Safety#

If you close the browser tab during a WebRTC stream, sendBeacon attempts to upload any remaining chunks. The server will auto-finalize when it detects the stream has ended.

DVR / Live Seeking#

Viewers can seek backwards in a live stream using the DVR controls:

DVR availability appears after ~30 seconds of recording.

Clips#

Viewers can create clips from live streams:

  1. Click the Clip button during a stream
  2. Set the clip duration (default: 30 seconds)
  3. The clip is saved from the server-side recording

Clips are unlisted by default — the stream owner can publish or delete them from the dashboard.

VOD Management#

From the dashboard:

Chat Replay#

VODs include synchronized chat replay. Messages are stored in the database with timestamps relative to the stream start. Deleted messages are automatically excluded from replay (soft-delete with is_deleted flag).

AI moments: pastes and clips never overlap#

Two jobs turn stream moments into content: server/ai/ai-moments-job.js (image pastes for the home hero + pastes tab, every 6 h) and server/ai/auto-clip-job.js (live chat-spike clips + a VOD backfill). They used to pick the same second of the same VOD with the same title. Now:

AI-inferred category#

Go-live used to default every stream to irl, so every AI prompt (AI viewers, streamer overviews, VOD overviews, the Arena, sound detection) assumed everyone is an IRL streamer. Now the category selector defaults to Auto (stored as NULL), and the stream-memory rollup — the same summarise call that already runs — returns { overview, category, tags } with category from the fixed taxonomy (outdoors, travel, building, music, gaming, robot, desktop, irl, other). It is stored on streams.ai_category / streams.ai_tags and the channel inherits the latest read (channels.ai_category).

Everything reads the effective value: listing queries return COALESCE(ai_category, category) AS category (the self-selected value is still there as chosen_category), stream_category on VODs/clips, the AI viewers' session block ("judged from the stream itself"), streamer overviews, sound detection and the Arena all prefer ai_category. A streamer can still pick a category manually; the AI read wins once it exists.

This page is rendered from docs/vods-and-clips.md in the OpenVibe.Live repository. Found a mistake? Edit it there.