new Socket
src/mediaudp.ts:171new Socket(mediaGateway: Socket)The encrypted UDP transport that sends and receives voice packets.
import { MediaUdp } from 'detritus-client-socket';
MediaUdp.Socket;new Socket(mediaGateway: Socket)_sendFrame(packet: Buffer, type: string, options?: FrameOptions): voidconnect(ip?: string | null, port?: number | null): SocketdeleteFrameAssembler(ssrc: number): voiddisconnect(): voidemitRTPError(
event: string,
message: string,
from: UDPFrom,
packet: Buffer,
rtp?: RTPPayload,
): voidOnly builds the error (and its stack trace) when something listens for it, dropped packets can come in at hundreds a second
getCodecs(): MediaCodecDescription[]What we can send and receive, the voice server picks the video codec we send from these (lower priority goes first)
on(event: string | symbol, listener: (...args: any[]) => void): thisAdds 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
// aThe callback function
on(event: "close", listener: () => any): thison(event: "killed", listener: () => any): thison(event: "log", listener: (error: Error) => any): thison(event: "open", listener: () => any): thison(event: "frame", listener: (frame: TransportFrame) => any): thison(event: "keyframeRequest", listener: (request: { ssrc: number }) => any): thison(event: "videoCodec", listener: (codec: MediaCodecs) => any): thison(event: "packet", listener: (packet: TransportPacket) => any): thison(event: "ready", listener: () => any): thison(event: "socket", listener: (socket: Socket) => any): thison(event: "warn", listener: (error: Error) => any): thisonPacket(packet: Buffer, from: UDPFrom): voidonRTCPFeedback(packetType: number, format: number, packet: Buffer): voidonRTCPPacket(packet: Buffer, from: UDPFrom): voidrtpsize 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
onSend(error: any, bytes: number): voidonVideoPacket(
codec: MediaCodecs,
ssrc: number,
sequence: number,
timestamp: number,
marker: boolean,
data: Buffer,
userId: string | null,
): voidrequestKeyframe(ssrc: number, force?: boolean): voidAsks the sender of a video stream for a keyframe (rtcp picture loss indication), at most every 500ms per stream
retransmit(sequences: number[]): voidRFC 4588, resends the packets viewers nack'd on our retransmission stream
send(packet: Buffer): voidsendAudioFrame(packet: Buffer, options?: FrameOptions): voidsendAudioSilenceFrame(): voidsendFeedback(
packetType: RTCPPacketTypes,
format: number,
mediaSSRC: number,
fci?: Buffer,
): voidRFC 4585 Section 6.1, a feedback message about one of the streams we receive
sendFrame(packet: Buffer, options?: FrameOptions): voidsendNack(mediaSSRC: number, sequences: number[]): voidRFC 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(mediaSSRC: number): voidRFC 4585 Section 6.3.1
sendVideo(
frame: Buffer,
options: { codec?: string; keyframe?: boolean; timestamp: number },
): booleanSends 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
sendVideoFrame(packet: Buffer, options?: FrameOptions): voidsetAudioCodec(codec?: string | null): SocketsetKey(value: number[]): SocketsetMode(value: string): SocketsetPreferredVideoCodec(codec: string): SocketAsks 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
setSSRC(value: number): SocketsetTransportId(value: string): SocketsetVideoCodec(codec?: string | null): SocketstartKeepAlive(): void