-
-
Notifications
You must be signed in to change notification settings - Fork 338
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WebAssembly build #10
Comments
I'll look into this, thanks. Though I don't think this will give big speedup compared to asm.js since it's just another format for the same thing. The really promising feature would be SIMD.js. |
I mean compile FFMPEG directly to WebAssembly. It is possible to compile any (LLVM-based) programming language other than JavaScript (initially mainly C/C++) to WebAssembly. See http://2ality.com/2015/06/web-assembly.html for more info. |
There is no real difference between compiling to asm.js or compiling to wasm. Most important advantage is load time, in terms of speed Firefox uses AOT compilation for asm.js anyway, so it shouldn't be faster. I don't mean wasm is bad, just trying to say that pros are mostly related to initial loading/better browser support/standartization/etc. |
Judging by the wasm demo, it seems like there is a big performance difference. |
This might be a useful read: https://hacks.mozilla.org/2017/03/why-webassembly-is-faster-than-asm-js/. It highlights the performance differences between asm.js and WebAssembly. |
I am attempting to to give this a try (compiling to WebAssembly). First I built "ffmpeg-worker-webm.js" without any modifications to make sure I could successfully build on my machine. I was able to build and run that in my browser without any issues. To convert to WebAssembly, I took a look at https://github.com/kripken/emscripten/wiki/WebAssembly. I concluded that I needed to add the flag:
@Kagami Do you happen to have any advice? I will admit, I am not terribly familiar with WebAssembly/asm.js, so I might be completely off the mark. I am just interested in the performance benefits that WebAssembly (potentially) offers. |
That is interesting... I was suprised that WASM is considerably slower... |
I'm getting more than twice the processing duration:
very strange... |
I've been running tests on a fork of audioconverter.js and wasm doesn't seem to be giving much of an improvement, I haven't been able to create a proper benchmark for it yet but I've put some console.time calls in preRun and postRun. These are the results:
Tests were converting wav files to webm opus ( audio only ), and each one was run twice. Obviously needs more iterations and using something a little more accurate than console.time but it demonstrates the point. WASM proves to be fairly disappointing thus far in terms of performance improvements. Also chrome seems to crash occasionally with the WASM version, which is less than ideal. |
Anybody still interested? Managed to compile it with O2 optimization. Compiling to wasm reduced size to 7mb, I have slight performance increase in some scenarios on Chrome and really nice performance boost on firefox ... my only remaining issue is that even with ALLOW_MEMORY_GROWTH=1 i still manage to crash chrome tab if I render 9 minute video with ultrafast preset and some filters this build has added concat filter and mjpeg and image2 support for mp4_build as well |
@picitujeromanov thank you for your build, it works! (and faster than asm.js with -O3 on my machine) |
You can compile to wasm with my fork. |
@picitujeromanov thank you. I really appreciate that. |
@picitujeromanov using your mp4 worker and it works great, is there's a way to get ffmpg text command output? |
@picitujeromanov I'm building off your repo right now. I'm hoping this works. I have a project that actually requires transcoding video in Mobile Safari, and this is my last hope for getting this working. |
@picitujeromanov If you can believe it, this actually worked for me for a legitimate use case. I've got an end to end encrypted messenger app called Tunnelgram that supports sending videos. Normally a messenger app will take whatever video you give it and transcode it into something more compatible on the server side. Since mine is sending encrypted video, I can't transcode it on the server. So basically videos from Android were viewable by everyone, but videos from iPhone were only viewable on Apple devices. Your ffmpeg.js build saved me. Plus it's nice to not have to pay for the server cost of transcoding a bunch of videos. xD Thank you @picitujeromanov and super thank you @Kagami! |
happy to hear that |
@hperrin have you tried encoding really big videos? I've had a problem where when I was using complex filters (picture in picture effect etc) it crashed the worker if the resulting video got to around 100mb in size. I see you updated ffmpeg and h264 lib, I might as well try my use case with your build now if it successfully finishes |
I have no issues using WASM build too. May be it's filters code issue? I remember that working with filters is tricky with buffers retain. You can try execute your test locally, without emcc and check with -fsanitize=address (on linux also shows memory leaks, use drmemory if on windows). Leaks is very common with writing ffmpeg filters code. |
@picitujeromanov I have a limit of 20mb for videos, so I use a two pass strategy to transcode them with the right bitrates to be just under 20mb. The biggest video I've tried transcoding was 35mb, and it took over an hour. (I have all the fancy H.264 features enabled to make the quality really good. Basically equivalent to the "fast" preset, which wasn't working.) These are the command line options: |
I also took out every encoder but H.264 and AAC, since those are the only ones I'm using, and I wanted the file size to be as small as possible. |
@hperrin have you tried compiling with |
@Mathieu-Gosbee-ConnectedLab Yeah, I've done that. I think the transcoding time is just because I'm using pretty high quality H.264 settings, and I'm using two passes (so it's almost twice as long just from that). @picitujeromanov Scratch what I said earlier, I've tried it on a 53mb video and it worked no problem. I'll try it with a 160mb copy of Big Buck Bunny and upload the results. That is, if it doesn't crash, considering asking H.264 to bring a 160mb video down to 20mb is probably unrealistic. |
Ok, done. The original video was actually only 106mb, but here's the result: And it took a little over an hour to do that one too. |
@hperrin I would be much interested in your findings using WASM compared to asm.js and whether performance improved further with the newest libx264 as well |
A lot has happened in the last 4 years. So maybe @Kagami is interested on a fresh evaluation whether to add wasm implementation:
So i modified the build scripts to build a specialized ffmpeg version (encoding to h264, no audio, some filters added) for me and received the following build sizes:
So when the files are gzipped there's not so much difference but if there is no gzipping the difference is huge. Nevertheless the whole build needs to be parsed by the interpreter. Parsing 9MB of JavaScript will take some time. Wasm has the added benefit that parsing is much more faster as the whole code is already transformed to a binary format and it's a lot smaller too. But codesize is not everything, execution time is also very important. As my wasm build had a small bug i could not get rid off (returning the results failed everytime) i used the js and wasm builds of ffmpegjs/ffmpeg.js. As both are simply wrapping ffmpeg they should be pretty comparable. I built an easy reproducible benchmark which everybody can run. It may take a few minutes and i would suggest keeping the tab always in the foreground to not skew the results. Here are my results on how much wasm was faster compared to a non-wasm version:
As you can see the wasm version was always faster, sometimes by a large amount (chrome heavily optimizes for it, but i am not using a thread-enabled build!). A lot has happened on browser engines optimizing their wasm implementations 😀. It failed on Safari on parsing my ffmpeg paramters, don't know why, maybe a bug in the compiled version. I was not able to test on edge, but as it is nowadays simply chrome the numbers should be equal. So in my opinion a lot has changed! Wasm shows very impressive performance benefits which should be used. I mean it's just another build. When a working wasm build is available it will be really interesting how performance will change for a wasm with threads build for chrome. |
Thanks for your research @tpetry. I agree, it's definitely worth to add support for WebAssembly. |
This lady will give you more insight on how to build it for webAssembly, she even mentions you @Kagami and me |
Interestingly for wasm builds |
This is actually a pretty big one for me, I spend a heap of time just re-compiling to see where the memory issues come in. That and I know the v8 WASM team are doing a heap of work in this space (it might enable us to turn on SIMD and Threading support easily) |
Can you guys please provide me a link of gziped wasm build of latest kagami ffmpeg for mp4? |
+1 for a wasm build! I haven't been able to achieve realtime h262 to h264 transcoding via emscripten. I can see light at the end of my tunnel with this. |
Encoding to h264 with |
@tpetry maybe it would be faster to extract the audio and dump image frames from the video to "play back" in an html5 canvas. This would also involve having to create some type of sync mechanism for audio/video to align. |
@grkblood13 Sounds very complicated for a very low probability that this solution would really be faster. |
+1 on the wasm build! Would also love to see threading support (given Chrome supports it) |
Any progress? I just built a wasm version with only changes exception thrown: RuntimeError: unreachable,RuntimeError: unreachable
at exit_program (<anonymous>:wasm-function[120]:0x12a34)
at write_option (<anonymous>:wasm-function[126]:0x13535)
at parse_optgroup (<anonymous>:wasm-function[127]:0x13691)
at ffmpeg_parse_options (<anonymous>:wasm-function[46]:0x496c)
at main (<anonymous>:wasm-function[183]:0x18f6a)
at callMain (http://localhost:8080/js/ffmpeg-worker-mp4.js:6932:15)
at doRun (http://localhost:8080/js/ffmpeg-worker-mp4.js:6994:23)
at run (http://localhost:8080/js/ffmpeg-worker-mp4.js:7009:5)
at __ffmpegjs (http://localhost:8080/js/ffmpeg-worker-mp4.js:7059:1)
at self.onmessage (http://localhost:8080/js/ffmpeg-worker-mp4.js:7107:20) By the way, my test shows wasm version is 2x faster, and only 0.5x in size. |
See also: ffmpegwasm/ffmpeg.wasm#75. |
@ahuglajbclajep 's library worked for me. all attempts at making my own build failed |
I have wasm version working in #166 |
What about compiling FFMPEG to WebAssembly?
There are experimental native WebAssembly implementations for Google Chrome, Mozilla Firefox, Microsoft Edge and Apple Safari.
The text was updated successfully, but these errors were encountered: