I'm trying to seek a timestamp in an mp4 file. The procedure is as follows:
createFile and set onReady / onSamples callbacks
- Start appending chunks from the start of the file
- As soon as
onReady runs, stop appending chunks
setExtractionOptions and file.start()
- Call
file.seek(time, true) and store the offset
- Start appending chunks starting from offset and wait for
onSamples callback
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
I'm trying to seek a timestamp in an mp4 file. The procedure is as follows:
createFileand setonReady / onSamplescallbacksonReadyruns, stop appending chunkssetExtractionOptionsandfile.start()file.seek(time, true)and store the offsetonSamplescallbackI'm still pretty new to the library so if any of the above doesn't make sense, I'd appreciate the feedback.
The result
onSamples❌I think I've managed to track it down to the
seekTrackfunction. In there, there's some arithmetic done withalreadyReadvalues that areundefined. I don't fully understand whyalreadyReadis optional and what it means for it to not be defined, butnumber + undefineddoesn't feel right.The following change to
seekTrackfixed the issue for me, but it feels more like a patch to that particular function than a real fixIt 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