$ show jeffvli/feishin
Feishin is a feature-complete self-hosted music player client, delivered as an Electron desktop application and a standalone web build. In production it connects to Subsonic/OpenSubsonic, Navidrome, or Jellyfin servers and presents their libraries (albums, artists, playlists, folders, genres, radio) through a React 19 + Mantine 9 UI. Playback is performed client-side through multiple engines: MPV via an IPC bridge, an HTML5/web-audio engine with gapless transition and crossfade curve math, and DLNA speaker casting via SSDP discovery and SOAP control. It also ships a companion mobile remote web app (src/remote) that controls the desktop player over a WebSocket-based protocol, including queue, playlists, and radio. The repository is purely an application; its only data-related surfaces are integrations with external music-server APIs and client-side caching/validation logic. Architecturally, the app is split into an Electron main process (src/main) housing platform features — lyrics providers (Genius, NetEase, Lrclib, SimpMusic), DLNA, Discord RPC, MPRIS, custom-theme file watching, and a taglib-wasm tag editor — a typed preload IPC bridge (src/preload), and a feature-foldered React renderer (src/renderer). Data flows through TanStack React Query with structured per-server query keys and optimistic mutations; Zustand stores (with persistence and migration logic) manage player/settings/auth/app state; a typed event emitter decouples list, queue, and player components. Additional subsystems include a smart-playlist query builder, word-level synchronized karaoke lyrics with furigana/romaji conversion, scrobbling, Auto-DJ, internet radio, audio visualizers (Butterchurn, AudioMotion), and an extensive theming/i18n surface (30+ themes, 40+ locales). The codebase is very actively maintained with CI covering build/release on all desktop platforms, Docker, and updates. The strongest, most reusable craftsmanship sits in self-contained subsystems: the dual-player web audio engine, the lyrics animation engine, hand-rolled ThumbHash/BlurHash placeholder decoders, a Zod-based response-validation layer, and generic polymorphic component utilities. The tradeoff is breadth over polish: near-identical list/filter/grid/table variants are copy-pasted per entity, virtual-table hooks are tightly coupled to DOM structure, isElectron() guards are scattered throughout, and visible unit tests are minimal. It is a solid reference for Electron + React music-player architecture, but extracting individual features requires care due to internal coupling.
The LLM identified 6 files worth highlighting for reuse:
Dual-HTML5-audio-engine implementation with gapless transitions, configurable crossfade curves (dip/equal-power/constant-power, with documented math references), network retry/fallback, and volume normalization. It demonstrates non-obvious web audio engineering and could be extracted into any music player that needs seamless track-to-track playback.
Word-level synchronized lyric animation engine that converts timed cue lists into continuous animation progress states with autoscroll. Self-contained and generic enough to power any karaoke-style lyric or subtitle rendering experience with minimal adaptation.
Self-contained ThumbHash decoder that converts compact base64 thumbnail hashes into canvas images for use as low-fi placeholders. Extracted and adapted from upstream work, it provides dependency-free placeholder generation suitable for any image-heavy UI with bandwidth constraints.
Env-flag-gated Zod schema validation for external music-server API responses that logs unknown/new fields rather than failing silently. It is a cautious consumer-side adapter pattern for third-party JSON APIs that drift over time, and is directly reusable for any project integrating with loosely versioned external APIs.
Generic polymorphic component factory that allows a React component's root element to change at runtime (e.g., div vs button vs Link) while preserving full TypeScript prop inference. Small, zero-dependency, and safely extractable into any React + TypeScript component library.
Converts Japanese lyric text into furigana/romaji reading overlays via kuroshiro, aligning readings to word-level cues for synchronized lyric display. Demonstrates non-trivial CJK text-processing integration and is reusable for any app needing per-character reading annotations for Japanese content.