mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 09:16:55 +00:00
fix(engine): a muted video no longer plays at full volume in renders that skip the browser probe (#6044)
* fix(engine): a muted video no longer plays at full volume in renders that skip the browser probe A <video data-has-audio="true" muted> with an audio stream is silent in preview and in renders that run the browser probe, but a render that skipped the probe mixed it at volume 1.0, ignoring data-volume. The audio parser drops muted videos; the video parser kept hasAudio from data-has-audio alone, so the auto-detect fallback re-added the sound. The video parser now asks the same isAudibleVideoElement check. * style(producer): format the muted-video parity test
This commit is contained in:
@@ -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 }
|
||||
|
||||
@@ -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 = `<div data-composition-id="root" data-start="0" data-duration="4">
|
||||
<video id="quiet" src="quiet.mp4" data-start="0" data-duration="4" data-has-audio="true" data-volume="0.72" muted></video>
|
||||
<video id="voice" src="voice.mp4" data-start="0" data-duration="4" data-has-audio="true" data-volume="0.5"></video>
|
||||
<audio id="music" src="music.mp3" data-start="0" data-duration="4" data-volume="0.19"></audio>
|
||||
</div>`;
|
||||
// Both files carry an audio stream, so the auto-detect fallback would add any video the parsers miss.
|
||||
const extracted = ["quiet", "voice"].map((videoId) => ({
|
||||
videoId,
|
||||
metadata: { hasAudio: true },
|
||||
}));
|
||||
|
||||
for (const probed of [false, true]) {
|
||||
it(`stays out of the mix ${probed ? "after" : "without"} the browser probe`, () => {
|
||||
const composition = collectRenderMedia(html);
|
||||
if (probed) {
|
||||
pruneMutedBrowserMedia(composition, [
|
||||
{ id: "quiet", tagName: "video", muted: true },
|
||||
{ id: "voice", tagName: "video", muted: false },
|
||||
{ id: "music", tagName: "audio", muted: false },
|
||||
]);
|
||||
}
|
||||
appendAutoDetectedVideoAudio(
|
||||
composition,
|
||||
extracted as unknown as Parameters<typeof appendAutoDetectedVideoAudio>[1],
|
||||
);
|
||||
|
||||
expect(composition.audios.map(({ id, volume }) => [id, volume])).toEqual([
|
||||
["music", 0.19],
|
||||
["voice-audio", 0.5],
|
||||
]);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user