Running FFMPEG with WASM in a Web Worker

I love FFMPEG.js, it’s a neat tool that is compiled with asm.js`and it let’s me build JS web apps that can quickly edit videos. FFMPEG.js also works with web workers so that you can encode videos without blocking the main thread.
I also love Comlink. Comlink let’s me easily interact with web workers by exposing functions and classes without having to deal with a complex postMessage state machine.
I recently got to combine the two together.


This content originally appeared on Modern Web Development with Chrome and was authored by Paul Kinlan

<p>I love <a href="https://github.com/Kagami/ffmpeg.js">FFMPEG.js</a>, it's a neat tool that is compiled with asm.js`and it let's me build JS web apps that can quickly edit videos. FFMPEG.js also works with web workers so that you can encode videos without blocking the main thread.</p> <p>I also love <a href="https://github.com/GoogleChromeLabs/comlink">Comlink</a>. Comlink let's me easily interact with web workers by exposing functions and classes without having to deal with a complex <code>postMessage</code> state machine.</p> <p>I recently got to combine the two together. I was <a href="https://github.com/PaulKinlan/ffmpeg.js/tree/wasm">experimenting getting FFMPEG exported to Web Assembly</a> (it works - yay) and I wanted to clean up all of the postMessage work in the current FFMPEG.js project. Below is what the code now looks like - I think it's pretty neat. We have one worker that imports ffmpeg.js and comlink and it simply exposes the ffmpeg interface, and then we have the webpage that loads the worker and then uses comlink to create a proxy to the ffmpeg API.</p> <p>Neat.</p> <h4 id="workerjs">worker.js</h4> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-javascript" data-lang="javascript"><span style="color:#a6e22e">importScripts</span>(<span style="color:#e6db74">'https://cdn.jsdelivr.net/npm/comlinkjs@3.0.2/umd/comlink.js'</span>); <span style="color:#a6e22e">importScripts</span>(<span style="color:#e6db74">'../ffmpeg-webm.js'</span>); <span style="color:#a6e22e">Comlink</span>.<span style="color:#a6e22e">expose</span>(<span style="color:#a6e22e">ffmpegjs</span>, <span style="color:#a6e22e">self</span>); </code></pre></div><h4 id="clienthtml">client.html</h4> <div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-javascript" data-lang="javascript"><span style="color:#66d9ef">let</span> <span style="color:#a6e22e">ffmpegjs</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">await</span> <span style="color:#a6e22e">Comlink</span>.<span style="color:#a6e22e">proxy</span>(<span style="color:#a6e22e">worker</span>); <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">result</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">await</span> <span style="color:#a6e22e">ffmpegjs</span>({ <span style="color:#a6e22e">arguments</span><span style="color:#f92672">:</span> [<span style="color:#e6db74">'-y'</span>,<span style="color:#e6db74">'-i'</span>, <span style="color:#a6e22e">file</span>.<span style="color:#a6e22e">name</span>, <span style="color:#e6db74">'output.webm'</span>], <span style="color:#a6e22e">MEMFS</span><span style="color:#f92672">:</span> [{<span style="color:#a6e22e">name</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">file</span>.<span style="color:#a6e22e">name</span>, <span style="color:#a6e22e">data</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">data</span>}], <span style="color:#a6e22e">stdin</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">Comlink</span>.<span style="color:#a6e22e">proxyValue</span>(() => {}), <span style="color:#a6e22e">onfilesready</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">Comlink</span>.<span style="color:#a6e22e">proxyValue</span>((<span style="color:#a6e22e">e</span>) => { <span style="color:#66d9ef">let</span> <span style="color:#a6e22e">data</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">e</span>.<span style="color:#a6e22e">MEMFS</span>[<span style="color:#ae81ff">0</span>].<span style="color:#a6e22e">data</span>; <span style="color:#a6e22e">output</span>.<span style="color:#a6e22e">src</span> <span style="color:#f92672">=</span> <span style="color:#a6e22e">URL</span>.<span style="color:#a6e22e">createObjectURL</span>(<span style="color:#66d9ef">new</span> <span style="color:#a6e22e">Blob</span>([<span style="color:#a6e22e">data</span>])) <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">'ready'</span>, <span style="color:#a6e22e">e</span>) }), <span style="color:#a6e22e">print</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">Comlink</span>.<span style="color:#a6e22e">proxyValue</span>(<span style="color:#66d9ef">function</span>(<span style="color:#a6e22e">data</span>) { <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">data</span>); <span style="color:#a6e22e">stdout</span> <span style="color:#f92672">+=</span> <span style="color:#a6e22e">data</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">"\n"</span>; }), <span style="color:#a6e22e">printErr</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">Comlink</span>.<span style="color:#a6e22e">proxyValue</span>(<span style="color:#66d9ef">function</span>(<span style="color:#a6e22e">data</span>) { <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">'error'</span>, <span style="color:#a6e22e">data</span>); <span style="color:#a6e22e">stderr</span> <span style="color:#f92672">+=</span> <span style="color:#a6e22e">data</span> <span style="color:#f92672">+</span> <span style="color:#e6db74">"\n"</span>; }), <span style="color:#a6e22e">postRun</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">Comlink</span>.<span style="color:#a6e22e">proxyValue</span>(<span style="color:#66d9ef">function</span>(<span style="color:#a6e22e">result</span>) { <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">'DONE'</span>, <span style="color:#a6e22e">result</span>); }), <span style="color:#a6e22e">onExit</span><span style="color:#f92672">:</span> <span style="color:#a6e22e">Comlink</span>.<span style="color:#a6e22e">proxyValue</span>(<span style="color:#66d9ef">function</span>(<span style="color:#a6e22e">code</span>) { <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#e6db74">"Process exited with code "</span> <span style="color:#f92672">+</span> <span style="color:#a6e22e">code</span>); <span style="color:#a6e22e">console</span>.<span style="color:#a6e22e">log</span>(<span style="color:#a6e22e">stdout</span>); }), }); </code></pre></div><p>I really like how Comlink, Workers and WASM compiled modules can play together. I get idiomatic JavaScript that interacts with the WASM module directly and it runs off the main thread.</p> <p><a href="https://github.com/PaulKinlan/ffmpeg.js/blob/wasm/examples/async.html">Read full post</a>.</p>


This content originally appeared on Modern Web Development with Chrome and was authored by Paul Kinlan


Print Share Comment Cite Upload Translate Updates
APA

Paul Kinlan | Sciencx (2018-10-02T16:17:19+00:00) Running FFMPEG with WASM in a Web Worker. Retrieved from https://www.scien.cx/2018/10/02/running-ffmpeg-with-wasm-in-a-web-worker/

MLA
" » Running FFMPEG with WASM in a Web Worker." Paul Kinlan | Sciencx - Tuesday October 2, 2018, https://www.scien.cx/2018/10/02/running-ffmpeg-with-wasm-in-a-web-worker/
HARVARD
Paul Kinlan | Sciencx Tuesday October 2, 2018 » Running FFMPEG with WASM in a Web Worker., viewed ,<https://www.scien.cx/2018/10/02/running-ffmpeg-with-wasm-in-a-web-worker/>
VANCOUVER
Paul Kinlan | Sciencx - » Running FFMPEG with WASM in a Web Worker. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2018/10/02/running-ffmpeg-with-wasm-in-a-web-worker/
CHICAGO
" » Running FFMPEG with WASM in a Web Worker." Paul Kinlan | Sciencx - Accessed . https://www.scien.cx/2018/10/02/running-ffmpeg-with-wasm-in-a-web-worker/
IEEE
" » Running FFMPEG with WASM in a Web Worker." Paul Kinlan | Sciencx [Online]. Available: https://www.scien.cx/2018/10/02/running-ffmpeg-with-wasm-in-a-web-worker/. [Accessed: ]
rf:citation
» Running FFMPEG with WASM in a Web Worker | Paul Kinlan | Sciencx | https://www.scien.cx/2018/10/02/running-ffmpeg-with-wasm-in-a-web-worker/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.