npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@seydx/rtsp

v0.0.7

Published

RTSP media relay that fans out a single upstream source to many consumers (RTSP server, FFmpeg, raw callbacks) with two-way audio support

Readme

@seydx/rtsp

npm version npm downloads License: MIT TypeScript

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.

Documentation

Table of Contents

Installation

npm install @seydx/rtsp node-av

It ships the prebuilt FFmpeg binaries, so no separate FFmpeg install is needed.

Quick Start

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.

Sources

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.

Sinks

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.

Two-Way Audio

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 },
});

Lifecycle

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

Examples

Runnable examples live in examples/. Run any with tsx:

tsx examples/basic-relay.ts rtsp://user:pass@cam/stream

License

MIT