Show HN: A music delivery service built around the WebAudio API
ampl.fi
ampl.fi
The current process is rather simple: I utilize M3U8 for storing segment information, and manually parse the file when a play request is received. I grab the first few (Opus-encoded) segments, pass them through an OfflineContext to maintain a specific sample rate, and store the resulting buffer in a wrapper object. Each object is stored in an array, and is responsible for re-creating the AudioNode when stopping or starting.
The hardest part about this (for me at least) was fetching and scheduling accurately while the player is running. I group segments requests together, and schedule after each group has finished downloading. It's not perfect, as I occasionally get pops between each segment: Chrome seems to be less noticeable than Firefox in this regard. I schedule based on the buffer duration, but there seems to be subtle differences between browsers.
In any case, I've had quite a bit of fun working on this project.
Could you elaborate a bit more on what the site does, perhaps in an ELI5 way (explain it like I'm 5 years old)? It's not entirely obvious at a glance, i.e is it like SoundCloud?/How does it differ?/Can it be used to create music?
In terms of interaction, it's similar to SoundCloud. I've been using SoundCloud for years - just right after they transitioned to their V2 site. I've also used Bandcamp for selling my own music, and always felt their approach was transparent and fair when it came to monetization. When I started this project, a little bit of both went into the design and structure.
But I don't really understand what the texts want to tell me.
- Is this for people who like to listen to music (a music player)?
- Is it for people who like to create music where they can upload and sell it (like a store)?
Somehow I have a feeling it is both, but 'music delivery service' feels to me like an abstract term (what is the difference to 'website for sharing music'). Might be worth iterating over those parts again.
Nevertheless, cool project :-)
Honestly, I wasn't sure how to label it myself: I'm terrible with describing things. I'll be sure to give it some thought though.
seems to not work on safari 12 (Mojave). as in... press the play button, state changes, no audio, no other activity happens.
as with many webby things these days.... works fine on chrome, not on safari.
See this issue:
https://github.com/goldfire/howler.js/issues/706
I could fallback to something like MP3, which is something I'm looking into.
I really need to add some type of alert for users using Safari, at least for the time being. Thanks for reminding me!
Can you say something about the specifics? Like – can I use it like a locker service similar to Google Play Music? If so, how many tracks can I upload?
At the moment, the upload limit is 15 tracks a month. Since this is a subscription-less service, there's no way to subscribe to a plan for unlimited uploading. We can always override the limit on a per user basis, depending on your needs.
* An POST request is sent to the web server. If the file is valid, it is moved via FTP to a local server. I then create a message for RabbitMQ to add to a transcode queue.
* A worker listening on the channel gets the job, and does all the needed work to make the file "streamable", e.g. segmenting and encoding file parts, creating the M3U8, generating the waveform, storing to S3, etc. Throughout the process, progress is saved in Redis, which is made available to the client for visual feedback
* Once the process is done, an identifier is generated, which the client refers to when saving any modifications to the track information. We primarily use MariaDB.
The transcode process is the most complex piece of the puzzle, of course. Everything else is pretty much CRUD operations.
Pardon the probably stupid question, but is that (splitting into several files) really necessary? Isn't supporting HTTP range requests enough?
Or is it because clients tend to download the whole file, even when the listener is still at the very beginning and might skip, meaning wasted bandwidth?
When I had started the project, I saw how other streaming sites fetched their audio, and I saw a pattern in individual GET requests for segments. I thought, "Hey, they're doing this for a reason, and even though I don't fully understand this reason, maybe I should do it to." At the time, I think I justified it by thinking that someone who wants to rip the stream file would have to piece the track together versus just requesting the full track.
In the end, it really doesn't matter: anyone who is willed enough can get whatever is being sent to their client. It's one of those moments where I didn't bother to really think it through and factor in the practicality aspect. I'd like to go back and re-visit byte-range requests, though, just to see how it would work differently.
Quite a number of older Android clients, like TVs, cheap phones, etc. don't have an up-to-date browser on them, and they will make the first range-request correctly (with a byte range that reflects the browser knows the full content-length, etc)...
But you'll have to build your own scheduling system to pull in further requests, which is painful, clumsy and doesn't always work.