eshaz/wasm-audio-decoders

Worker necessity

dy opened this issue · 2 comments

dy commented

Hi @eshaz! I'm thinking to take your decoders as foundation for new version of audio-decode. I have one consideration about workers, would like to know your opinion.

I found out that you export *Worker entry for all encoders.
It seems to me that has a couple of gotchas.

  1. It increases the final decoder bundle size, which could be somewhat less.
  2. Safari workers don't support spawning, in other words, Worker class is not available in globalThis worker context. As a result your decoders require polyfill like pseudo-worker to let them work in safari workers.

It makes me thinking - wouldn't that be more compact and easier to leave decoders function minimalistic single-threaded and leave up to user to implement parallelizing? Is there any benefit added by your workers over the naive single-threaded fork?

eshaz commented

@dy Thanks for the question.

It's not strictly necessary for this library to have the built-in Worker implementation, but it is one of the core features of the library for these reasons:

  1. Decoding is a relatively computationally intense operation, and executing it on the main thread will freeze any other operations on your web page, or NodeJS app. Having parallelism work out of the box eliminates this issue without having to do any extra work as a user. Also, as a user of this library myself in a few other libraries I maintain, I don't want to have to rewrite the worker implementation every time I use this.
  2. If I left the burden of running this library in a Worker to the user, they would first need to figure out how to load the source code into a Worker. This is a surprisingly difficult problem since the options are to either stringify all of the code along with any dependencies (difficult and in some cases impossible when using bundlers / minifiers), or load as a separate file (requires special environment considerations e.g. where to host the file). They would also need to write the API layer to communicate to and from the worker. This is not as difficult, but would be cumbersome.

The worker implementation does add a couple KBs of extra JavaScript, but the bulk of that is in @wasm-audio-decoder/common which is a shared dependency that is only installed once when multiple decoders are used in an application. The vast majority of the bundle size is consumed by the WASM binary data.

On your second point, it's probably advantageous to have the decoder operate in a nested worker, if there's some other code happening in first worker layer that benefits from threading. It's unfortunate Safari doesn't support this, but you could do a simple check to use the main thread version if nested Workers aren't supported: const DecoderClass = globalThis.Worker ? DecoderWorker : Decoder;. Safari isn't exactly on the cutting edge when it comes to web standards. Interestingly enough, Safari limitations are what inspired this library since I couldn't use MediaSource with iOS Safari in my other library, icecast-metadata-player!

dy commented

If that's not much of a burden, I can agree. Just wanted to raise these concerns. Thank you!