Skip to content

create a video file encoded using WebCodecs  #243

Description

@tlecoz

Hello !

I'm trying to generate a video file using mp4box & webcodec directly inside the browser, without nodejs & ffmpeg. It almost works but my video-file contains only 2-3 frames instead of 300 and I don't understand at all what's happening.

The problem come from the mp4box part because the same code works well if I use ffmpeg (with nodejs) as a muxer instead of mp4box.

I'm not an expert at all with mp4box, muxers and stuffs like that. Few months ago I didn't even know the word "muxer" ( 😅 ) so please do not assume that I understand what is behind the hood. I'm just a web-developer , not a video-master ;)

Webcodec is not released yet. It will be released next month but you can use it now if you go to chrome://flags , then search "Experimental Web Platform features" and enable it.

More infos about webcodecs here : https://github.com/w3c/webcodecs

Here is my experimentation with mp4box (it's a minimal example, it couldn't be smaller) :

  <html>
    <script src="mp4box.all.min.js" ></script>
    <body>
        <script>
			
            let w = 1920;
            let h = 1080;
            let durationInMillisecond = 5000;
            let fps = 60;
            let frameTimeInMillisecond = 1000 / fps; 
	    let totalFrames = Math.floor(durationInMillisecond / frameTimeInMillisecond) ;
            let chunkCount = 0;
            let videoEncoder;
            let encoderClosed = false;


            //------ Mp4box setup --------

            let oneSecondInMillisecond = 1000;
            let timescale = 1000;

            let trackOptions = {
                timescale:(oneSecondInMillisecond * timescale),
                duration:(durationInMillisecond * timescale),
                width:w,
                height:h,
                nb_samples:totalFrames,
            }

            let sampleOptions = {
                duration:(frameTimeInMillisecond * timescale)
            } 

            let file = MP4Box.createFile();
            let track = file.addTrack(trackOptions);
            
            //--- WebCodec videoEncoding -----
	   async function buildAndConfigureEncoders() {
			    let videoEncoder = new VideoEncoder({
                                  output: (encodedChunk,config)=>{ 
                        
                                       file.addSample(track,new Uint8Array(encodedChunk.data),sampleOptions);
                        
                                       chunkCount++;
                                       if (chunkCount==totalFrames) {
                                          videoEncoder.close();
                                          encoderClosed = true;
                                          file.save("test.mp4");
                                         console.log("completed !");
                                       }
                        
                                },
                               error: (error)=>{
                                     console.log("onCodecError ",error);
                                }
                         });
			  
                
                         await videoEncoder.configure({
                            codec : 'avc1.42001E',
                            width:w,
                            height:h,
                            hardwareAcceleration:"deny",
                            avc:{format:"annexb"} // format can be "annexb" or "avc" but mp4box doesn't seem to support "avc"
                        });
				
			 
		  return videoEncoder;
	    }	
            
            
            //--- create a simple movie inside a canvas and send frames to webcodec.VideoEncoder ----
            let canvas = document.createElement("canvas");//new OffscreenCanvas(w, h);
            canvas.width = w;
            canvas.height = h;
            document.body.appendChild(canvas)
            let ctx = canvas.getContext("2d");

            function drawFrame(progress){
                if(encoderClosed) return;
                
                ctx.fillStyle = "#ffffff";
                ctx.fillRect(0,0,w,h);
                ctx.fillStyle = "#000000";
                ctx.fillRect(Math.round((w-50)*progress),200,50,50);
                
                createImageBitmap(canvas).then((bmp)=>{
                    let videoFrame = new VideoFrame(bmp,{timestamp:durationInMillisecond*progress});
                    videoEncoder.encode(videoFrame);
                    videoFrame.close();
                });			
            }

            async function start() {
		 videoEncoder = await buildAndConfigureEncoders();
                
	 	 let i = 0;
                  while (i++<totalFrames) drawFrame(i/totalFrames)		
	   }
			
	   start();

        </script>
    </body>
</html>

You can see the result here :
https://beginfill.com/webcodec_mp4box/test.mp4

(that's weird, online it doesn't move at all, but if I use the video-player called VLC I can see the first 2-3 frames)

Can someone please help me to get it working as exected ?

Thank you for reading

test_webcodec_videoEncoder_and_mp4box_muxer.zip

image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions