WebRTC de baja latencia
Player WebRTC sobre LiveKit con latencia sub-segundo para "ver en vivo ahora" y videollamadas. Tokens de subscribe efímeros por room.
StreamHub es una capa de gestión sobre LiveKit: WebRTC sub-segundo, ingest multi-protocolo, HLS en vivo, grabación a tu propio S3 y un SDK JavaScript liviano y drop-in para publicar y suscribirte por WebRTC. Multi-tenant, con webhooks firmados y observabilidad.
WebRTC, RTMP, WHIP, RTSP y HLS; grabación a tu S3; realtime, multi-tenant, webhooks firmados y un SDK WebRTC liviano. Sobre LiveKit, self-hosted.
Entrá por donde quieras, salí en WebRTC de baja latencia o en HLS embebible.
Player WebRTC sobre LiveKit con latencia sub-segundo para "ver en vivo ahora" y videollamadas. Tokens de subscribe efímeros por room.
Push desde OBS/ffmpeg a rtmp://…:1935/live/<key>. Stream key + password opcional: StreamHub corta el push que no se validó antes.
Endpoint WHIP para publicar desde el navegador o encoders modernos por WebRTC, sin pasar por RTMP.
Tirá de una fuente remota (rtsp://camara/stream) y republicala en la room. Ideal para cámaras IP y NVRs.
Egress HLS segmentado servido en /hls/<app>/<room>/index.m3u8 (video.js, CORS abierto). ~6-15s, embebible en cualquier lado.
La media es tuya: se sube a tu bucket. Las salidas van a YouTube, Twitch o tu CDN.
Egress a MP4 y subida a tu propio bucket S3 (AWS, Wasabi, MinIO). Un bucket/prefijo por app; las claves nunca viven en el YAML.
Cada grabación queda como VOD en tu S3 con snapshot, metadatos (duración/resolución/codec) y URL pública o presignada.
Cortá la grabación cada N minutos: cada parte es su propio MP4 = su propio VOD, indexado y con callback recording_part_ready.
Capturá un JPEG cada N segundos durante la grabación, subido a tu S3. También snapshots on-demand de cualquier room.
Reenviá una room a un RTMP/RTMPS externo (YouTube/Twitch/custom) con el widget Transmitir: webcam del navegador → restream.
Chat, reacciones y viewers sobre data-channels; webhooks firmados de todo lo que pasa.
Chat sobre data-channels de LiveKit (con emojis). El backend puede inyectar mensajes y dispara el callback chat_message.
Reacciones animadas flotantes sobre el topic reaction: corazones y likes en tiempo real, con su callback reaction.
Conteo de subscribers reales por stream en vivo, excluyendo publishers y participantes ocultos/QC. Exportado a Prometheus.
StreamHub postea un JSON firmado (HMAC-SHA256) por CADA evento: room, participantes, ingress/egress, grabación, VOD y HLS.
Páginas públicas /play y /embed + snippet iframe. Players WebRTC y HLS sin auth, con panel de chat/reacciones/viewers incluido.
Apps aisladas, transcoding adaptativo con GPU opcional y métricas Prometheus de todo.
Ladder de renditions vía simulcast de LiveKit + ingress multi-layer para un player adaptativo por app, sin config extra.
Detección de GPU por nodo (NVIDIA nvidia-smi / VAAPI /dev/dri) y hwaccel auto/gpu/cpu por app. Nunca falla si no hay GPU.
Cada "app" es un tenant: rooms/streams namespaced, su S3, sus VODs/DB, sus tokens y callbacks. Totalmente aisladas.
Equipos aislados por tenant, roles/permisos y cuotas: apps, streams concurrentes, minutos de grabación y GB de egress al mes.
Métricas Prometheus en /metrics (streams, viewers, VODs, uploads S3, callbacks, GPU…), health probe, stats y logs consultables.
Registro global streamhub.db + una vods.db por app. Sin base pesada que operar: SQLite por tenant y media en S3 por app.
Todo por API, todo self-hosteable. Sumás el SDK y empezás a publicar en pocas líneas.
Un SDK JavaScript liviano: sumás @streamhub/adaptor (npm o un <script>) y StreamHubAdaptor te deja publicar y suscribirte por WebRTC en pocas líneas.
API bajo /api/v1 con envelope { data, error }. Apps, ingress, grabación, VODs, tokens, broadcast y HLS: todo por HTTP.
Auth built-in (signup/login JWT, teams, superadmin) + API tokens sk_ para server-to-server. Bearer en todos los endpoints.
Rooms audio-only (voz estilo Discord) + modo radio: un locutor publica y los oyentes entran subscribe-only ocultos, con listen-token público.
Self-hosteable de punta a punta (Docker + LiveKit). En beta y gratis. ¿No querés operarlo? Lo hosteamos por vos.
Capturas reales del panel de StreamHub. Un solo lugar para tus apps, streams, grabaciones, tokens y webhooks — corriendo sobre LiveKit.






Estado del core de un vistazo: CPU, memoria y disco en vivo, streams activos, apps registradas y conexiones de ingress/egress. Con salud de LiveKit y uptime.
Claro u oscuro, vos elegís — todo el backoffice tematizado.


De cero al aire en tres pasos.
Cada app es un tenant aislado: su prefijo de sala, su bucket S3, sus tokens y cuotas. Listo en segundos desde el backoffice.
Enviá tu señal por RTMP, WHIP, RTSP o directo desde la webcam. Copiás la URL y el stream key en OBS y salís al aire.
WebRTC sub-segundo o HLS, grabación a tu propio S3 (VOD + snapshots) y players embebibles con link público o iframe.
Estamos en beta y es gratis. Open source y self-hostable — o lo hospedamos nosotros por vos.
Un stack completo y self-hostable, documentado de punta a punta. Una API REST (global y por app), webhooks firmados, config por app, integraciones nativas y un deploy en un comando. Cada ruta vive detrás de un único dominio, con un explorador OpenAPI en vivo.
Guías a fondo por función, de WebRTC a las cuotas.
Superficie REST de todo el server, protegida por tokens sk_.
Todo acotado a una única app tenant.
Eventos entrantes de LiveKit y POST firmados salientes.
El config.yaml por app, sin secretos.
Clientes nativos y de dispositivos, y el protocolo que habla cada uno.
Un docker compose up, o systemd + nginx.
Cómo está construido y hacia dónde va.
Autenticá con un sk_ token. Los nombres de sala llevan el prefijo de la app (live + demo → live-demo).
# Scaffold an isolated tenant: config, per-app SQLite, S3 prefix, samples
curl -s -X POST https://streamhub.digitalhub.com.ar/api/v1/apps \
-H "Authorization: Bearer $STREAMHUB_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"live","displayName":"Live","roomPrefix":"live"}' # One call returns the LiveKit token + wsUrl + play/embed URLs
curl -s -X POST https://streamhub.digitalhub.com.ar/api/v1/apps/live/tokens \
-H "Authorization: Bearer $STREAMHUB_TOKEN" \
-H "Content-Type: application/json" \
-d '{"room":"demo","identity":"viewer-1","canPublish":false,"ttl":"10m"}'
# → { "data": { "token": "<jwt>", "wsUrl": "wss://media.digitalhub.com.ar",
# "room": "live-demo", "playUrl": "...", "embedUrl": "...", "iframe": "..." } } # RTMP push endpoint (also: whip, or url for RTSP/HLS pull)
curl -s -X POST https://streamhub.digitalhub.com.ar/api/v1/apps/live/ingress \
-H "Authorization: Bearer $STREAMHUB_TOKEN" \
-H "Content-Type: application/json" \
-d '{"inputType":"rtmp","room":"demo","enableTranscoding":true}'
# → { "data": { "ingressId": "IN_abc123", "streamKey": "sk-9f3c...", "roomName": "live-demo" } }
# then push with any RTMP encoder (OBS, ffmpeg, a drone...)
ffmpeg -re -i input.mp4 -c:v libx264 -c:a aac \
-f flv "rtmp://media.digitalhub.com.ar:1935/live/<streamKey>" # Room-composite MP4 → the app's own bucket (AWS / Wasabi / MinIO) → VOD + snapshot
curl -s -X POST https://streamhub.digitalhub.com.ar/api/v1/apps/live/recording/start \
-H "Authorization: Bearer $STREAMHUB_TOKEN" \
-H "Content-Type: application/json" \
-d '{"roomName":"live-demo"}'
# → { "data": { "vodId": 12, "egressId": "EG_xyz789", "status": "recording" } }
# stop it (by VOD id or egress id); a vod_ready webhook fires when the upload finishes
curl -s -X POST https://streamhub.digitalhub.com.ar/api/v1/apps/live/recording/12/stop \
-H "Authorization: Bearer $STREAMHUB_TOKEN" # Start a live HLS egress for a stream (video.js-compatible, embeddable)
curl -s -X POST \
https://streamhub.digitalhub.com.ar/api/v1/apps/live/streams/live-demo%2Fcamera-1/hls/start \
-H "Authorization: Bearer $STREAMHUB_TOKEN"
# → { "data": { "playlistUrl":
# "https://streamhub.digitalhub.com.ar/hls/live/live-demo/index.m3u8" } }
# the playlist itself needs no auth — point any HLS player at it
open https://streamhub.digitalhub.com.ar/hls/live/live-demo/index.m3u8 // Every callback is a signed POST. Verify the HMAC-SHA256 over the raw body.
import crypto from 'node:crypto';
app.post('/streamhub', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.header('X-StreamHub-Signature'); // "sha256=<hex>"
const expected =
'sha256=' + crypto.createHmac('sha256', SECRET).update(req.body).digest('hex');
if (!sig || !crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected)))
return res.status(401).end();
const evt = JSON.parse(req.body.toString('utf8')); // { event, app, data }
switch (evt.event) {
case 'stream_started': /* a publisher/ingress went live */ break;
case 'vod_ready': /* recording uploaded to your S3 */ break;
case 'recording_failed': /* upload failed, local file kept */ break;
}
res.status(200).end();
}); # Open source — self-host it, or let us host it for you.
git clone <vision-media-server> # repo: vision-media-server
cp .env.example .env # LiveKit keys, per-app S3, PUBLIC_BASE_URL
docker compose up -d # core + LiveKit + ingress/egress, HTTPS via Caddy
# Swagger / OpenAPI: /api/v1/docs Metrics: /metrics Health: /api/v1/health Esto es un recorrido, no el mapa completo — la referencia entera cubre arquitectura, operación, testing y cada variable de entorno. Exploralo en vivo en los docs OpenAPI, o leé los streamhub-docs en el repo.
@streamhub/adaptor es un SDK JavaScript liviano para publicar y suscribirte por WebRTC, construido sobre livekit-client. Un constructor mínimo, un puñado de métodos y callbacks simples por string — poné una cámara al aire o reproducí una sala en pocas líneas.
import { StreamHubAdaptor } from "@streamhub/adaptor";
// A lightweight WebRTC client, built on livekit-client.
const adaptor = new StreamHubAdaptor({ /* config below */ }); npm install @streamhub/adaptor livekit-client import { StreamHubAdaptor } from "@streamhub/adaptor";
const adaptor = new StreamHubAdaptor({
// StreamHub mints the LiveKit token for you (prefer a pre-minted token + wsUrl in prod)
streamhubApiUrl: "https://streamhub.digitalhub.com.ar/api/v1",
appName: "live",
streamhubApiToken: STREAMHUB_TOKEN, // dev only — mint server-side for production
mediaConstraints: { video: true, audio: true },
localVideoId: "localVideo", // <video id="localVideo"> preview element
callback: (info, obj) => {
if (info === "initialized") adaptor.joinRoom("demo", "camera-1");
else if (info === "joinedTheRoom") adaptor.publish(obj.streamId); // send cam + mic
else if (info === "publish_started") console.log("on air");
},
callbackError: (err, msg) => console.warn(err, msg),
}); import { StreamHubAdaptor } from "@streamhub/adaptor";
const viewer = new StreamHubAdaptor({
streamhubApiUrl: "https://streamhub.digitalhub.com.ar/api/v1",
appName: "live",
streamhubApiToken: STREAMHUB_TOKEN,
isPlayMode: true, // subscribe-only: no camera / mic
callback: (info, obj) => {
if (info === "initialized") viewer.joinRoom("demo", "viewer-1");
else if (info === "joinedTheRoom") viewer.play(obj.ATTR_ROOM_NAME);
else if (info === "newStreamAvailable") {
const el = document.createElement("video");
el.autoplay = el.playsInline = true;
el.srcObject = new MediaStream([obj.track]); // obj.track is a MediaStreamTrack
document.getElementById("remote").append(el);
}
},
}); <!-- No build step? Drop in one script tag and you're ready. -->
<script src="https://streamhub.digitalhub.com.ar/sdk/streamhub-adaptor.global.js"></script>
<script>
const viewer = new StreamHubAdaptor({ isPlayMode: true, /* ...config */ });
</script> <!-- The mint call returns a ready-to-paste embed. Public player, no SDK needed. -->
<iframe
src="https://streamhub.digitalhub.com.ar/embed/live/live-demo"
width="640" height="360" frameborder="0"
allow="autoplay; fullscreen; camera; microphone"
allowfullscreen>
</iframe> initialized, publish_started, newStreamAvailable, roomInformation, data_received…
joinRoom, publish, play, sendData, switchVideoCameraCapture, enableStats…
cambiá cámara o micrófono al vuelo y ajustá el bitrate por emisor, en vivo
chat y reacciones viajan por DataPackets de LiveKit; canPublishData va en cada token
LiveKit maneja simulcast y streaming adaptativo de forma nativa. Para producción, emití los tokens del lado del server y pasá token + wsUrl para que el token de administración nunca llegue al navegador.
StreamHub es 100% open source y self-hostable — o, si preferís, lo hosteamos nosotros. Estamos en beta, así que podés probarlo gratis mientras lo pulimos.
Cloná el repo y corré tu propio media server sobre LiveKit. Grabación a tu S3, tus apps, tus reglas. Sin lock-in.
¿No querés operar la infra? Te damos StreamHub gestionado, actualizado y monitoreado. Vos te enfocás en transmitir.
Contanos tu caso de uso — WebRTC de baja latencia, ingest RTMP/WHIP/RTSP, grabación a tu S3, restream a YouTube/Twitch o multi-tenant. Te ayudamos a arrancar, ya sea self-hosted o gestionado.
Empezá en minutos
Probá la app en vivo, sin instalar nada.
Tus datos, tu S3
Grabaciones y VOD en tu propio bucket.
Entrar a la app
app.streamhub.studio