@soundws/stem-player v2.0.0-beta.18
General
A high performance streaming Stem Player, utilising capable of playing multiple stems allowing the user to control the volumes of each stem.
See this live example of our stem player
Contributing
This repo is a subtree split of our monorepo which will be made public in due course. We cannot process any pull-requests to this repo. Please contact us for help.
Installation
simply execute
npm install @soundws/stem-player
or using yarn
yarn add @soundws/stem-player
Usage
The component can be either instantiated as HTML
<script type="module">
import { defineCustomElements } from '../dist/soundws-stem-player.es.js';
// first register the custom elements
defineCustomElements();
</script>
<soundws-stem-player row-height="60px" sample-rate="22050">
<soundws-stem-player-controls
label="A label"
wave-color="white"
wave-progress-color="rgb(0, 206, 224)"
></soundws-stem-player-controls>
<soundws-stem
label="Drums A"
src="https://your-cdn-com/drums.m3u8"
waveform="https://your-cdn-com/drums.json"
volume="0.1"
>
</soundws-stem>
<soundws-stem
label="Vocals"
src="https://your-cdn-com/vocals.m3u8"
waveform="https://your-cdn-com/vocals.json"
muted="true"
volume="0.2"
></soundws-stem>
</soundws-stem-player>
or using javascript
import { defineCustomElements } from '@soundws/stem-player';
// first register the custom elements
defineCustomElements();
// create the stems-player web-component
const player = document.createElement('soundws-stem-player');
// append the controls web-component
const controls = document.createElement('soundws-stem-player-controls');
controls.label = 'Stems rule!';
player.appendChild(controls);
// append a stem web-component
const drums = document.createElement('soundws-stem');
drums.label = 'Drums';
drums.src = 'https://your-cdn-com/drums.m3u8;
drums.waveform = 'https://your-cdn-com/drums.json';
player.appendChild(drums);
// append a stem web-component
const vocals = document.createElement('soundws-stem');
vocals.label = 'Vocals';
vocals.src = 'https://your-cdn-com/vocals.m3u8;
vocals.waveform = 'https://your-cdn-com/vocals.json';
player.appendChild(vocals);
// listen to some events
player.addEventListener('timeupdate', () => { /* do something */ });
player.addEventListener('end', () => { /* do something */ });
See docs for more information.
Demo
Clone this repo and run
npm install
npm start
Browser Support
The Player works in browsers supporting the Web Audio API. This includes most modern browsers.
The stem player is built as a web-component which is supported natively by most modern browsers.
A bundles ES module is provided, transpiled to support modern browsers.
For targeting older browsers, you can utilise your own build system.
Polyfills for web-components exist for support for older browsers.
Audio
The player consumes m3u8 playlist files known from the HLS protocol.
The audio is split up into chunks and served (over simple HTTP) separately.
Why HLS and not just download whole files? Downloading and decoding, for example, 10 5minute audio files will consume bandwith and bloat memory: each minute of every audio file worth of mp3 data is decoded into 44k PCM data and will consume roughly 100mb. By using live streaming we not only speed up playback, we also reduce the memory footprint.
Why not progressive download? We need to use the web audio API to achieve precise synchronized playback.
See also
- https://ffmpeg.org/ffmpeg-formats.html#toc-hls-1
- https://ffmpeg.org/ffmpeg-formats.html#toc-segment_002c-stream_005fsegment_002c-ssegment
In due course we will release a docker image to make this process easier.
Waveforms
Because we don't download the entire audio file, we cannot analyse the audio so that we can display a nice waveform. So unfortunately these also need to be pre-generated. Although inconvenient, it is probably good practice anyway as a waveform in json format is very small in size; there is no need to re-compute it time and time again.
See here for info on how to generate compatible waveforms
In due course we will release a docker image to make this process easier.
ES modules and bare imports in the browser
This
import { defineCustomElements } from '@soundws/stem-player';
should work fine when using node, webpack etc. to create a bundled application.
However when using ES modules directly in the browser this will lead to an error:
failed to resolve module specifier "lit". Relative references must start with either "/", "./", or "../".
In order to resolve this we need to rely on import-maps. This is because module resolution in the browser works differently from what we are used to from Node.
<script type="importmap">
{
"imports": {
"lit": "https://cdn.jsdelivr.net/npm/lit-element@3.3.2/+esm"
}
}
</script>
<script type="module">
import { defineCustomElements } from 'node_modules/dist/soundws-stem-player.es.js';
defineCustomElements();
</script>
License
Copyright (C) 2019-2023 First Coders LTD
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago