ffmpeg concat demuxer dies with "Error sending frames to consumers:
Invalid argument" when input segments don't share codec / pixel format
/ framerate / resolution. Mixed-source timelines hit this every time —
e.g. an AV1 clip + an H.264 clip going through the same concat.
Switch to the concat *filter*. It re-encodes through a filter graph
so disparate inputs are normalised inline. Each input is scaled to
1920x1080 with letterbox, format=yuv420p, audio resampled. concat=n=N
joins them into [outv]/[outa].
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Three cooperating bugs left the rendered output silent and in the
wrong codec:
1. executor.js trimSegment used `-frames:v` with no audio mapping.
ffmpeg dropped the audio track on each segment before they reached
the concat step. Add `-c:a copy -shortest` so each segment carries
its original audio.
2. conform.js audioFlag was `audio === 'include' ? aac : -an`. The
panel's v2.2.1 defaults send `audio: 'broadcast'`, which didn't
match 'include' → `-an` explicitly stripped audio at the encode
step. Switch to the opposite default: only an explicit 'none' or
'off' disables audio; everything else gets AAC 320k @ 48kHz.
3. conform.js video codec map only matched `codec === 'prores'`. The
panel sends `'prores_hq'` (and the conform slide panel can send
`'prores_4444'` / `'dnxhr_hq'`). All of those fell through to
libx264 and silently rendered H.264 instead of the requested codec.
Add a real codec map with the right prores_ks profiles (3=HQ,
4=4444) and DNxHR. Skip -crf for ProRes since the profile encodes
quality.
The asset-row metadata's `codec` column is normalised the same way so
the new asset record matches what was actually written.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Panel had been sending xmeml with clipitem/name = the local Premiere
file path's basename (e.g. "dragonflight-Interstellar - Docking Scene
1080p IMAX HD.mp4"). The worker's old filename lookup ran
SELECT id, original_s3_key FROM assets WHERE filename = $1
which never matched, because the assets row's filename is the
original MAM ingest name without the "dragonflight-" prefix.
Fix: when job.data has sequenceId (always set by the conform endpoint
at routes/sequences.js:317), pull edits directly from sequence_clips,
which the panel already wrote with authoritative asset_id mappings on
push. We JOIN to assets for original_s3_key + filename and order by
(timeline_in_frames, track) so segment indices stay deterministic.
The XML is still parsed for sequence-level metadata (name, fps) when
provided, but its clipitems are no longer authoritative.
The legacy filename path (EDL input or fcpXml without sequenceId)
stays unchanged for backward compatibility.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
track?.@_currentExplodedTrackIndex is invalid JS syntax — @ is not a
valid identifier character. Replaced with track?.['@_currentExplodedTrackIndex']
so the worker process no longer crashes on startup.
The jobs table row no longer exists for conform jobs (POST /jobs/conform
now goes directly to BullMQ). The UPDATE queries were no-ops (WHERE id = NULL)
so they're safe to remove. BullMQ tracks completed/failed status itself.