Examples

Camera

About

A live camera, from RTP to the page.

quillo run media.qwe --watch then open http://localhost:8080

Then send it a stream. A test picture and a tone, with ffmpeg:

ffmpeg -re -f lavfi -i testsrc=size=1280x720:rate=30 -f lavfi -i sine=frequency=440
-map 0:v -c:v libx264 -tune zerolatency -profile:v baseline -pix_fmt yuv420p -g 60
-f rtp rtp://127.0.0.1:5004 -map 1:a -c:a libopus -f rtp rtp://127.0.0.1:5006

or this Mac's camera and microphone (-f v4l2 -i /dev/video0 on Linux):

ffmpeg -f avfoundation -framerate 30 -video_size 1280x720 -i "0:0"
-map 0:v -c:v libx264 -tune zerolatency -profile:v baseline -pix_fmt yuv420p -g 60
-f rtp rtp://127.0.0.1:5004 -map 0:a -c:a libopus -f rtp rtp://127.0.0.1:5006

The server takes the RTP and passes the frames on to every page watching, over WebTransport where the browser has it: no transcoding, no HLS segments, a fraction of a second behind the camera. A page that starts watching gets the frames since the last keyframe, so it shows a picture at once. Each <quillo-media> decodes with the browser's own decoders (WebCodecs); click it for sound.

Run it

$ quillo run media.qwe --watch

Source

media.qwe
media.rtp("cam", { video: 5004, audio: 5006 })server fn live_streams() -> list = media.streams()// How the stream is going, asked for every second.component Stats() {    state streams = live_streams()    every(1000, () => { streams = live_streams() ?? streams })    <p.stats>        {for s in streams => <span key={s.name}>            <b>{s.video.fps}</b> fps · <b>{s.video.kbps + s.audio.kbps}</b> kbit/s · <b>{s.viewers}</b> watching · <b>{s.video.lost + s.audio.lost}</b> packets lost        </span>}    </p>}let style = css`* { box-sizing: border-box; }body { font: 15px/1.4 system-ui, sans-serif; max-width: 60rem; margin: 2rem auto; padding: 0 1rem; color: #1f2328; }h1 { font-size: 1.4rem; margin: 0 0 1rem; }quillo-media { width: 100%; border-radius: 10px; overflow: hidden; background: #000; aspect-ratio: 16 / 9; }quillo-media[data-state="connecting"]::after, quillo-media[data-state="waiting"]::after {  content: "Waiting for the stream…"; position: absolute; inset: 0; display: grid; place-items: center; color: #aaa;}.stats { color: #57606a; font-variant-numeric: tabular-nums; } .stats b { color: #1f2328; }@media (prefers-color-scheme: dark) { body { background: #0d1117; color: #e6edf3; } .stats { color: #8b949e; } .stats b { color: #e6edf3; } }`route GET / =    <html>        <head>            <meta charset="utf-8"/>            <meta name="viewport" content="width=device-width, initial-scale=1"/>            <title>Camera</title>            <style>{style}</style>        </head>        <body>            <h1>Camera</h1>            <quillo-media stream="cam" controls muted/>            <Stats/>        </body>    </html>

See media.qwe on GitHub

Thread
11Useful? Like it, or add to its thread below.

Thread 0 posts

On Camera: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.