
Product
Introducing Repository Access Permissions and Custom Roles
Socket now supports Custom Roles and Repository Access Permissions so organizations can control who can access specific repositories and actions.
@seydx/rtsp
Advanced tools
RTSP media relay that fans out a single upstream source to many consumers (RTSP server, FFmpeg, raw callbacks) with two-way audio support
A small, modern media relay: connect one upstream source and fan it out to many consumers — the source only ever holds a single connection.
Source ──▶ Relay (fan-out hub) ──▶ Sink…
├─ RTSP server (many rtsp:// pullers)
├─ FFmpeg (transcode / remux)
└─ Callback (raw packets)
All codec and protocol heavy-lifting is delegated to node-av; this package is the orchestration layer plus a lean multi-client RTSP server.
npm install @seydx/rtsp node-av
It ships the prebuilt FFmpeg binaries, so no separate FFmpeg install is needed.
import { Relay, CallbackSink, FfmpegSink } from '@seydx/rtsp';
import { AvSource } from '@seydx/rtsp/sources';
const relay = new Relay({
source: new AvSource('rtsp://user:pass@cam/stream', { transport: 'tcp' }),
idleTimeout: 5_000, // tear down the upstream when the last sink leaves
});
// Fan out to many RTSP pullers from a single upstream connection.
const server = await relay.serveRtsp({ path: 'live' });
console.log(server.url); // rtsp://127.0.0.1:<port>/live
// …or pipe to ffmpeg / a raw callback.
relay.pipe(new FfmpegSink({ output: 'out.ts', format: 'mpegts' }));
relay.pipe(new CallbackSink({ onPacket: (packet) => {/* raw packets */} }));
The upstream is lazy: it opens on the first sink and, after idleTimeout, closes once the last sink leaves.
A source is a single-connection upstream. Two are built in (importable from @seydx/rtsp/sources):
AvSource — a node-av-backed demuxer for RTSP, files, and byte streams. Supports transport selection, read-rate pacing, looping, and the ONVIF backchannel.MultiSource — merges several inputs (e.g. a camera that exposes audio and video as separate streams) into one flattened multi-track source.import { MultiSource } from '@seydx/rtsp/sources';
const source = new MultiSource([
{ input: 'rtsp://cam/video' },
{ input: 'rtsp://cam/audio' },
]);
Implement the Source contract to add your own.
A sink consumes the relayed stream. Three are built in (importable from @seydx/rtsp/sinks):
RtspServerSink — re-serves the relay as a multi-client rtsp:// endpoint. Created via relay.serveRtsp().FfmpegSink — remuxes the stream into another container, in-process, via a node-av muxer (stream copy, no child process).CallbackSink — delivers raw packets to your own callback.Implement the Sink contract to add your own.
Talkback (ONVIF backchannel) sends audio from a viewer back to the camera. The source must request the backchannel:
const relay = new Relay({
source: new AvSource('rtsp://cam/stream', { transport: 'tcp', backchannel: true }),
});
// Pass-through: advertise the camera's own talkback codec; forward viewer RTP as-is.
await relay.serveRtsp({ path: 'live', backchannel: true });
// …or transcode: advertise a different codec to viewers; the relay converts it
// to the camera's codec in-process.
await relay.serveRtsp({
path: 'live',
backchannel: { codec: 'opus', payloadType: 97, clockRate: 48000, channels: 2 },
});
The relay is an event emitter. A newly attached sink is held until the next keyframe so it starts on a clean GOP, and a slow sink is isolated from the rest.
relay.on('start', (info) => console.log('upstream live:', info.tracks.length, 'tracks'));
relay.on('sink:added', () => {});
relay.on('sink:removed', () => {});
relay.on('end', () => {}); // upstream ended on its own
relay.on('error', (err) => console.error(err));
await relay.stop(); // tear down the upstream and every sink
Runnable examples live in examples/. Run any with tsx:
tsx examples/basic-relay.ts rtsp://user:pass@cam/stream
MIT
FAQs
RTSP media relay that fans out a single upstream source to many consumers (RTSP server, FFmpeg, raw callbacks) with two-way audio support
We found that @seydx/rtsp demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Socket now supports Custom Roles and Repository Access Permissions so organizations can control who can access specific repositories and actions.

Product
Socket MCP now lets AI assistants review org alerts, investigate threats using the Socket threat feed, and inspect package files in addition to dependency scoring.

Product
Socket Firewall blocks malicious VS Code and Open VSX extensions before install, protecting developers from compromised editor marketplaces.