-
Notifications
You must be signed in to change notification settings - Fork 374
Description
Hello! I ran into a problem when assembling a full-fledged MP4 from a fragmented Pinterest stream. We intercept all SourceBuffer.appendBuffer calls on the page and collect them into one ArrayBuffer, which we pass to mp4box.js for analysis and subsequent remultiplexing. MP4BOX stack trace:
TypeError: Cannot read properties of undefined (reading 'mdia')
at ISOFile.updateSampleLists (libs/mp4box.all.js:7294)
at ISOFile.appendBuffer (libs/mp4box.all.js:6332)
Contents of the captured buffer (first atoms):
offset=0 type=ftyp size=36
offset=36 type=free size=64
offset=100 type=moov size=914
offset=1014 type=ftyp size=36 ← second init-segment
offset=1050 type=free size=64
offset=1114 type=moov size=800 ← third init-segment
offset=1914 type=moof size=568
offset=2482 type=mdat size=200786
offset=203268 type=moof size=284
offset=203552 type=mdat size=16146
…
It can be seen that Pinterest sends ftyp+moov before each rather large fragment (in fact, each HLS segment begins with an init segment). After the third moov, mp4box tries to update the tables, but it encounters a trak without mdia and crashes.
Minimum code
// Chrome OffscreenDocument (Service Worker) – mp4box.js v2.1.0
import * as MP4Box from 'mp4box';
async function parseCapturedBuffer(arrayBuffer) {
const mp4box = MP4Box.createFile(true);
mp4box.onError = (e) => console.error('mp4box error', e);
mp4box.onReady = (info) => {
console.log('tracks', info.tracks.map(t => ({
id: t.id,
codec: t.codec,
nb_samples: t.nb_samples,
})));
};
const buf = arrayBuffer.slice(0);
buf.fileStart = 0;
mp4box.appendBuffer(buf); // crashes here _ISOFile.updateSampleLists
mp4box.flush();
}
What we have already checked
If you manually delete all repeated ftyp+moov and leave only the first init segment + all moof/mdat, the file is parsed correctly.
If you delay the start of the interception (wait 2 seconds before feeding the mp4box buffer), the situation does not change — Pinterest still sends init segments again, and mp4box crashes.
In the examples from examples/ mp4box, it is used on progressive MP4 or streams without a repeated init segment, so such a case is not shown there.
Questions
Is there in mp4box.is js a regular way to ignore (or automatically process) repeated ftyp/moov when we transfer the combined buffer?
Is it recommended to filter init segments manually before appendBuffer (leaving only the first ftyp+moov), or is there a more correct API for working with such a stream?
Is it possible to transfer a sequence of "pieces" to mp4box (each ArrayBuffer with its own fileStart) so that the library itself correctly builds the structure?
I use mp4box.js: 2.1.0 (mp4box.all.js)
I would be grateful for recommendations or hints on how to properly feed a stream with duplicate init segments without deleting them manually.