peertube

peertube · sources · schema v1

PEERTUBE — federated-video SOURCE. Search the open PeerTube fediverse, pick a video, and its picture streams in as a CLEAN (untainted) WebGL video texture plus stereo audio — a real downstream-usable source, NOT play-only. MODEL: a debounced search box queries Sepia Search (sepiasearch.org, the official PeerTube meta-index — CORS-open + anonymous, NO proxy needed); results list title, channel@host, duration, a LIVE badge, and a thumbnail. Click a result → the card fetches that video's per-instance public API (https://<host>/api/v1/videos/{uuid}) and resolves a playable stream: it PREFERS the HLS master playlist (streamingPlaylists[0].playlistUrl → attached via hls.js for adaptive playback) and FALLS BACK to the highest-resolution progressive MP4 (files[].fileUrl, attached as a plain <video src>). The stream attaches to a card-owned <video crossorigin="anonymous"> → the engine samples it into the FBO (the `video` output) + taps stereo audio (audio_l / audio_r via MediaElementSource → ChannelSplitter, with the shared keep-alive so an unpatched source keeps decoding at full rate). WHY THE TEXTURE + AUDIO ARE CLEAN (verified): PeerTube sends Access-Control-Allow-Origin:* on the FINAL media hop (master .m3u8 + the fragmented-mp4 / mpeg-ts segments) under a favorable `credentialless` COEP posture, so a crossorigin <video> fed by hls.js both PLAYS and yields an untainted texture — unlike archive.org video (play-only). IO — Inputs: play_trigger (gate, edge=trigger — a rising edge toggles play/pause), next_trigger (gate, edge=trigger — a rising edge loads the next search result, wrapping). Outputs: video (the live frame texture), audio_l / audio_r (stereo, silent ConstantSource placeholders until a stream attaches), loaded (trigger — one pulse when a new video finishes loading), ended (trigger — pulses when the video reaches its end), playing (gate — HIGH while actually playing), playhead (CV — 0..1 normalized position). CV/PATCHING: all inputs + outputs live in the card's yellow drill-down PATCH PANEL (top-left/top-right affordances → INPUT/OUTPUT → grouped Gates / CV / Audio / Video rows) — there are NO raw side jacks (#767 standard). Trigger inputs are main-thread edge-detected the established video-module way (a single bridge-written cv-param read per tick — never a whole-AnalyserNode rescan). USAGE: type a term, press Enter (or wait for the debounce), pick a video, and route VIDEO into a mixer/keyer/OUTPUT and audio_l/audio_r into AUDIO OUT or a SCOPE/SYNESTHESIA for audio-reactive visuals; clock the next_trigger from a sequencer to channel-surf the fediverse. GRACEFUL: ~1/6 instances misconfigure CORS (raw S3 with no ACAO) → the element taints / the HLS load fails fatally → the card degrades to "display unavailable", surfaces a clear status, and AUTO-SKIPS to the next result (it never crashes, taints the texture, or hangs on loading). An optional instance field biases attribution display. Only { instanceHost, uuid, name, selectedHost } persist on the node + sync to rack-mates (everyone resolves + plays the same video locally); transient playback state stays render-local (never a per-frame synced-store write). The AUDIO TRAP: the <video> is created muted for autoplay, then un-muted ONLY after the MediaElementSource tap succeeds, so audio routes into WebAudio without native speaker double-output. LEGAL: federated PUBLIC videos, not hosted by patchtogether — an in-card disclaimer + attribution to PeerTube + Sepia Search ship with it.

A federated-video SOURCE that streams public videos from the PeerTube fediverse. Type a term into the search box (debounced ~350ms, rate-limited to ~50 calls / 10s, optionally scoped to one instance) and the card queries Sepia Search — the CORS-open meta-index of the PeerTube federation — for a results list (title, channel@host, duration, thumbnail). Click a result and the card hits that instance's video-details API to resolve the HLS master playlist (.m3u8), then attaches it via hls.js (or progressive MP4 / Safari-native HLS) to a card-owned crossorigin video element. The engine samples that element into a WebGL framebuffer; the fragment shader is a straight passthrough of the live frame (and draws a dim near-black idle gradient when nothing is loaded), so the video out is a genuine downstream-usable texture, not play-only. Unlike ARCHIVIST (which is VIDEO-ONLY because archive.org's final media hop is CORS-tainted, so its audio jacks are dead), PeerTube sends Access-Control-Allow-Origin:* on the master playlist + segments, so the texture is UNTAINTED and the stereo audio track is fully extractable and patchable on audio_l/audio_r (split from a MediaElementSource via a 2-channel splitter, with a silent gain-0 keep-alive bridged to the destination that keeps the element decoding at full rate even when audio isn't patched). Frames upload at the source's decode cadence (requestVideoFrameCallback; Firefox falls back to a currentTime-advance check) downscaled to the engine resolution so a high-bitrate stream doesn't flood GPU texture traffic. Only the selection (selected host, video uuid, name) plus the last search term and optional instance host are persisted to the node so rack-mates resolve the SAME stream; ~1/6 instances misconfigure CORS (raw S3, no ACAO) and a stream that taints, errors, or stalls past a 14s timeout is marked "display unavailable" and auto-skips to the next result after a short beat rather than hanging. The card UI (none of these are module params) is: a search input + optional instance-host input, a "↻ next" button, the resizable 16:9 preview screen, a now-playing label with an attribution link to the watch page, a Play/Pause transport button with a playhead progress bar, a scrollable results list, and a Sepia Search / PeerTube attribution disclaimer. The card has a resizable 16:9 preview screen (bottom-right corner-drag handle, persisted size; default 360x540, min 360x360). Usage: drop it as a video source and feed its output into a mixer or any video module; patch a clock into next_trigger to channel-surf the results hands-free, and patch the loaded/ended event outs or playhead CV downstream to sequence around the playback.

the faceplate

peertubeplay_triggergatenext_triggergatevideovideoaudio_laudioaudio_raudioloadedgateendedgateplayinggateplayheadcvaudiocvgatepitch
2 inputs · 7 outputs · 3 params

inputs

idcablewhat it does
play_triggergateTrigger (gate cable, edge:'trigger'): a rising edge toggles the current video between play and pause. Routed through the CV bridge as the synthetic cv_play_trigger param, which the card polls + edge-detects (<0.5 -> >=0.5); it fires once per rising edge, not while held. Patch a clock or any gate here for hands-free transport.
gate / trigger; modulates cv_play_trigger (summed directly (the destination DSP scales it)); trigger — fires once per rising edge
next_triggergateTrigger (gate cable, edge:'trigger'): a rising edge advances to the NEXT result in the search list (wrapping to the first; if the list is empty it re-runs the last search). Routed through the CV bridge as the synthetic cv_next_trigger param and edge-detected by the card; fires once per rising edge, not while held. Patch a clock here to channel-surf the results in time.
gate / trigger; modulates cv_next_trigger (summed directly (the destination DSP scales it)); trigger — fires once per rising edge

outputs

idcablewhat it does
videovideoThe loaded stream's live frame as a video texture — untainted and downstream-usable because PeerTube sends CORS/ACAO on its media. Dim near-black idle gradient when nothing is loaded; goes to the auto-skip 'unavailable' fallback for a CORS-misconfigured instance.
RGB video stream
audio_laudioLeft channel of the stream's stereo audio (output 0 of the channel splitter fed by the video element's MediaElementSource — working audio, unlike ARCHIVIST). A silent ConstantSource (offset 0) placeholder until a stream attaches and the audio tap is wired.
audio signal
audio_raudioRight channel of the stream's stereo audio (output 1 of the same channel splitter). A silent ConstantSource (offset 0) placeholder until a stream attaches and the audio tap is wired.
audio signal
loadedgateTrigger out (gate cable, edge:'trigger'): one short ~5ms rising-edge pulse each time a newly selected video finishes loading and its audio is wired. Patch into a downstream clock/reset/sample-and-hold to react to a track change.
gate / trigger; trigger — fires once per rising edge
endedgateTrigger out (gate cable, edge:'trigger'): one short ~5ms rising-edge pulse when the playing video reaches its end. Patch into next_trigger (self or another source) to auto-advance, or into any downstream trigger consumer.
gate / trigger; trigger — fires once per rising edge
playinggateGate out (gate cable, edge:'gate'): held HIGH while the video is actually playing, LOW while paused, loading, idle, or unavailable. Use as a run/transport gate for downstream modules.
gate / trigger; gate — acts while the level is high (reacts to both edges)
playheadcvCV out: the normalized playback position, 0..1 (currentTime / duration), updated as the video plays. Patch into any CV destination to scrub or modulate downstream gear in sync with the video timeline.
control voltage (CV)

params

idlabelrangedefaultcurve
gainGain0..2linear
cv_play_triggerPlay trigger0..10linear
cv_next_triggerNext trigger0..10linear

controls

controlwhat it does
Next triggerNext trigger (hidden synthetic param, 0 to 1, default 0): the CV bridge writes the next_trigger input's gate level here; the card polls readParam and edge-detects a rising edge to load the next search result. Not a user-facing knob.
Play triggerPlay trigger (hidden synthetic param, 0 to 1, default 0): the CV bridge writes the play_trigger input's gate level here; the card polls readParam and edge-detects a rising edge (<0.5 -> >=0.5) to toggle play/pause. Not a user-facing knob.
GainGain — declared output-level param (0 to 2, linear; default 1.0). NOTE: like TV-LIBRARIAN, the passthrough shader has no uGain uniform and draw() never applies it, so the param is carried on the module but currently inert — it does not yet brighten or scale the video output.

source

peertube.ts on GitHub.

Generated from packages/web/src/lib/{audio,video}/module-registry.ts · repo