-
Notifications
You must be signed in to change notification settings - Fork 373
Description
I'm trying to seek a timestamp in an mp4 file. The procedure is as follows:
createFileand setonReady / onSamplescallbacks- Start appending chunks from the start of the file
- As soon as
onReadyruns, stop appending chunks setExtractionOptionsandfile.start()- Call
file.seek(time, true)and store the offset - Start appending chunks starting from offset and wait for
onSamplescallback
I'm still pretty new to the library so if any of the above doesn't make sense, I'd appreciate the feedback.
The result
- If the file is not fragmented, everything works fine ✅
- If the file is fragmented:
- If I feed tiny chunks to the file, it works, but I haven't delved too deep into why that is ✅
- If I feed reasonably sized chunks (64kb), it doesn't work. I get no calls to
onSamples❌
I think I've managed to track it down to the seekTrack function. In there, there's some arithmetic done with alreadyRead values that are undefined. I don't fully understand why alreadyRead is optional and what it means for it to not be defined, but number + undefined doesn't feel right.
The following change to seekTrack fixed the issue for me, but it feels more like a patch to that particular function than a real fix
MP4Box.ISOFile.prototype.seekTrack = function (time, useRap, trak) {
let rap_seek_sample_num = 0;
let seek_sample_num = 0;
let timescale;
if (trak.samples.length === 0) {
return { offset: 0, time: 0 };
}
for (let j = 0; j < trak.samples.length; j++) {
const sample = trak.samples[j];
if (j === 0) {
seek_sample_num = 0;
timescale = sample.timescale;
} else if (sample.cts > time * sample.timescale) {
seek_sample_num = j - 1;
break;
}
if (useRap && sample.is_sync) {
rap_seek_sample_num = j;
}
}
if (useRap) {
seek_sample_num = rap_seek_sample_num;
}
time = trak.samples[seek_sample_num].cts;
trak.nextSample = seek_sample_num;
// ========================================= Original =========================================
while (trak.samples[seek_sample_num].alreadyRead === trak.samples[seek_sample_num].size) {
if (!trak.samples[seek_sample_num + 1]) {
break;
}
seek_sample_num++;
}
const seek_offset = trak.samples[seek_sample_num].offset + trak.samples[seek_sample_num].alreadyRead;
return { offset: seek_offset, time: time / timescale };
// ========================================= Original =========================================
// ========================================= My version =========================================
let alreadyRead = trak.samples[seek_sample_num].alreadyRead ?? 0;
while (alreadyRead === trak.samples[seek_sample_num].size) {
if (!trak.samples[seek_sample_num + 1]) {
break;
}
seek_sample_num++;
alreadyRead = trak.samples[seek_sample_num].alreadyRead ?? 0;
}
const seek_offset = trak.samples[seek_sample_num].offset + alreadyRead;
return { offset: seek_offset, time: time / timescale };
// ========================================= My version =========================================
}It would be great to get some clarity on whether this is an actual bug, and whether the library supports seeking fragmented files altogether.
Thank you 😃
P.S this happens to me with pretty much every fragmented file, but here's one that fails for reference https://drive.google.com/file/d/1OgxDcNcQPJ4MlmW9tN08RjJzVQ0l2CQG/view?usp=sharing