I have previously tinkered with ffmpeg in the browser and implemented a workaround[1] for the (then) missing pthread support. It turned out quite clunky, but worked.
- First they were disabled due to Spectre. - Chrome reenabled them. - New HTTP headers were added for cross-origin resource partitioning. - FF/Chrome are both requiring those headers (FF now, Chrome next month)
That's awesome that you've played around with this, too. It was quite a bit of fun :)
We had to "optimize" loading it twice.
The first time, I moved it from auto-loading to when the user clicks convert to save on bandwidth.
The second time, I moved it to after a file is selected. That gives it time to load while users are presented with options before converting.
It's definitely a trade-off. For us, the choice was easy-ish because we want to keep the budget down as Indie Hackers, so we can't just offer a free tool that costs a ton in backend/serverless charges.
(This is how I tried to measure FFmpeg binary size, I have no idea if it is correct:
ldd $(which ffmpeg) | egrep -o "/[^ ]+" | \
xargs readlink -f | xargs stat -c '%s' | \
python3 -c 'import sys; print(sum(map(lambda s: int(s.strip(), 10), sys.stdin.read().split())))'
178092232)
My ffmpeg which I compiled as follows (with my own filter)
--enable-gpl --enable-version3 --enable-nonfree --enable-libx264 --enable-libx265 --enable-libmp3lame
is 21,387,880 bytesRunning with your command reports an additional 18,273,624 bytes
linux-vdso.so.1 (0x00007ffcbcdfd000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007ff60391b000) libmp3lame.so.0 => /usr/lib/x86_64-linux-gnu/libmp3lame.so.0 (0x00007ff6036a4000) libx264.so.152 => /usr/lib/x86_64-linux-gnu/libx264.so.152 (0x00007ff6032ff000) libx265.so.146 => /usr/lib/x86_64-linux-gnu/libx265.so.146 (0x00007ff60267e000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ff60245f000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff60206e000) /lib64/ld-linux-x86-64.so.2 (0x00007ff605d14000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007ff601e6a000) libnuma.so.1 => /usr/lib/x86_64-linux-gnu/libnuma.so.1 (0x00007ff601c5f000) libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007ff6018d6000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007ff6016be000)
I guess it depends what you compile in.
du -cb $(ldd $(which ffmpeg) | egrep -o "/[^ ]+" | cat <(which ffmpeg) - | xargs readlink -f) | tail -n1
I think this is what the ffmpeg.wasm-core project is compiling in:https://github.com/ffmpegwasm/ffmpeg.wasm-core/blob/n4.3.1-w...
Overall I think the wasm size is pretty good, maybe even smaller than the non-wasm binaries to a first approximation.
I've been really happy with the results so far!
If the tool is popular long term, we might do a serverless option to make it accessible to Safari users or something though.
Even our mp4s aren't very well-optimized right now.
If you work with video a bit and think this tool might be helpful to you, let me know!
We're trying to keep this tool super simple for our end users, but I think we might be able to add a webm preset.
If you'd like me to look into it, drop me an email: andrew@<domain in link> and show me a sample command :)
ffmpeg -i input.mp4 -b:v 0 -crf 30 -pass 1 -an -f webm /dev/null
ffmpeg -i input.mp4 -b:v 0 -crf 30 -pass 2 output.webm
Making it two passes seems to be important for WEBM according to the post. It has worked well for me so far, but I need to look it up every time. ffmpeg -i FILE -codec:v libvpx-vp9 -qscale:v 0 -codec:a libvorbis -qscale:a 0 FILE.webm
And end up with really good results out the other end. When I was rendering with pre-VP9 I needed a few more flags (stuff like crf) to maintain quality, but this works fine for most things. And has been really impressive on the filesize side of things.I'm using ffmpeg.wasm, it's basically ffmpeg compiled for the browser, and it's a simple layer where you basically treat it like the ffmpeg command, eg:
ffmpeg.run(['-i', 'input.gif', ..., 'output.gif').then(() => { // handle output file })
And I'm still learning a ton :)
That sounds like a great use case for us to handle! Although I think ffmpeg in the browser loses some efficiency over the command line.
I think we added cropping as a possible future feature. I'll bet ffmpeg makes that really easy to do.
I think we should also work on optimizing the output size. I think we use a pretty high (err, low) -crf, which can result in ridiculous file sizes.
Thanks for the comment! Appreciate hearing use cases :)
Hi HN,
I love new web tech, and was excited to see ffmpeg ported to WebAssembly so decided to build a free tool that uses it to:
- Clip/trim videos - Overlay text and images - Resize - Create GIFs or convert to a web-friendly MP4
All of this done in your browser, without ever uploading a file to a web server! (* Except Safari, it doesn't support SharedArrayBuffers)
A little more:
I've been building a video creation app with my cofounder, and being a 2-man team, we wanted to think outside of the box on an "eng as marketing" strategy.
As a techy on a budget, ffmpeg.wasm sounded like the perfect library to make a powerful free tool without requiring a ton of server resources.
So we looked up some common tasks people want to do with videos and set out to build a quick tool to accomplish them.
I think there's a ton more we can build into this - it's been about a 2 week project, but thought it was cool enough to do an initial release now.
Hope you like it, and have suggestions on what we can improve!