diff --git a/packages/engine/src/services/videoFrameExtractor.ts b/packages/engine/src/services/videoFrameExtractor.ts index b0015b3ae3..296e9e47b4 100644 --- a/packages/engine/src/services/videoFrameExtractor.ts +++ b/packages/engine/src/services/videoFrameExtractor.ts @@ -768,7 +768,7 @@ export function parseVideoElements(html: string): VideoElement[] { mediaStart: readMediaStart(el), playbackRate: readElementRateSpec(el), loop: el.hasAttribute("loop"), - hasAudio: hasAudioAttr === "true", + hasAudio: hasAudioAttr === "true" && isAudibleVideoElement(el), ...(isSelfOrAncestorHidden(el) || (isAudibleVideoElement(el) && isMemberGroupHidden(groupsById, el)) ? { hidden: true } diff --git a/packages/producer/src/services/render/stages/mutedParity.test.ts b/packages/producer/src/services/render/stages/mutedParity.test.ts index 6fff334819..b4f67a697f 100644 --- a/packages/producer/src/services/render/stages/mutedParity.test.ts +++ b/packages/producer/src/services/render/stages/mutedParity.test.ts @@ -1,5 +1,7 @@ import { describe, expect, it } from "bun:test"; import { pruneMutedBrowserMedia } from "./probeStage.js"; +import { appendAutoDetectedVideoAudio } from "./extractVideosStage.js"; +import { collectRenderMedia } from "../../renderMediaCollector.js"; describe("pruneMutedBrowserMedia", () => { it("drops muted audio from the mix and clears hasAudio on muted video", () => { @@ -36,3 +38,38 @@ describe("pruneMutedBrowserMedia", () => { expect(composition.videos[0]?.hasAudio).toBe(true); }); }); + +describe("a muted video's sound in the mix", () => { + const html = `