detritus

Socketclass

The encrypted UDP transport that sends and receives voice packets.

On this page
import { MediaUdp } from 'detritus-client-socket';

MediaUdp.Socket;
EventEmitterEventSpewerSocket
27 properties30 methodssrc/mediaudp.ts:129

Constructor

Properties

codecs
{ audio: string | null; video: string | null }
connected
boolean
frameAssemblers
Map<number, MediaFrameAssembler>
headers
{ audio: RTPHeader; rtx?: RTPHeader; video?: RTPHeader }
keepAlive
{ counter: number; interval: Interval; intervalTime: number }
key
Uint8Array<ArrayBufferLike> | null
keyframeRequests
Map<number, number>
mediaGateway
mode
string | null
nackTrackers
Map<number, MediaNackTracker>
nonces
{ audio: RTPNonce; video?: RTPNonce }
pictureId
number
preferredVideoCodec
Default null
remote
sendHistory
socket
Socket | null
ssrc
number
transportId
string | null

Accessors

audioSSRC
number
get
receiveEnabled
boolean
get
rtpAudioPayloadType
number | null
get
rtpRTXPayloadType
number | null
get
rtpVideoPayloadType
number | null
get
rtxSSRC
number
get
videoEnabled
boolean
get
videoSSRC
number
get

Methods

connect()

src/mediaudp.ts:416
connect(ip?: string | null, port?: number | null): Socket
ip?
string | null
Default null
port?
number | null
Default null

emitRTPError()

src/mediaudp.ts:1000
emitRTPError(
  event: string,
  message: string,
  from: UDPFrom,
  packet: Buffer,
  rtp?: RTPPayload,
): void

Only builds the error (and its stack trace) when something listens for it, dropped packets can come in at hundreds a second

on()

src/mediaudp.ts:1227
on(event: string | symbol, listener: (...args: any[]) => void): this

Adds the listener function to the end of the listeners array for the event named eventName. No checks are made to see if the listener has already been added. Multiple calls passing the same combination of eventName and listener will result in the listener being added, and called, multiple times.

server.on('connection', (stream) => {
  console.log('someone connected!');
});

Returns a reference to the EventEmitter, so that calls can be chained.

By default, event listeners are invoked in the order they are added. The emitter.prependListener() method can be used as an alternative to add the event listener to the beginning of the listeners array.

import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
//   b
//   a

Since v0.1.101

event
string | symbol
listener
(...args: any[]) => void

The callback function

on(event: "close", listener: () => any): this
on(event: "killed", listener: () => any): this
on(event: "log", listener: (error: Error) => any): this
on(event: "open", listener: () => any): this
on(event: "frame", listener: (frame: TransportFrame) => any): this
on(event: "keyframeRequest", listener: (request: { ssrc: number }) => any): this
on(event: "videoCodec", listener: (codec: MediaCodecs) => any): this
on(event: "packet", listener: (packet: TransportPacket) => any): this
on(event: "ready", listener: () => any): this
on(event: "socket", listener: (socket: Socket) => any): this
on(event: "warn", listener: (error: Error) => any): this
Overrides EventSpewer.on

onRTCPFeedback()

src/mediaudp.ts:922
onRTCPFeedback(packetType: number, format: number, packet: Buffer): void

onRTCPPacket()

src/mediaudp.ts:889
onRTCPPacket(packet: Buffer, from: UDPFrom): void

rtpsize modes leave the first header and sender ssrc unencrypted, everything after it (other packets of a compound packet included) is encrypted like an rtp payload

onVideoPacket()

src/mediaudp.ts:750
onVideoPacket(
  codec: MediaCodecs,
  ssrc: number,
  sequence: number,
  timestamp: number,
  marker: boolean,
  data: Buffer,
  userId: string | null,
): void

requestKeyframe()

src/mediaudp.ts:815
requestKeyframe(ssrc: number, force?: boolean): void

Asks the sender of a video stream for a keyframe (rtcp picture loss indication), at most every 500ms per stream

ssrc
number
force?
boolean
Default false

retransmit()

src/mediaudp.ts:966
retransmit(sequences: number[]): void

RFC 4588, resends the packets viewers nack'd on our retransmission stream

sendFeedback()

src/mediaudp.ts:860
sendFeedback(
  packetType: RTCPPacketTypes,
  format: number,
  mediaSSRC: number,
  fci?: Buffer,
): void

RFC 4585 Section 6.1, a feedback message about one of the streams we receive

sendNack()

src/mediaudp.ts:835
sendNack(mediaSSRC: number, sequences: number[]): void

RFC 4585 Section 6.2.1, each entry is a lost sequence number and a bitmask of which of the 16 after it are lost too

sendPictureLossIndication()

src/mediaudp.ts:828
sendPictureLossIndication(mediaSSRC: number): void

RFC 4585 Section 6.3.1

sendVideo()

src/mediaudp.ts:1077
sendVideo(
  frame: Buffer,
  options: { codec?: string; keyframe?: boolean; timestamp: number },
): boolean

Sends a whole encoded video frame (vp8/vp9, or h264 as annex b): e2e encrypts it, splits it into rtp packets and sends them with the frame's timestamp, the marker bit on the last one. Pacing is up to the caller, this sends now Returns false if it couldn't be sent, viewers can't decrypt anything before we're in the DAVE group, so the frame gets dropped then. Nothing after a dropped frame decodes until the next keyframe, check keyframe to know

frame
Buffer
options
{ codec?: string; keyframe?: boolean; timestamp: number }
options.codec?
string
options.keyframe?
boolean
options.timestamp
number

setPreferredVideoCodec()

src/mediaudp.ts:365
setPreferredVideoCodec(codec: string): Socket

Asks the voice server to have us send codec (SESSION_UPDATE), its answer comes as a videoCodec event It can still pick another one, every viewer has to be able to decode what we send