Use --pre-js to redefine functions in Module

There are tons of output from FFmpeg, it contains important information like meta data of the video, output from encoder/decoder and the progress of the task. By default these information is printed from native C library printf / sprintf , although you can see it in DevTools, you can not manipulate with JavaScript.

Luckily, in Emscripten we can redefine the behavior of the some default functions with --pre-js or --post-js . For the scenario above, the function we need to redefine is Module['printErr'] (as the output of FFmpeg uses stderr ) and added to our ffmpeg.js with --pre-js .

Below are some of my lesson learnt for your reference:

You can only use ES5 syntax in --pre-js (No arrow function, const, let)

(No arrow function, const, let) You need to add extra macro to prevent your code removed by Closure compiler (Here I don’t use Closure compiler)

Here is current prepend.js used in ffmpeg.js:

We actually define a new function setLogger to register our custom logger function and redefine two existing functions print and printErr . With this prepend.js, now we can easily manipulate the output message of FFmpeg and develop more features (like progress bar).

Add --pre-js in build script is easy (Line 54):

Now we have setLogger in Module object, we can use it after initialization (Line 13):

Use ffmpeg.js with webcam

Here I would like to describe how to use ffmpeg with live streaming, here we use webcam as an example, but most of the case should have similar work flow.

The basic work flow is:

Use MediaRecorder API to save the streaming to Blob Convert Blob to Uint8Array data Use ffmpeg.js to transcode the Uint8Array data

Step.1 access webcam using getUserMedia (https protocol is required)

<video id="webcam" width="320px" height="180px"></video>

<script>

const webcam = document.getElementById('webcam');

(async () => {

webcam.srcObject = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });

await webcam.play();

})();

</script>

Step.2 use MediaRecorder to record chunks

const startRecording = () => {

const rec = new MediaRecorder(webcam.srcObject);

const chunks = [];

rec.ondataavailable = e => chunks.push(e.data);

rec.onstop = async () => {

transcode(new Uint8Array(await (new Blob(chunks)).arrayBuffer()));

};

rec.start();

};

Step.3 reuse the trancode in the previous part to do the transcoding.

Check CodePen below for full code and live demo:

In Part.5, we have learnt how to use --pre-js to redefine / extend the capability of Module and introduce an example how to use ffmpeg in live streaming scenario.

For Part.6, we will have a deep dive into the file system: Build FFmpeg WebAssembly version (= ffmpeg.js): Part.6 a Deep Dive into File System

Repositories: