Files
GMW/services/discord-gateway/tests/goLive-port.test.ts
T
asepharyana 9ae230d047 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.
2026-08-11 16:16:52 +07:00

95 lines
3.3 KiB
TypeScript

/**
* goLive port smoke tests — verify the TS layer (no native binding needed
* for these; native is covered by the C++/node test-packetizer.js).
*/
import { describe, expect, it } from "vitest";
import { H264Helpers } from "../src/goLive/AnnexBHelper.js";
import { AVCodecID } from "../src/goLive/Demuxer.js";
import {
BaseMediaStream,
CodecPayloadType,
Encoders,
normalizeVideoCodec,
} from "../src/goLive/index.js";
import { rewriteSPSVUI } from "../src/goLive/SPSVUIRewriter.js";
describe("goLive port: codec + encoders", () => {
it("normalizeVideoCodec maps aliases to canonical names", () => {
expect(normalizeVideoCodec("H.264")).toBe("H264");
expect(normalizeVideoCodec("AVC")).toBe("H264");
expect(normalizeVideoCodec("h265")).toBe("H265");
expect(normalizeVideoCodec("vp8")).toBe("VP8");
expect(normalizeVideoCodec("av1")).toBe("AV1");
});
it("software encoder exposes x264 libx264 superfast film", () => {
const enc = Encoders.software()();
expect(enc.H264.name).toBe("libx264");
expect(enc.H264.options).toContain("-preset superfast");
expect(enc.H264.options).toContain("-tune film");
});
it("CodecPayloadType has opus + H264 entries", () => {
expect(CodecPayloadType.opus).toBeDefined();
expect(CodecPayloadType.H264).toBeDefined();
});
});
describe("goLive port: annexb + sps rewriter", () => {
it("H264Helpers detects NAL unit types", () => {
const nal = Buffer.from([0x67, 0x42, 0x00, 0x1e]); // SPS
expect(H264Helpers.getUnitType(nal)).toBe(7); // SPS type
expect(H264Helpers.getUnitType(Buffer.from([0x65, 0x88]))).toBe(5); // IDR
});
it("rewriteSPSVUI returns a buffer for valid SPS", () => {
const sps = Buffer.from([
0x67, 0x42, 0x00, 0x1e, 0x96, 0x54, 0x05, 0x01, 0xec, 0x80,
]);
expect(() => rewriteSPSVUI(sps)).not.toThrow();
});
});
describe("goLive port: streams", () => {
it("BaseMediaStream accepts plain frame objects", () => {
// BaseMediaStream is abstract — use a concrete subclass that no-ops the
// packetizer hook.
class TestStream extends BaseMediaStream {
async _sendFrame(_frame: Buffer, _frametime: number): Promise<void> {
/* no-op */
}
}
const stream = new TestStream("video");
const frame = {
data: Buffer.from([1, 2, 3]),
pts: 0,
duration: 40,
timeBase: { num: 1, den: 48000 },
flags: 0,
streamIndex: 0,
free: () => {},
};
expect(() => stream.write(frame)).not.toThrow();
stream.end();
});
});
describe("goLive port: demuxer codec ids", () => {
it("maps H264/HEVC/opus AVCodecID values", () => {
expect(AVCodecID.AV_CODEC_ID_H264).toBe(27);
expect(AVCodecID.AV_CODEC_ID_HEVC).toBe(173);
expect(AVCodecID.AV_CODEC_ID_OPUS).toBe(86019);
});
});
describe("goLive port: prepareStream option merge", () => {
it("merges default options into the descriptor (no ffmpeg spawn)", () => {
// Import the merge logic directly via the module; prepareStream spawns
// ffmpeg so we verify the descriptors it would build by checking the
// encoder + option functions that prepareStream uses.
const enc = Encoders.software()();
expect(enc.H264.options).toContain("-forced-idr 1");
expect(normalizeVideoCodec("H264")).toBe("H264");
});
});