-
Notifications
You must be signed in to change notification settings - Fork 76
Open
Labels
enhancementNew feature or requestNew feature or request
Description
Overview
Let viewers and streamers create short clips (30–60s) from a live stream by clicking a ✂️ Clip button. Clips are the primary viral mechanic on streaming platforms — a great moment gets clipped, shared, and drives new viewers back.
How it works
- Viewer/streamer clicks ✂️ Clip button on the player during a live stream
- Selects clip length: 30s or 60s
POST /api/streams/clipsis called:- Calls Mux to create an asset from the last N seconds of the DVR stream
- Inserts a
stream_recordingsrow withstatus: 'processing',clip: true
- Mux
video.asset.readywebhook fires → updates status toready - User is notified (links to notification issue feat: real-time notifications system #365) with a share link
Mux DVR requirement
Clipping requires live DVR to be enabled when the stream is created. Update POST /api/streams/create:
{
latency_mode: "standard", // required for DVR
use_slate_for_standard_latency: false,
reconnect_window: 60,
}Clip creation (Mux API)
// POST /api/streams/clips
const asset = await mux.video.assets.create({
input: [{
url: `https://stream.mux.com/${playbackId}.m3u8`,
start_time: Math.floor(Date.now() / 1000) - durationSeconds,
end_time: Math.floor(Date.now() / 1000),
}],
playback_policy: ["public"],
mp4_support: "standard",
});
// Insert into DB
await sql`
INSERT INTO stream_recordings
(id, user_id, playback_id, mux_asset_id, status, clip, clipped_by, source_stream_id)
VALUES
(${uuid}, ${streamOwnerId}, ${asset.playback_ids[0].id},
${asset.id}, 'processing', true, ${clippedByUsername}, ${streamId})
`;DB changes
ALTER TABLE stream_recordings ADD COLUMN IF NOT EXISTS clip BOOLEAN DEFAULT false;
ALTER TABLE stream_recordings ADD COLUMN IF NOT EXISTS clipped_by TEXT;
ALTER TABLE stream_recordings ADD COLUMN IF NOT EXISTS source_stream_id TEXT;API route
POST /api/streams/clips
- Auth required (session cookie)
- Rate limited: max 5 clips per user per stream
- Request:
{ playback_id, duration_seconds: 30 | 60, stream_owner_username } - Response:
{ clip_id, status: "processing" }
UI
Clip button on player (view-stream.tsx)
- ✂️ icon in player controls overlay (bottom-right, near fullscreen)
- Only visible when stream is live and user is logged in
- Opens a small popover: "30 second clip" / "60 second clip" → Confirm
- "Creating clip..." loading state → "Clip ready! Share →" toast with link
Clips page (/[username]/clips)
- Clips show a ✂️ badge on the thumbnail
- "Clipped by @username" shown if clipped by a viewer (not the owner)
- Owner can delete clips from their page (already implemented)
Share
- On clip ready: clipboard copy of
/[username]/clips/[id] - OG metadata already works for clip pages (already implemented)
Acceptance criteria
- Mux DVR enabled on stream creation
- ✂️ Clip button visible on live stream player for logged-in users
- 30s/60s length selection
-
POST /api/streams/clipscreates Mux asset from DVR stream -
stream_recordingsrow inserted withstatus: processing - Mux
video.asset.readywebhook updates status toready - Clip visible on
/[username]/clipswith ✂️ badge - Share link with working OG metadata
- Rate limit: max 5 clips per user per stream
- Notification sent when clip is ready
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request