Settings

Theme

Show HN: WebAssembly and ffmpeg = Quick clip, overlay, resize and GIF-ize videos

vidds.co

104 points by Andrew_W 5 years ago · 50 comments

Reader

Andrew_WOP 5 years ago

* VM is upgraded - we're back :) *

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!

  • phoboslab 5 years ago

    Very cool! I see that SharedArrayBuffers are enabled again, after they were disable due to spectre!?

    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.

    [1] https://phoboslab.org/files/ffmpeg-mt-fixed/

    • Andrew_WOP 5 years ago

      Yeah, SharedArrayBuffers have been back and forth!

      - 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 :)

  • PowerfulWizard 5 years ago

    It is a really good idea. My #1 question with this type approach was how big the WASM would end up -- 24MB in this case.

    • Andrew_WOP 5 years ago

      Yeah, that's definitely an issue!

      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.

      • PowerfulWizard 5 years ago

        I agree it makes a lot of sense for stuff that could never be offered as a free back-end service. FFmpeg is a complex app as well, I tried to measure the the size of the binary + all shared libraries on my linux system and I came up with almost 180MB. I couldn't tell if the .WASM file was being transferred compressed either, it should compress more than 2x.

        (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

        )

        • iso1210 5 years ago

          You're not adding the size of the ffmpeg binary itself with that.

          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 bytes

          Running 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.

        • Andrew_WOP 5 years ago

          Yeah. My biggest question when I started building this was whether there was enough in the wasm to support the features we wanted to build.

          I've been really happy with the results so far!

      • daxfohl 5 years ago

        Have you tried running this as a fastly worker?

        • Andrew_WOP 5 years ago

          Nope! It's all running client-side, so it uses a bit more bandwidth, but there's no way a serverless platform can compete with the cost :)

          If the tool is popular long term, we might do a serverless option to make it accessible to Safari users or something though.

          • daxfohl 5 years ago

            I'd be curious what difference it makes. Supposedly fastly compiles wasm down to native first, so it should run faster. Obviously fetch time would be faster since it's sitting on their hard drives. Data transfer would obviously be video file size and bandwidth dependent. A lot of variables there, but still it would be interesting to see even for your particular bandwidth and distance from a fastly server, for what file size the break even point is (for a few different operations).

  • felixfbecker 5 years ago

    Any plans to support WEBM? Files are even smaller than MP4, which makes them perfect for replacing GIFs

    • Andrew_WOP 5 years ago

      Yeah, webm is already built in to ffmpeg, we just had a pretty limited focus for our initial release.

      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!

      • felixfbecker 5 years ago

        I record little screencasts/demos regularly for embedding them on webpages and currently always convert them with the ffmpeg CLI to WEBM, but it's really cumbersome and hard to remember all the command line flags you need to use (especially with 2 passes). I don't really like online cloud converters though because each video needs to both be uploaded and downloaded again and I'm worried they do a lossy compression on the video behind the scenes. A simple to use, trustworthy, client-based webapp to do this would be amazing.

        • Andrew_WOP 5 years ago

          That's awesome! Do you have an example ffmpeg command you run?

          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 :)

          • felixfbecker 5 years ago

            I use this command I found on SO (was the first Google result): https://video.stackexchange.com/a/28276

                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.
          • shakna 5 years ago

            I use the very basic:

                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.
  • iudqnolq 5 years ago

    Amy advice for someone trying to write code against the ffmpeg api for the first time? It's...esoteric and the "correct" way seems to be reading a bunch of ten year old blog posts by random uncertain people. Even the python binding devs have a disclaimer they aren't confident they understand everything they document, despite doing their best to read the source.

    • Andrew_WOP 5 years ago

      Oh, no, I have nothing there, sorry! haha

      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 })

      • iudqnolq 5 years ago

        Don't sell yourself short, the cli args aren't easier either.

        • Andrew_WOP 5 years ago

          True! When I first started building a video creation app, I was flailing around with google searches to find snippets to use. It was such a relief to spend an hour reading ffmpeg docs to understand how it works.

          And I'm still learning a ton :)

  • madeofpalk 5 years ago

    The main reason why I use ffmpeg/edit videos is to take my 3440x1440 screen recordings and crop+resize them in a format friendly for twitter, otherwise twitter will do its own (additional?) resizing and compression which just destroys videos

    • Andrew_WOP 5 years ago

      Sorry for not responding sooner.

      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 :)

arsalanb 5 years ago

This is great! Another neat project that comes to mind is https://modfy.video

  • Andrew_WOP 5 years ago

    Oh that tool is neat, and they have a super slick UI!

    Our tool definitely isn't as slick, but I think that has its benefits too. Like our trim interface doesn't look as nice, but shows a live preview of where you're at in the video.

    I want their UI and style haha

    • cryogenicplanet 5 years ago

      This is super cool, love to see more people working in this space!

      Would love to chat about what you guys doing.Potentially collab and improve both our products!

      Reach out rahul@modfy.video

kumarm 5 years ago

Its amazing what we can do with modern browsers today.

Our app plug: 7 years back we did a quick tool to shrink JPG's in browser (Again needs Chrome or Firefox) without uploading images to server: http://shrinkjpeg.com

  • Andrew_WOP 5 years ago

    Seriously! We were trying to build our video editor in the same style (eg like tinypng and GIF optimizers).

    It's so cool to do it all in the browser!

    I even built a simple landing page creator that let you change text and images, then created a zip file that you could extract to your web host - no backend needed!

    I think for me, CORS is the biggest hindrance to some of my ideas, esp. around editing, creation, and working with the content.

had-rien 5 years ago

Awesome idea, it is hard to try for now but it could be very useful. I especially like simple clip and resize feature but can't try them right now...

  • Andrew_WOP 5 years ago

    Sorry if you were having trouble because the website was down. We upgraded the server and it seems to be doing a little better!

    But also get it if you mean you're not in a good place to test the tool at the moment haha

    • had-rien 5 years ago

      I have managed to try it now, and indeed it is almost perfect for my use case : Often I find videos on youtube for example which I want to show snippet to someone or save it. So I download it easily with youtube-dl but then clipping is never really easy (especially on linux).

      To improve the tool it would be nice to play the part clipped with the sound to check if it's ok. Also the tool failed to load one video.

      Good job !

      • Andrew_WOP 5 years ago

        Hey, this feedback is great! And it isn't even too difficult to add - we have live clipped playback in our main app.

        When it failed to load the video, did it show a convert option that failed to load it as well? I think there are some limitations to the ffmpeg.wasm compile. Do you know the extension, or any details of the codecs, etc?

      • Andrew_WOP 5 years ago

        If you send me an e-mail (andrew@<domain in link>), I can dig in a bit more and let you know when I add it :)

baxuz 5 years ago

Man I wish WebGPU would come soon so that we could get HW acceleration support for a lot of WASM projects.

  • Andrew_WOP 5 years ago

    Yeah, and Spectre/Meltdown haven't helped.

    There are some pretty crazy security restrictions (no external scripts!) just to get ffmpeg running. I can't imagine the additional security precautions that would prevent exploits for WebGPU.

jack_riminton 5 years ago

"Error establishing a database connection" is what I'm getting. Hug of death?

EDIT: working again now, looks pretty cool!

danabrams 5 years ago

"You might have come across .mov while working with Apple softwares such as QuickTime, it was introduced in 1998 and uses a top secret compression algorithm. It is often quoted as the catalyst to Apple bringing feature length movie quality to their devices."

This description is absolutely killing me.

donatj 5 years ago

I made a similar thing last year that’ll take any gif you throw at it and make a Zoom background compatible video.

https://donatstudios.com/GifAsZoomBackground

FunnyLookinHat 5 years ago

This is awesome - nice job!

Adding the ability to loop the gif back and forth would be great!

  • Andrew_WOP 5 years ago

    Interesting idea, like append the video to itself but reversed for a clean loop? I like this idea :)

tonyzzz 5 years ago

I remembered that WASM application cannot use any kind of hardware acceleration. So have anyone tested the website for large videos?

  • Andrew_WOP 5 years ago

    Definitely a performance hit! Probably a combination of the lack of hardware acceleration and running in a JS virtual machine.

    I haven't checked the exact hit, but that's mostly because our focus for this tool was on people who would never touch ffmpeg or a command line.

    Also, the alternative for us would've been to upload remotely and run on Lambda or similar, which I think would lack hardware acceleration as well.

prussian 5 years ago

sounds cool. wonder in practice how this will work out with patent encumbered video formats.

  • Quarrel 5 years ago

    Don't the patent holders want the creation / manipulation of patent encumbered videos?

    Unfortunately, of course, they then want to get paid during playback, but that's the reality for everyone already.

Keyboard Shortcuts

j
Next item
k
Previous item
o / Enter
Open selected item
?
Show this help
Esc
Close modal / clear selection