fix: audio from video files not being exported

This commit is contained in:
Maze Winther
2026-02-23 06:20:11 +01:00
parent 93d1e3383c
commit 71970d5f5f
+61 -18
View File
@@ -71,27 +71,54 @@ export async function collectAudioElements({
if (canTracktHaveAudio(track) && track.muted) continue; if (canTracktHaveAudio(track) && track.muted) continue;
for (const element of track.elements) { for (const element of track.elements) {
if (element.type !== "audio") continue; if (!canElementHaveAudio(element)) continue;
if (element.duration <= 0) continue; if (element.duration <= 0) continue;
const isTrackMuted = canTracktHaveAudio(track) && track.muted; const isTrackMuted = canTracktHaveAudio(track) && track.muted;
pendingElements.push(
resolveAudioBufferForElement({ if (element.type === "audio") {
element, pendingElements.push(
mediaMap, resolveAudioBufferForElement({
audioContext, element,
}).then((audioBuffer) => { mediaMap,
if (!audioBuffer) return null; audioContext,
return { }).then((audioBuffer) => {
buffer: audioBuffer, if (!audioBuffer) return null;
startTime: element.startTime, return {
duration: element.duration, buffer: audioBuffer,
trimStart: element.trimStart, startTime: element.startTime,
trimEnd: element.trimEnd, duration: element.duration,
muted: element.muted || isTrackMuted, trimStart: element.trimStart,
}; trimEnd: element.trimEnd,
}), muted: element.muted || isTrackMuted,
); };
}),
);
continue;
}
if (element.type === "video") {
const mediaAsset = mediaMap.get(element.mediaId);
if (!mediaAsset || !mediaSupportsAudio({ media: mediaAsset })) continue;
pendingElements.push(
resolveAudioBufferForVideoElement({
mediaAsset,
audioContext,
}).then((audioBuffer) => {
if (!audioBuffer) return null;
const elementMuted = element.muted ?? false;
return {
buffer: audioBuffer,
startTime: element.startTime,
duration: element.duration,
trimStart: element.trimStart,
trimEnd: element.trimEnd,
muted: elementMuted || isTrackMuted,
};
}),
);
}
} }
} }
@@ -136,6 +163,22 @@ async function resolveAudioBufferForElement({
} }
} }
async function resolveAudioBufferForVideoElement({
mediaAsset,
audioContext,
}: {
mediaAsset: MediaAsset;
audioContext: AudioContext;
}): Promise<AudioBuffer | null> {
try {
const arrayBuffer = await mediaAsset.file.arrayBuffer();
return await audioContext.decodeAudioData(arrayBuffer.slice(0));
} catch (error) {
console.warn("Failed to decode video audio:", error);
return null;
}
}
interface AudioMixSource { interface AudioMixSource {
file: File; file: File;
startTime: number; startTime: number;