perf(golive/spike): binding addTrack + TS port of @dank074 media stack

Phase 1 spike: replace @dank074/discord-video-stream + node-datachannel +
node-av (1.3GB) with minimal libdatachannel N-API binding + native RTP
packetizers (H264 FU-A, RTCP SR/NACK, pacer) + pure-TS GoLive stack.

Binding v0.4: addTrack (m=audio/video SDP), TrackWrap w/ setPacketizer +
sendFrame (raw RTP to transport) + addTimestamp — verified by two-peer
handshake emitting SDP with audio(opus 120)+video(H264 101) and 8-frame
RTP roundtrip.

TS layer (src/goLive/, 21 files): CodecPayloadType, VoiceOpCodes,
GatewayOpCodes, utils, BaseMediaConnection (voice WS + DAVE + heartbeat),
VoiceConnection, StreamConnection, Streamer, WebRtcWrapper (SDP mungling,
DAVE encrypt, packetizer chain), BaseMediaStream (pacing/sync), VideoStream,
AudioStream, Demuxer (ffmpeg-spawn NUT/AnnexB, no node-av 114M binary),
Encoders, prepareStream/playStream.

Integration: screenShareController.ts now imports from ../../goLive/index.js —
prepareStream(prepared, ...) + playStream(prepared, streamer, {...}).

Tests: tests/goLive-port.test.ts (8/8 pass). tsc --noEmit clean. biome clean.
This commit is contained in:
asepharyana
2026-08-11 16:16:52 +07:00
parent a1a6d8b418
commit 9ae230d047
22 changed files with 3026 additions and 17 deletions
@@ -0,0 +1,25 @@
/**
* VoiceConnection — guild/DM voice channel GoLive connection.
* Ported from @dank074/discord-video-stream VoiceConnection.js.
*/
import { BaseMediaConnection } from "./BaseMediaConnection.js";
import type { StreamConnection } from "./StreamConnection.js";
export class VoiceConnection extends BaseMediaConnection {
streamConnection: StreamConnection | null = null;
get daveChannelId(): string {
return this.channelId;
}
get serverId(): string | null {
// for guild vc it is the guild id, for dm voice it is the channel id
return this.guildId ?? this.channelId;
}
stop(): void {
super.stop();
this.streamConnection?.stop();
}
}