Closed Yahav closed 1 year ago
I think this is a good idea. I'm thinking it could be implemented slightly differently though.
The bulk of the code size is consumed by the wasm-audio-decoders
and the synaudio
libraries. The metadata functionality is actually quite small in comparison, probably less than 10kB.
I think it would be good to have these features able to be selectively enabled / disabled so that when they are disabled, the extra code isn't bundled when used with a bundler such as webpack or rollup.
One main example would be that if you only ever use Opus for your stream, you won't need the MP3 or FLAC decoders, which would save about 150kB. Or if you don't want iOS support / WebAudio, you could remove the decoders altogether.
This kind of change would require some significant refactoring of the existing code, but I'll take a look at this.
@eshaz Is there anyway we can have a quick conversation about that?
We can, but I would prefer to use this issue thread so that others can reference this in the future. Will that work?
I think it would be good to have these features able to be selectively enabled / disabled so that when they are disabled, the extra code isn't bundled when used with a bundler such as webpack or rollup.
One main example would be that if you only ever use Opus for your stream, you won't need the MP3 or FLAC decoders, which would save about 150kB. Or if you don't want iOS support / WebAudio, you could remove the decoders altogether.
You are absolutely right, that is even better :) If we're going this route, imho the best way to achieve that is not to pre-configure which modules/decoders/mechanisms you're going to use, but rather have them dyanmically imported on a "need" basis, for instance, if an Opus stream is initiated and we're on a platform that doesn't support native playback, await import() the desired module to handle this situation, same goes for the metadata mechanisms and cross-play feature.
await import() the desired module
That's a good idea, and probably the way to go.
It would be preferable to have the dependencies pulled in as needed, but I'm wondering if bundlers would be able to evaluate the condition whether or not to execute the import
if it happens during runtime. There might have to be a hard coded parameter set on the library that bundlers could use to evaluate the conditional import
statements and strip out those unused dependencies.
It seems reasonable for those who want to save a couple hundred kilobytes to explicitly enable / disable features if it can't be done at runtime. Just for reference, the minified bundle with all features including MP3, Flac and Opus audio decoders is 273KiB.
@Yahav, it turns out the await import()
solution works great with webpack.
If you want to take a look, I have #164 that splits the icecast-metadata-player
into separate files that are downloaded as needed by the library. This should allow for a bit less data to be loaded on the initial page load.
Amazing! I'll have a look into this later this week. This dynamic import loads the different kind of encoders, how about the rest of the optional mechanisms, like the metadata fetching, are those something that you might be able to dynamically import as well?
The metadata fetching isn't all that much code, and it's tightly integrated with everything else so I'm going to leave that built in for now.
The main reason to do this is to reduce the initial load time and total size, which is enhanced the most by deferring the decoders.
Not sure if that's intended. but when setting the playback method to html5, the mediasource.js file is loaded anyway. If you select mediasource as the playback method, it loads it twice, once when the page loads and again when you play the audio.
@eshaz
As an addition to the above reply.
I found out that we can save further size by dynamically loading the EmscriptenWasm.js as well, it takes a rather large size of each encoder..
It should be good as is. That file is needed for the WASM audio decoders to function, so it all needs to load if one of the decoders is also needed.
@eshaz ok. What about that one though: https://github.com/eshaz/icecast-metadata-js/issues/163#issuecomment-1518690986
It preloads since most browsers use mediasource by default (everything except iOS), and then loads it again from cache in the import
. The preload made starting playback a bit more responsive at the cost of just a few extra KB downloaded for iOS users.
So, you've created a cross-platform, cross-encoding stream player with a unified API here which is not something to be taken lightly. I feel like there should be a version of this which is simply and only the streaming playing capabilities, stripping the whole metadata related dependencies and code could make the package really lightweight which is very desirable. Will you consider this? I might be able to sponsor this fork as well should you decide its a good idea.