fix: synth silence bed for audio-less produce sources

Audio-less inputs no longer emit [0:a] maps that ffmpeg rejects; the worker
branches to an anullsrc bed configured at the output preset's rate/layout.
Producer tests 42/42.
This commit is contained in:
glass beadian 2026-10-15 21:27:09 +00:00
parent 613aba236b
commit 5808e89dde
6 changed files with 130 additions and 8 deletions

View file

@ -47,6 +47,11 @@ function uuid(value: unknown, field: string): string {
return text;
}
/** True once 009's probe job has run: the probe writes duration + codecs together, so duration≠NULL means probed. */
function probed(row: Record<string, unknown>): boolean {
return row.duration_ms !== null && row.duration_ms !== undefined;
}
function nullableNumber(value: unknown): number | null {
if (value === null || value === undefined) return null;
const n = typeof value === "number" ? value : Number(value);
@ -63,9 +68,11 @@ function sourceFromRow(row: Record<string, unknown>): ProduceSourceAsset {
height: nullableNumber(row.height),
durationMs: row.duration_ms === null || row.duration_ms === undefined ? null : Math.round(Number(row.duration_ms)),
frameRate: nullableNumber(row.frame_rate),
// Probed "no audio track" (009 stores an empty codec) → a silent bed, so the
// output always has an audio stream.
hasAudio: row.audio_codec === null || row.audio_codec === undefined ? null : String(row.audio_codec) !== "",
// An unprobed asset has NULL codec AND NULL duration (009's probe fills all
// of them at once); a probed one always has a duration. So the probed
// audio-less case is duration≠NULL + audio_codec NULL/'' — which must become
// a silent bed, or the graph references [0:a] on a file with no audio track.
hasAudio: probed(row) ? String(row.audio_codec ?? "") !== "" : null,
};
}