From ef9e24360950fec3d663d5c91aafdcd0550e3af8 Mon Sep 17 00:00:00 2001 From: asepharyana Date: Wed, 12 Aug 2026 11:37:04 +0700 Subject: [PATCH] fix(goLive): encode H264 baseline to match SDP profile-level-id (black tile) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SDP offer advertises profile-level-id=42e01f (constrained baseline) but x264 encoded the default High profile — Discord's receiver configures its decoder from the negotiated profile, so the High-profile bitstream failed to decode → black GoLive tile despite valid access units + correct RTP timestamps (fixed in 42a503c). - Add -profile:v baseline to H264 encoder options (matches @dank074's proven config; SPS now 6742c01e → profile_idc=66 baseline, aligns with the 42e01f fmtp). - Default x264 tune film → zerolatency (no lookahead — correct for live GoLive; @dank074 uses it). - Update goLive-port test to assert baseline + zerolatency. --- services/discord-gateway/src/goLive/Encoders.ts | 15 +++++++++++++-- .../discord-gateway/tests/goLive-port.test.ts | 7 +++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/services/discord-gateway/src/goLive/Encoders.ts b/services/discord-gateway/src/goLive/Encoders.ts index 44296c6..8879cd1 100644 --- a/services/discord-gateway/src/goLive/Encoders.ts +++ b/services/discord-gateway/src/goLive/Encoders.ts @@ -26,13 +26,24 @@ export function software( } = {}, ): () => EncoderSet { const { x264, x265 } = opts; - const { preset: x264Preset = "superfast", tune: x264Tune = "film" } = + const { preset: x264Preset = "superfast", tune: x264Tune = "zerolatency" } = x264 ?? {}; const { preset: x265Preset = "superfast", tune: x265Tune } = x265 ?? {}; return () => ({ H264: { name: "libx264", - options: ["-forced-idr 1", `-tune ${x264Tune}`, `-preset ${x264Preset}`], + // -profile:v baseline is REQUIRED: the SDP advertises + // profile-level-id=42e01f (constrained baseline) and Discord's + // receiver decodes with that profile. x264's default is High — a + // High-profile bitstream against a baseline SDP negotiation fails to + // decode → black GoLive tile (production bug, fixed 2026-08-12). + // zerolatency matches @dank074 (no lookahead — correct for live). + options: [ + "-forced-idr 1", + "-profile:v baseline", + `-tune ${x264Tune}`, + `-preset ${x264Preset}`, + ], }, H265: { name: "libx265", diff --git a/services/discord-gateway/tests/goLive-port.test.ts b/services/discord-gateway/tests/goLive-port.test.ts index a7210f1..11ddc05 100644 --- a/services/discord-gateway/tests/goLive-port.test.ts +++ b/services/discord-gateway/tests/goLive-port.test.ts @@ -22,11 +22,14 @@ describe("goLive port: codec + encoders", () => { expect(normalizeVideoCodec("av1")).toBe("AV1"); }); - it("software encoder exposes x264 libx264 superfast film", () => { + it("software encoder exposes x264 libx264 baseline zerolatency", () => { const enc = Encoders.software()(); expect(enc.H264.name).toBe("libx264"); expect(enc.H264.options).toContain("-preset superfast"); - expect(enc.H264.options).toContain("-tune film"); + expect(enc.H264.options).toContain("-tune zerolatency"); + // Baseline profile is REQUIRED to match the SDP's profile-level-id=42e01f + // (constrained baseline) — High-profile bitstreams fail to decode → black + expect(enc.H264.options).toContain("-profile:v baseline"); }); it("CodecPayloadType has opus + H264 entries", () => {