fix audio exporting with microphone and system sound etc

This commit is contained in:
Alan Trebugeais
2026-05-09 19:43:54 +02:00
parent 561090a473
commit 5e5dd7166e
4 changed files with 49 additions and 17 deletions
-1
View File
@@ -24,7 +24,6 @@ import {
import type { AudioSyncAdjustment } from "../types";
import { moveFileWithOverwrite } from "../utils";
import {
RECORDING_AUDIO_SIDECAR_DEBUG_ENV,
shouldKeepRecordingAudioSidecars,
WINDOWS_NATIVE_MIC_PRE_FILTERS,
} from "./audioFilters";
+24 -14
View File
@@ -25,6 +25,18 @@ const OFFLINE_ENCODE_CHUNK_FRAMES = 1024;
const OFFLINE_CHUNK_DURATION_SEC = 30;
const USER_AUDIO_NORMALIZE_GAIN = 1.35;
function resolveSourceTrackGain(
sourceAudioTrackSettings: SourceAudioTrackSettings | undefined,
trackId: "mic" | "system" | "mixed",
) {
const settings = sourceAudioTrackSettings?.[trackId];
if (!settings) {
return 1;
}
const normalizeGain = settings.normalize ? USER_AUDIO_NORMALIZE_GAIN : 1;
return Math.max(0, Math.min(2, settings.volume * normalizeGain));
}
interface TimelineSlice {
sourceStartMs: number;
sourceEndMs: number;
@@ -607,17 +619,19 @@ export class AudioProcessor {
sourceAudioFallbackPaths,
audioRegions,
sourceTrackGainById: {
mic: Math.max(0, Math.min(2, sourceAudioTrackSettings?.mic?.volume ?? 1)),
system: Math.max(0, Math.min(2, sourceAudioTrackSettings?.system?.volume ?? 1)),
mixed: Math.max(0, Math.min(2, sourceAudioTrackSettings?.mixed?.volume ?? 1)),
mic: resolveSourceTrackGain(sourceAudioTrackSettings, "mic"),
system: resolveSourceTrackGain(sourceAudioTrackSettings, "system"),
mixed: resolveSourceTrackGain(sourceAudioTrackSettings, "mixed"),
},
embeddedGain: Math.max(
0,
Math.min(
2,
sourceAudioTrackSettings?.mixed?.volume ??
sourceAudioTrackSettings?.system?.volume ??
1,
sourceAudioTrackSettings?.mixed
? resolveSourceTrackGain(sourceAudioTrackSettings, "mixed")
: sourceAudioTrackSettings?.system
? resolveSourceTrackGain(sourceAudioTrackSettings, "system")
: 1,
),
),
});
@@ -626,11 +640,7 @@ export class AudioProcessor {
const mainBuffer = resolvedPlan.includeEmbeddedInExport
? await this.decodeAudioFromUrl(videoUrl)
: null;
const mainBufferGainSettings =
sourceAudioTrackSettings?.mixed ?? sourceAudioTrackSettings?.system ?? null;
const mainBufferGain = mainBufferGainSettings
? Math.max(0, Math.min(2, mainBufferGainSettings.volume))
: 1;
const mainBufferGain = resolveSourceTrackGain(sourceAudioTrackSettings, "mixed");
const mainBufferEntry = mainBuffer ? { buffer: mainBuffer, gain: mainBufferGain } : null;
if (this.cancelled) throw new Error("Export cancelled");
@@ -647,9 +657,9 @@ export class AudioProcessor {
companionEntries.push({
buffer,
gain: Math.max(
0,
Math.min(2, sourceAudioTrackSettings?.[getSourceTrackIdFromPath(audioPath)]?.volume ?? 1),
gain: resolveSourceTrackGain(
sourceAudioTrackSettings,
getSourceTrackIdFromPath(audioPath),
),
startDelaySec: estimateCompanionAudioStartDelaySeconds(
refDuration,
+12 -1
View File
@@ -169,6 +169,16 @@ type NativeAudioPlan =
};
const FILTERGRAPH_FALLBACK_AUDIO_SAMPLE_RATE = 48_000;
function hasNonDefaultSourceTrackSettings(sourceAudioTrackSettings?: SourceAudioTrackSettings) {
if (!sourceAudioTrackSettings) {
return false;
}
return Object.values(sourceAudioTrackSettings).some(
(settings) =>
Math.abs((settings?.volume ?? 1) - 1) > 0.0005 || Boolean(settings?.normalize),
);
}
const MIN_NATIVE_STATIC_LAYOUT_SPEED = 0.25;
const MAX_NATIVE_STATIC_LAYOUT_SPEED = 30;
@@ -1184,7 +1194,8 @@ export class ModernVideoExporter {
speedRegions.length > 0 ||
audioRegions.length > 0 ||
sourceAudioFallbackPaths.length > 1 ||
hasTimedSourceAudioFallback
hasTimedSourceAudioFallback ||
hasNonDefaultSourceTrackSettings(this.config.sourceAudioTrackSettings)
) {
const sourceDurationMs = Math.max(
0,
+13 -1
View File
@@ -123,6 +123,16 @@ type NativeAudioPlan =
const FILTERGRAPH_FALLBACK_AUDIO_SAMPLE_RATE = 48_000;
function hasNonDefaultSourceTrackSettings(sourceAudioTrackSettings?: SourceAudioTrackSettings) {
if (!sourceAudioTrackSettings) {
return false;
}
return Object.values(sourceAudioTrackSettings).some(
(settings) =>
Math.abs((settings?.volume ?? 1) - 1) > 0.0005 || Boolean(settings?.normalize),
);
}
export class VideoExporter {
private config: VideoExporterConfig;
private streamingDecoder: StreamingVideoDecoder | null = null;
@@ -563,7 +573,8 @@ export class VideoExporter {
speedRegions.length > 0 ||
audioRegions.length > 0 ||
sourceAudioFallbackPaths.length > 1 ||
hasTimedSourceAudioFallback
hasTimedSourceAudioFallback ||
hasNonDefaultSourceTrackSettings(this.config.sourceAudioTrackSettings)
) {
const sourceDurationMs = Math.max(
0,
@@ -947,6 +958,7 @@ export class VideoExporter {
this.config.audioRegions,
this.config.sourceAudioFallbackPaths,
this.config.sourceAudioFallbackStartDelayMsByPath,
this.config.sourceAudioTrackSettings,
),
"ffmpeg edited audio rendering",
"audio",