An online player for your offline music and audio-books
This is an experimental project to build a simple web based audio player with first-class support for audio books. When complete, ths should be able to:
- Play all audio files supported by the browser
- Support/UI for all platforms including mobile
- Work offline (PWA)
- Display music metadata
- Album art
- Lyrics
- Other details
- Sort files semantically
- Keep a log of files played with start, end times of both the file and the clock so that audio-books can be resumed from anywhere quickly even if the user had fallen asleep in the middle of the book. (This happens to me quite a lot.)
- Save playlists (collections)
- Basic player functions:
- Play
- Pause
- Resume
- Stop
- Play Next File
- Play Previous File
- Fast Rewind
- Fast Forward
- Speed Control
- Pitch Control
- Repeat current song once/forever
- Repeat playlist
- Shuffle playlist (+altered by repeat option)
- Change volume
- Auto-scan folders to create playlists
- Equalizer and effects
- Clone the project and switch to directory
- Setup
pnpm
globally if not already installed:npm i -g pnpm
- Run
pnpm install
- Run
pnpm start
Some of the tools and design decisions might be different from what you are familiar when working with React. These might be replaced/abandoned in the future depending on how they will match the requirements.
- Vite is used as the bundler which uses esbuild for compilation and rollup for bundling.
- Using PNPM instead of NPM/Yarn.
- No state management libraries such as Redux/Mobx/XState/Recoil...; RxJS is used to create a redux + redux-observable/saga like environment which is more flexible and powerful.
- Using TailwindCSS: trying to minimize CSS use and completely avoiding CSS-in-JS. Utility class names are used and when necessary, class names are combined to make a new selector/class name in a PostCSS file. These class names are used semantically like how interfaces are used in OOP.
components
are organized in a tree based on where they are used. The logic required for each component is stored with the component semantically unless they impact the global state. New components are created to avoid deep prop-drilling, to avoid tree going too deep and when new features are introduced. Logic for cross-cutting concerns are in theutil
folder.reducer
,epics
andeffects
handle most of the top level application logic and need refactoring. OnlyApp
has direct access to global state, so there is no presentational vs. container component separation.