vjeux / mp4-h264-re-encode

Pure re-encoding of an mp4-h264 video file with the web APIs as well as in-depth description of how it works.
https://vjeux.github.io/mp4-h264-re-encode/mp4box.html
MIT License
466 stars 7 forks source link

Duration issue #14

Closed vjeux closed 1 year ago

vjeux commented 1 year ago

Repro:

What is happening on Chrome 108.0.5359.124 current prod version:

InputFrame gets to 16666 after a while but chunk is always 0.

Click to see the logs ``` inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null <3> inputFrame 16666 inputFrame null <10> inputFrame 16666 chunk 0 <14> inputFrame 16666 chunk 0 <16> inputFrame 16666 chunk 0 <15> inputFrame 16666 chunk 0 <20> inputFrame 16666 chunk 0 <16> inputFrame 16666 chunk 0 <16> inputFrame 16666 chunk 0 <14> inputFrame 16666 chunk 0 inputFrame 16666 inputFrame 21028 <2> inputFrame 16666 <269> chunk 0 ```

What is happening on Chrome 111.0.5514.0 Canary:

It is better but still not working as expected. There's no change in terms of inputFrame, but chunk eventually gets to 16666.

Click to see the logs ``` inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null inputFrame null chunk 0 inputFrame null <3> inputFrame 16666 inputFrame null <6> inputFrame 16666 chunk 0 <12> inputFrame 16666 chunk 0 <14> inputFrame 16666 chunk 0 <14> inputFrame 16666 chunk 0 <11> inputFrame 16666 chunk 0 <19> inputFrame 16666 chunk 0 <16> inputFrame 16666 chunk 0 <14> inputFrame 16666 chunk 0 <15> inputFrame 16666 chunk 0 inputFrame 16666 inputFrame 21028 <2> inputFrame 16666 <134> chunk 0 <3> chunk 16666 chunk 0 <122> chunk 16666 chunk 21028 <2> chunk 16666 ```

That said, if you always pass in the right duration to the encoder, chunk still doesn't always gets the right value.

Click to see the logs ``` <11> inputFrame 16666.666666666668 chunk 0 <12> inputFrame 16666.666666666668 chunk 0 <4> inputFrame 16666.666666666668 chunk 0 <4> inputFrame 16666.666666666668 chunk 0 <4> inputFrame 16666.666666666668 chunk 0 <4> inputFrame 16666.666666666668 chunk 0 <4> inputFrame 16666.666666666668 chunk 0 <4> inputFrame 16666.666666666668 chunk 0 <4> inputFrame 16666.666666666668 chunk 0 <4> inputFrame 16666.666666666668 chunk 0 <4> inputFrame 16666.666666666668 chunk 0 <4> inputFrame 16666.666666666668 chunk 0 <4> inputFrame 16666.666666666668 chunk 0 <4> inputFrame 16666.666666666668 chunk 0 <4> inputFrame 16666.666666666668 chunk 0 <8> inputFrame 16666.666666666668 chunk 0 <8> inputFrame 16666.666666666668 chunk 0 <12> inputFrame 16666.666666666668 chunk 0 <14> inputFrame 16666.666666666668 chunk 0 <17> inputFrame 16666.666666666668 chunk 0 <13> inputFrame 16666.666666666668 chunk 0 <18> inputFrame 16666.666666666668 chunk 0 <14> inputFrame 16666.666666666668 chunk 0 <14> inputFrame 16666.666666666668 chunk 0 <15> inputFrame 16666.666666666668 chunk 0 <16> inputFrame 16666.666666666668 chunk 0 <19> inputFrame 16666.666666666668 chunk 0 <16> inputFrame 16666.666666666668 chunk 0 <15> inputFrame 16666.666666666668 chunk 0 <16> inputFrame 16666.666666666668 chunk 0 <11> inputFrame 16666.666666666668 inputFrame 21028.645833333332 <143> chunk 0 <3> chunk 16666 chunk 0 <122> chunk 16666 chunk 21028 <2> chunk 16666 ```
diff --git a/mp4box.html b/mp4box.html
index 331fc1e..e1e56ca 100644
--- a/mp4box.html
+++ b/mp4box.html
@@ -24,12 +24,14 @@ async function reencode(file) {
       async output(inputFrame) {
         const bitmap = await createImageBitmap(inputFrame);

-        console.log('inputFrame', inputFrame.duration);
+        const sampleDuration = sampleDurations.shift();
+        console.log('inputFrame', sampleDuration);
         const outputFrame = new VideoFrame(bitmap, {
           timestamp: inputFrame.timestamp,
           duration: inputFrame.duration,
         });

+
         const keyFrameEveryHowManySeconds = 2;
         let keyFrame = false;
         if (inputFrame.timestamp >= nextKeyFrameTimestamp) {
@@ -88,7 +90,7 @@ async function reencode(file) {
           });
         }

-        const sampleDuration = sampleDurations.shift() / (1_000_000 / timescale);
+        const sampleDuration = chunk.duration / (1_000_000 / timescale);
         mp4boxOutputFile.addSample(trackID, uint8, {
           duration: sampleDuration,
           is_sync: chunk.type === 'key',
vjeux commented 1 year ago

cc @dalecurtis

dalecurtis commented 1 year ago

The "always pass the right duration" code seems incorrect. You log sampleDuration but still set inputFrame.duration as duration on the input VideoFrame -- is that just a typo or is that how the logs were generated?

vjeux commented 1 year ago

Moved to https://bugs.chromium.org/p/chromium/issues/detail?id=1405606