Audio copy fast path is unreachable for AAC because priming delay makes firstTimestamp negative #467
Replies: 2 comments 1 reply
|
Yes, this is a known gap and I will fix this in the future properly, across all containers and codecs. |
|
Confirming the workaround from #482 works, with byte-level numbers in case they help anyone landing here.
Both elementary streams come back identical to the source, and the packet counts match (150 video / 217 audio; without the trim the audio gains two packets). Output duration goes 5.000 → 5.023 s, i.e. the 1024-sample priming delay is preserved rather than flattened — without the trim it drifts to 5.085 s. One note for anyone applying this: const first = await input.getFirstTimestamp();
const conversion = await Conversion.init({
input, output, tracks: 'all', video: {}, audio: {},
...(first < 0 ? { trim: { start: first } } : {}),
});Thanks for the pointer — that turns a 6% regression into a real copy today, and it's a good enough answer that the proper cross-container fix doesn't need to be rushed on my account. |
Uh oh!
There was an error while loading. Please reload this page.
I have been using Conversion to pass files through without re-encoding when the
source already meets the target. Video copies correctly. Audio never does, and
I think the reason is structural rather than a bug in my usage.
The copy fast path in conversion.js requires
!needsTrimming, whereneedsTrimmingisfirstTimestamp < this._startTimestamp. For an ordinary MP4produced by ffmpeg:
0.0232 s at 44100 Hz is 1024 samples, exactly one AAC frame. That is encoder
priming delay, and as far as I know every AAC track from every normal encoder
carries it. So
needsTrimmingis true for essentially all AAC input and thecopy path is never taken.
The visible effect is that a passthrough grows the file. Parsing the output:
The audio was re-encoded at roughly 191 kbps from a 96 kbps source, and a
3.3 MB input came back at 3.6 MB. On the low bitrate files a passthrough is
most useful for, that is around 10 percent.
I could not find a way around it from the caller's side. Passing a bitrate to
control the size forces a transcode on its own, since
!trackOptions.bitrateisalso one of the copy conditions, so the choice is between an uncontrolled
re-encode and an uncontrolled re-encode. I ended up adding a floor in my own
code: if a passthrough returns more bytes than it received and the source is
already MP4, return the source untouched.
Is treating a negative first timestamp caused by priming delay as trimming
intentional? If the priming offset could be carried into the output as an edit
list instead, the copy path would open up for a large share of real world MP4s.
Repro is any ffmpeg produced
-c:a aacfile. If a live example helps, thebrowser side compressor I hit this in is public,
and the passthrough case is easiest to trigger on an already small clip such as
the one on the compress video to 10 MB
page.
All reactions