ffmpegwasm / ffmpeg.wasm

FFmpeg for browser, powered by WebAssembly
https://ffmpegwasm.netlify.app
MIT License
13.61k stars 785 forks source link

Any plans to have a version without SharedArrayBuffer? #137

Closed PaTiToMaSteR closed 3 years ago

PaTiToMaSteR commented 3 years ago

Is your feature request related to a problem? Please describe. It's a known problem that SharedArrayBuffer was removed due to Spectre and Meldown hacks.

Describe the solution you'd like A safe version without SharedArrayBuffer

Describe alternatives you've considered I don't have the knowledge in Emcripten nor how you transpile the code to know if it's possible.

Additional context To be able to run this amazing project everywhere we need a version without SharedArrayBuffer!

Quackdoc commented 3 years ago

sharedarraybuffer support is still available in firefox and chrome. and will soon be enabled by default in both again as the security issues have been mitigated (see coop/cope)

I believe chrome desktop has enabled it already, snd chrome mobile is working on it https://www.chromestatus.com/feature/5171863141482496

Basically, there is no need infact if you follow the guide it should work on updated firefox and chrome no?

PaTiToMaSteR commented 3 years ago

That’s good to know, however my target is cross-platform so iOS, Android, PC... without that just simply doesn’t work use ffmpeg as a base framework. I was wondering if can be like a temporal workaround using other method instead of that🤔

Quackdoc commented 3 years ago

again shared buffer array is comming to mobiles (im not sure about IOS but im sure it wouldn't be too hard to find out), firefox nightly on android starts it but crashes before it starts encoding suggesting the issues something else

rakeshb-iprogrammer commented 3 years ago

Any other alternate way to achieve trimming video on mobile web app browser?

jeromewu commented 3 years ago

For the version without SharedArrayBuffer, I would suggest to use ffmpeg.js (https://github.com/Kagami/ffmpeg.js/), right now ffmpeg.wasm doesn't have plan to do that.

selmalee commented 3 years ago

Can i build my own ffmpeg.wasm without SharedArrayBuffer(using ffmpeg.wasm-core)? Where is SharedArrayBuffer used ?Thank you @jeromewu

jeromewu commented 3 years ago

@seminelee I would suggest you use ffmpeg.js instead, it doesn't use SharedArrayBuffer.

SharedArrayBuffer in ffmpeg is used to enable multi-threading, it makes it faster when transcoding media.

selmalee commented 3 years ago

@seminelee I would suggest you use ffmpeg.js instead, it doesn't use SharedArrayBuffer.

SharedArrayBuffer in ffmpeg is used to enable multi-threading, it makes it faster when transcoding media.

@jeromewu thank you. But I can't find SharedArrayBuffer both in ffmpegwasm/ffmpeg.wasm and ffmpegwasm/ffmpeg.wasm-core. Searching SharedArrayBuffer in code:

image

image

jeromewu commented 3 years ago

You can find it here: https://unpkg.com/@ffmpeg/core@0.10.0/dist/ffmpeg-core.js It is in the output of the build script, usually we don't store it in the repository.

Evengard commented 3 years ago

Unfortunately ffmpeg.js doesn't support libtheora (I need encoding), and Firefox addons are supporting SharedArrayBuffers only for "privileged addons" (and I wanted to use it for an addon). Is there really no way to build it without SAB? I don't really mind being it single-threaded.

jeromewu commented 3 years ago

Acutually you can build it on your own by removing all pthread support in build script, so it is totally possible but takes time to develop.

https://github.com/ffmpegwasm/ffmpeg.wasm-core/tree/n4.3.1-wasm/wasm/build-scripts

Currently I don't have plan to do that as single thread version is slow and conflicts with ffmpeg.js.

yahsaves commented 3 years ago

I'm trying to build a version with pthreads removed, as I need to target ios.

Speed is not important, as my use case is to extract audio from a user video upload.

Normally I would do this with audioContext.decodeAudioData, but safari doesn't support decoding their own MOV codec.

FFmpeg.js does not recognize a video file recorded from iPhone, but this project contains the libraries to work with a MOV file.

So using wasm.core I removed all the pthread references from the build script, and removed the -j flag from the MAKE commands. However the build does not produce a dist folder with the wasm files. The terminal log is very long, and there is no immediate error's at the end so I'm not sure where to start debugging.

Any advice how to debug building this project, or anything else I should look for that could cause the build to fail?

I would even consider paying someone to help build this project, as I really need it for my use case.

jeromewu commented 3 years ago

Maybe I can help to build the single thread version and put it somewhere, but to use it, you still need to write a wrapper like ffmpeg.wasm to load the ffmpeg.wasm-core for you.

Will update here once I build the single-thread version.

yahsaves commented 3 years ago

That would be amazing! Like to the 10th degree of awesome.

As for the wrapper, would there be significant changes from the utils.js file provided in the core example?

I was looking through the browser examples, and I didn't see anything in particular that looks like it had to change to support a single thread. Unless the calls utils makes to the 'createFFmpegCore' function would require different parameters.

ZYMoridae commented 2 years ago

@jeromewu May I ask is there any updates on the latest single-thread version?

jeromewu commented 2 years ago

I plan to release it after updating ffmpeg.wasm, but if you are in a hurry, you can download the singled threaded version here:

https://github.com/ffmpegwasm/ffmpeg.wasm-core/actions/runs/1050801687 (You can download it in artifacts section)

And you can check here for how to use it: https://github.com/ffmpegwasm/ffmpeg.wasm-core/tree/n4.3.1-wasm/wasm/tests/utils/st

(Sorry I only write a node.js version for testing, but it shouldn't be too hard to write a web worker version on your own)

ZYMoridae commented 2 years ago

I plan to release it after updating ffmpeg.wasm, but if you are in a hurry, you can download the singled threaded version here:

https://github.com/ffmpegwasm/ffmpeg.wasm-core/actions/runs/1050801687 (You can download it in artifacts section)

And you can check here for how to use it: https://github.com/ffmpegwasm/ffmpeg.wasm-core/tree/n4.3.1-wasm/wasm/tests/utils/st

(Sorry I only write a node.js version for testing, but it shouldn't be too hard to write a web worker version on your own)

Does that means once you update the ffmpeg.wasm we could directly use it in the browser with ffmpeg.wasm?

selmalee commented 2 years ago

I have build a version without SharedArrayBuffer by this build script: https://github.com/seminelee/ffmpeg.wasm-core/blob/n4.3.1-wasm/build1.sh Hope it can help someone~

By the way, is ffmpeg-core.worker.js neccesary for a custom ffmpeg-core without pthreads? thank you @jeromewu

ZYMoridae commented 2 years ago

I have build a version without SharedArrayBuffer by this build script: https://github.com/seminelee/ffmpeg.wasm-core/blob/n4.3.1-wasm/build1.sh

Hope it can help someone

Do you have a example for browser version?

jeromewu commented 2 years ago

Does that means once you update the ffmpeg.wasm we could directly use it in the browser with ffmpeg.wasm?

@ZYMoridae Yes, that is the plan, but I haven't got enough time to complete it.

jeromewu commented 2 years ago

@seminelee Nope, I don't think ffmpeg-core.worker.js is required for non-pthread version.

selmalee commented 2 years ago

@seminelee Nope, I don't think ffmpeg-core.worker.js is required for non-pthread version.

can i build a version with web worker but without sharedarraybuffer?TAT

jeromewu commented 2 years ago

I would suggest you write your own web worker script, it is actually easier than building one.

selmalee commented 2 years ago

I would suggest you write your own web worker script, it is actually easier than building one.

If I write a web worker script, can I still use this project @ffmpeg/ffmpeg ?

jeromewu commented 2 years ago

Nope, in that case you cannot use @ffmpeg/ffmpeg as it is not compatible.

julienbeisel commented 2 years ago

Hi @jeromewu, do you have an example of how to use the single thread ffmpeg build? I spend some time trying to use the ffmpeg-core single-thread version but I can't make it work. I already read the test files 20 times but I don't really understand it.

Thanks for your help :)

selmalee commented 2 years ago

Hi @jeromewu, do you have an example of how to use the single thread ffmpeg build? I spend some time trying to use the ffmpeg-core single-thread version but I can't make it work. I already read the test files 20 times but I don't really understand it.

Thanks for your help :)

The key is , in emcc, to move -s USE_PTHREADS=1, and to move _proxy_main in -s EXPORTED_FUNCTIONS. Also, I suggest that you can use web worker to run codes about ffmpeg in your project.

I have written an article about it, but in Chinese: https://juejin.cn/post/6998876488451751973 Hope it can help.^^

julienbeisel commented 2 years ago

Hi @jeromewu, do you have an example of how to use the single thread ffmpeg build? I spend some time trying to use the ffmpeg-core single-thread version but I can't make it work. I already read the test files 20 times but I don't really understand it. Thanks for your help :)

The key is , in emcc, to move -s USE_PTHREADS=1, and to move _proxy_main in -s EXPORTED_FUNCTIONS. Also, I suggest that you can use web worker to run codes about ffmpeg in your project.

I have written an article about it, but in Chinese: https://juejin.cn/post/6998876488451751973 Hope it can help.^^

Hi, thanks for the answer. Do you have an example for the browser version? I'd just like to use the build in a browser context.

chicken-suop commented 2 years ago

@seminelee I tried your article, and the build script you created, but I get this error when running the output .webm in web browser:

I used your PR: https://github.com/ffmpegwasm/ffmpeg.wasm/pull/235

[fferr] Assertion failed: Cannot call unknown function _main, make sure it is exported
14:21:54.063 4d8a490f-92a0-4e8b-a784-477c4378ca9e:9 Uncaught (in promise) RuntimeError: abort(Assertion failed: Cannot call unknown function _main, make sure it is exported). Build with -s ASSERTIONS=1 for more info.
    at abort (4d8a490f-92a0-4e8b-a784-477c4378ca9e:9)
    at assert (4d8a490f-92a0-4e8b-a784-477c4378ca9e:9)
    at getCFunc (4d8a490f-92a0-4e8b-a784-477c4378ca9e:9)
    at Object.cwrap (4d8a490f-92a0-4e8b-a784-477c4378ca9e:9)
    at Object.load (createFFmpeg.js:92)

SOLVED: Main function name should be called as main not _main in the js code

ZarcoV commented 2 years ago

@seminelee I've tried to use your build script, but I keep getting errors.

17 warnings generated. wasm-ld: error: unable to find library -lavdevice wasm-ld: error: unable to find library -lswresample emcc: error: '/emsdk/upstream/bin/wasm-ld -o /tmp/emscripten_temp_2xgulhk6/ffmpeg-core.wasm -Llibavcodec -Llibavdevice -Llibavfilter -Llibavformat -Llibavresample -L/emsdk/upstream/emscripten/system/local/lib -Llibavutil -L/emsdk/upstream/emscripten/system/lib -Llibpostproc -L/emsdk/upstream/emscripten/cache/wasm -Llibswscale -Llibswresample /tmp/emscripten_temp_2xgulhk6/ffmpeg_opt_0.o /tmp/emscripten_temp_2xgulhk6/ffmpeg_filter_1.o /tmp/emscripten_temp_2xgulhk6/ffmpeg_hw_2.o /tmp/emscripten_temp_2xgulhk6/cmdutils_3.o /tmp/emscripten_temp_2xgulhk6/ffmpeg_4.o -lavdevice libavfilter/libavfilter.a libavformat/libavformat.a libavcodec/libavcodec.a -lswresample libswscale/libswscale.a libavutil/libavutil.a /emsdk/upstream/emscripten/cache/wasm/libSDL2.a /emsdk/upstream/emscripten/cache/wasm/libgl.a /emsdk/upstream/emscripten/cache/wasm/libc.a /emsdk/upstream/emscripten/cache/wasm/libcompiler_rt.a /emsdk/upstream/emscripten/cache/wasm/libc++-noexcept.a /emsdk/upstream/emscripten/cache/wasm/libc++abi-noexcept.a /emsdk/upstream/emscripten/cache/wasm/libdlmalloc.a /emsdk/upstream/emscripten/cache/wasm/libpthread_stub.a /emsdk/upstream/emscripten/cache/wasm/libc_rt_wasm.a /emsdk/upstream/emscripten/cache/wasm/libsockets.a -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr --allow-undefined --import-memory --strip-debug --export-table --export main --export stackSave --export stackRestore --export stackAlloc --export __data_end --export __wasm_call_ctors --export __errno_location --export malloc --export free --export _get_tzname --export _get_daylight --export _get_timezone --export memset --export memalign --export emscripten_GetProcAddress --export strstr -z stack-size=5242880 --initial-memory=33554432 --no-entry --max-memory=2147483648 --global-base=1024' failed (1)

marcofugaro commented 2 years ago

@jeromewu if you are still planning to release the version without SharedArrayBuffer, maybe you can make createFFmpeg check 'SharedArrayBuffer' in window and download either one of the binary build.

marcofugaro commented 2 years ago

Downloading and trying the single-threaded version posted here results in this issue:

image

Aeroxander commented 2 years ago

@seminelee I've tried to use your build script, but I keep getting errors.

17 warnings generated. wasm-ld: error: unable to find library -lavdevice wasm-ld: error: unable to find library -lswresample emcc: error: '/emsdk/upstream/bin/wasm-ld -o /tmp/emscripten_temp_2xgulhk6/ffmpeg-core.wasm -Llibavcodec -Llibavdevice -Llibavfilter -Llibavformat -Llibavresample -L/emsdk/upstream/emscripten/system/local/lib -Llibavutil -L/emsdk/upstream/emscripten/system/lib -Llibpostproc -L/emsdk/upstream/emscripten/cache/wasm -Llibswscale -Llibswresample /tmp/emscripten_temp_2xgulhk6/ffmpeg_opt_0.o /tmp/emscripten_temp_2xgulhk6/ffmpeg_filter_1.o /tmp/emscripten_temp_2xgulhk6/ffmpeg_hw_2.o /tmp/emscripten_temp_2xgulhk6/cmdutils_3.o /tmp/emscripten_temp_2xgulhk6/ffmpeg_4.o -lavdevice libavfilter/libavfilter.a libavformat/libavformat.a libavcodec/libavcodec.a -lswresample libswscale/libswscale.a libavutil/libavutil.a /emsdk/upstream/emscripten/cache/wasm/libSDL2.a /emsdk/upstream/emscripten/cache/wasm/libgl.a /emsdk/upstream/emscripten/cache/wasm/libc.a /emsdk/upstream/emscripten/cache/wasm/libcompiler_rt.a /emsdk/upstream/emscripten/cache/wasm/libc++-noexcept.a /emsdk/upstream/emscripten/cache/wasm/libc++abi-noexcept.a /emsdk/upstream/emscripten/cache/wasm/libdlmalloc.a /emsdk/upstream/emscripten/cache/wasm/libpthread_stub.a /emsdk/upstream/emscripten/cache/wasm/libc_rt_wasm.a /emsdk/upstream/emscripten/cache/wasm/libsockets.a -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr --allow-undefined --import-memory --strip-debug --export-table --export main --export stackSave --export stackRestore --export stackAlloc --export __data_end --export __wasm_call_ctors --export __errno_location --export malloc --export free --export _get_tzname --export _get_daylight --export _get_timezone --export memset --export memalign --export emscripten_GetProcAddress --export strstr -z stack-size=5242880 --initial-memory=33554432 --no-entry --max-memory=2147483648 --global-base=1024' failed (1)

Getting the same error on Ubuntu WSL 20.04

wasm-ld: error: unable to find library -lavdevice wasm-ld: error: unable to find library -lswresample

Actually just had to run git submodule update --init --recursive

Now I just get image

Not sure why it's looping like that..

gregorym commented 2 years ago

@seminelee @Aeroxander Were you able to figure this out? I'm running into the same issue?

I also tried to load the wasm manually as such, but it looks obfuscated so i don't know how to use it.

      WebAssembly.compileStreaming(fetch('/ffmpeg-core.wasm'))
        .then(function (mod) {
          var imports = WebAssembly.Module.imports(mod);
          console.log(imports);
        });

Screen Shot 2021-09-29 at 10 56 08 PM

Aeroxander commented 2 years ago

@gregorym are you also getting the loop error, or the unable to find library error?

gregorym commented 2 years ago

@Aeroxander None of the above. I've tried 2 things. (@jeromewu )

  1. Just change the corePath.

      const ffmpeg = createFFmpeg({
        corePath: 'ffmpeg-core.js',
        log: true
      });
    
      await ffmpeg.load();

    this results in this error (same as @marcofugaro) :

    ...
    [info] ffmpeg-core.js script loaded
    [fferr] Assertion failed: Cannot call unknown function proxy_main, make sure it is exported
    Uncaught (in promise) RuntimeError: abort(Assertion failed: Cannot call unknown function proxy_main, make sure it is exported). Build with -s ASSERTIONS=1 for more info.
  2. I tried to load the wasm manually, as described above. In this case, it's not complaining but i don't know how to move forward from there.

gregorym commented 2 years ago

I have written an article about it, but in Chinese: https://juejin.cn/post/6998876488451751973

@seminelee Can you share in a gist the output of your compilation (.js, .wasm) in a gist? I tried to follow your article, but the build still fails for me.

Aeroxander commented 2 years ago

@gregorym Found the fix! Just need to change proxy_main to main.

https://github.com/ffmpegwasm/ffmpeg.wasm/blob/2d6fae83888950f98483d0f7dfcde6745a34ac92/src/createFFmpeg.js#L91

gregorym commented 2 years ago

@Aeroxander Fantastic! Do you mind creating a gist with the appropriate files?

Aeroxander commented 2 years ago

Done! https://gist.github.com/Aeroxander/96cee8b7fb8ba73d090abecb182dd493

I'm actually not able to compile it fully:

wasm-ld: error: unable to find library -lavdevice wasm-ld: error: unable to find library -lswresample

EDIT: Was able to download the compiled files from https://github.com/ffmpegwasm/ffmpeg.wasm-core/actions/runs/1050801687 actually :D now everything is working!

selmalee commented 2 years ago

@gregorym Found the fix! Just need to change proxy_main to main.

https://github.com/ffmpegwasm/ffmpeg.wasm/blob/2d6fae83888950f98483d0f7dfcde6745a34ac92/src/createFFmpeg.js#L91

yes! I have submited a pr before.

selmalee commented 2 years ago

Downloading and trying the single-threaded version posted here results in this issue:

image

Just need to change proxy_main to main. I have submited a pr before.

Number0131 commented 2 years ago

The artifact is not available anymore, can someone please put it back online somewhere?

luca-demma commented 2 years ago

I plan to release it after updating ffmpeg.wasm, but if you are in a hurry, you can download the singled threaded version here:

https://github.com/ffmpegwasm/ffmpeg.wasm-core/actions/runs/1050801687 (You can download it in artifacts section)

And you can check here for how to use it: https://github.com/ffmpegwasm/ffmpeg.wasm-core/tree/n4.3.1-wasm/wasm/tests/utils/st

(Sorry I only write a node.js version for testing, but it shouldn't be too hard to write a web worker version on your own)

Artificat isn't available anymore. Could someone upload it again pls?

hoomanaskari commented 2 years ago

I believe it makes sense to add an option to disable the WASM threads and use a single core (be it that it makes it slower). ffmpeg.js is massive and extremely slow and does not support most of the options we need, so it is not an option for us. At the same time, any attempt to use CORP and COEP disables Stripe, Intercom, and many other necessary integrations on our production website, which in effect makes ffmpeg.wasm not production-ready.

What happened to SharedArrayBuffer after the Spectre is fairly new and it's going to take some time for all the other companies out there to jump on the cross-origin isolation bandwagon.

Currently, there is only one way to use ffmpeg.wasm in production, which is by signing up for an origin trial to be able to use SharedArrayBuffers without cross-origin isolation, but this only works on Chrome, and only until Chrome 103, after which we are back to square one. There is some hope according to this article that options like Cross-Origin-Opener-Policy: same-origin-allow-popups might work in the future, but no one knows yet how many of those integrations would break again, back to my initial statement, without this option ffmpeg.wasm is not going to be actually production-ready.

zackees commented 2 years ago

The shard buffer issue is a blocker for this code. Please have a single version wasm available!

chicken-suop commented 2 years ago

@seminelee @Aeroxander ~I'm getting the same error when trying your build script. Any ideas on how to resolve it?~

wasm-ld: error: unable to find library -lavdevice
wasm-ld: error: unable to find library -lswresample

EDIT: I sorted above error by removing -Llibavdevice and -lavdevice from emcc args.

libx264

@seminelee Do you know how to add support for libx264? I tried adding --enable-encoder=libx264 and --enable-libx264 but I'm getting this error:

17 warnings generated.
emcc: warning: EXTRA_EXPORTED_RUNTIME_METHODS is deprecated, please use EXPORTED_RUNTIME_METHODS instead [-Wdeprecated]
wasm-ld: error: libavcodec/libavcodec.a(libx264.o): undefined symbol: x264_levels
wasm-ld: error: libavcodec/libavcodec.a(libx264.o): undefined symbol: x264_levels
wasm-ld: error: libavcodec/libavcodec.a(libx264.o): undefined symbol: x264_levels
emcc: error: '/home/ta/ffmpeg/emsdk/upstream/bin/wasm-ld -o wasm/dist/ffmpeg-core.wasm -Llibavcodec -Llibavfilter -Llibavformat -Llibavresample -Llibavutil -Llibpostproc -Llibswscale -Llibswresample /tmp/emscripten_temp__as0855l/ffmpeg_opt_0.o /tmp/emscripten_temp__as0855l/ffmpeg_filter_1.o /tmp/emscripten_temp__as0855l/ffmpeg_hw_2.o /tmp/emscripten_temp__as0855l/cmdutils_3.o /tmp/emscripten_temp__as0855l/ffmpeg_4.o libavfilter/libavfilter.a libavformat/libavformat.a libavcodec/libavcodec.a libswresample/libswresample.a libswscale/libswscale.a libavutil/libavutil.a -L/home/ta/ffmpeg/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten /home/ta/ffmpeg/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten/libSDL2.a -lGL -lal -lhtml5 -lstubs -lnoexit -lc -lcompiler_rt -lc++-noexcept -lc++abi-noexcept -ldlmalloc -lc_rt -lsockets -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr --import-undefined --strip-debug --export-if-defined=main --export-if-defined=__start_em_asm --export-if-defined=__stop_em_asm --export=stackSave --export=stackRestore --export=stackAlloc --export=__wasm_call_ctors --export=__errno_location --export=_get_tzname --export=_get_daylight --export=_get_timezone --export=malloc --export=memalign --export=free --export=memcpy --export=__dl_seterr --export-table -z stack-size=5242880 --initial-memory=33554432 --no-entry --max-memory=2147483648 --global-base=1024' failed (returned 1)

This is the updated build1.sh I use: https://gist.github.com/chicken-suop/f1fa1f665d699f0d20880a7ccacd7940

chicken-suop commented 2 years ago

Currently, there is only one way to use ffmpeg.wasm in production

Not true. You can compile a single core wasm yourself. I've done that, and it works fine in prod, as long as you can accept average speeds.

channyeintun commented 2 years ago

If I set headers for cross origin isolation which is needed to enable shared array buffer, I cannot download things from other site. Could anyone has a solution to that problem?

chicken-suop commented 2 years ago

@channyeintun You can build your own ffmpeg.wasm single thread that doesn't need shared array buffer. @seminelee made some comments above about how to do it. I shared the build1.sh file I use to build my own version. Only thing I haven't figured out is how to enable libx264 encoder