An HTML overlay, sent over WebRTC
Left: video with an HTML scorebug composited on top. Right: the same picture received as a WebRTC track. No OBS, no server.
The stream plugin keeps the overlay as a canvas. A program canvas draws it over the footage, captureStream() turns that into a video track, and WebRTC carries it.
Try it
Change the score, slide the lower third, or put your camera behind the graphics. The right side follows a few frames later. Open a viewer tab to add a receiver.
How it works
The overlay is HTML
Scoreboard, live badge and lower third are plain DOM on a transparent 960×540 stage. The lower third slides with
left, nottransform, so the stream patches a strip instead of repainting the frame.stream()keeps it as a canvasAfter the first full capture, only changes are captured and patched in. The stats line shows the median repaint cost.
A program canvas composites it
Each frame draws the footage, then the overlay canvas on top.
captureStream()makes it a trackThe program canvas becomes a
MediaStreamTrack.contentHint: 'detail'keeps the text sharp when bandwidth drops.WebRTC carries it
Both peers run in your browser; viewer tabs find the sender through a
BroadcastChannel. A real app does the offer/answer through its own signalling server. The media path is the same.
The code
import { stream } from '@zumer/snapdom-plugins/stream'
const overlay = stream(stage, { embedFonts: false })
function frame() {
ctx.drawImage(footage, 0, 0, 960, 540)
ctx.drawImage(overlay.canvas, 0, 0, 960, 540)
requestAnimationFrame(frame)
}
requestAnimationFrame(frame)
const track = program.captureStream(30).getVideoTracks()[0]
track.contentHint = 'detail'
peerConnection.addTrack(track)