Skip to content

Twarga/Tplayer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

107 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Table of contents


✨ What’s new in v0.3.0

  • 🎞 YouTube playlist import — fetch a full playlist, select individual videos, set format/quality/metadata, and download as a batch. Auto-creates an app playlist on completion, matched by download history (no more fuzzy title guessing).
  • 🔎 Global search overlayCtrl+K command-palette style overlay for tracks, albums, artists, and playlists. Keyboard navigable (↑/↓/Enter/Esc).
  • 🖱 Track right-click context menu — Play Now, Add to Queue (Next/Last), Add to Playlist submenu, Toggle Favorite. Available in Library, Playlist Detail, and Home.
  • Playlist mass selection — checkbox per row, Select All, batch delete in a single SQLite transaction.
  • Virtualized grids — Albums, Artists, and Playlists use @tanstack/react-virtual. Libraries with 200+ albums no longer freeze.
  • 🚀 Single-transaction queue — playing an album/artist/playlist fires one queue:set IPC call instead of N sequential adds.
  • 🌓 Home polish — time-aware greeting, favorites section, real mosaic covers for album/artist/playlist cards.

See the full CHANGELOG.


✨ Features

Feature Description
🎵 Local-first library Scan any folder. Albums, artists, folders, and playlists — indexed locally with better-sqlite3
YouTube import Search or paste a URL, pick a video or full playlist, choose format/quality, and import via yt-dlp + FFmpeg
🎚 10-band equalizer Bundled presets (Flat, Bass, Treble, Vocal, Rock, …), persisted across sessions
📝 Queue & playlists Batch queue, shuffle, repeat, right-click context, mass selection, mosaic playlist covers
🔁 Last.fm scrobbling Authenticated session, now-playing updates, offline-tolerant scrobble queue
Linux media keys MPRIS via dbus-next — play/pause/next/prev/seek from keyboard, tray, or lock screen
🔎 Global search Ctrl+K command-palette overlay for tracks, albums, artists, and playlists
🎨 Editorial dark UI Warm ink-and-gold palette, big album art, thin dividers, direct controls
Fast & virtualized Virtualized grids keep 200+ album libraries snappy
🔒 100% local, private No accounts, no telemetry, no cloud sync. Your files stay on your machine

🖥 Screenshots

Tplayer home view with favorites, recent imports, and recommended albums



Detailed now-playing view with album art, queue, and EQ YouTube import view with search results and download options
Detailed now-playing — playback stays visible while browsing. YouTube import — search, pick, and download into your library.

🚀 Quick start

Requirements

  • Linux (primary target) or Windows
  • ffmpeg on your system path
  • yt-dlp on your system path (optional — only for YouTube import)

Linux (one-liner)

curl -fsSL https://twarga.github.io/Tplayer/install.sh | bash

This downloads the latest AppImage from GitHub Releases and installs it into ~/.local/bin.

Manual downloads

First run

  1. Pick a folder to scan — Tplayer indexes your library locally
  2. (Optional) Paste a YouTube URL in the YouTube tab to import audio
  3. (Optional) Connect Last.fm in Settings to scrobble
  4. Press Ctrl+K from anywhere to jump around

⌨ Keyboard shortcuts

Keys Action
Space Play / pause
Ctrl + K Global search
/ Seek −5s / +5s
/ Volume up / down
N / P Next / previous track
S / R / F Shuffle / repeat / favorite
Esc Close dialog or overlay

Linux media keys (play/pause/next/prev) also work globally via MPRIS.


🏗 Architecture

Tplayer/
├── src/
│   ├── main/       ← Electron main: SQLite, yt-dlp pipeline, MPRIS, Last.fm scrobbler
│   ├── preload/    ← Context-isolated bridge, typed IPC to the renderer
│   ├── renderer/   ← React UI — Home, Library, Albums, Artists, Playlists, YouTube, Settings
│   └── shared/     ← Domain types + IPC channel contracts (used by both sides)
├── site/           ← GitHub Pages landing page (index.html + styles.css)
├── assets/         ← Banner, screenshots, logo, install.sh
├── docs/           ← Brand, release checklist, production readiness, repo hygiene
├── build/          ← Packaging icons (icon.png, icon.ico)
└── .github/        ← Release + Pages workflows, issue/PR templates

Three-process Electron model with typed IPC boundaries:

┌───────────────────────────────┐      ┌──────────────────────────────────┐
│ Renderer  (src/renderer)      │      │ Main process  (src/main)         │
│ React 19 · Zustand · Tailwind │◀──▶ │ Electron · yt-dlp · FFmpeg       │
│ Virtualized grids · Radix UI  │ IPC  │ better-sqlite3 · MPRIS · Last.fm │
└───────────────────────────────┘      └──────────────────────────────────┘
              ▲                                      ▲
              │  shared types (src/shared)           │
              └──────────────────────────────────────┘
                 typed contracts through preload
                       (src/preload)

Stack: Electron 33 · React 19 · Vite 5 · TypeScript 5 · Tailwind CSS 3 · Zustand · Radix UI · @tanstack/react-virtual · better-sqlite3 · music-metadata · yt-dlp · fluent-ffmpeg · dbus-next


🧑‍💻 Development

Prerequisites

  • Node.js 18+ and npm
  • ffmpeg on your system path
  • yt-dlp on your system path (only if you want to test YouTube import)

Setup

git clone https://github.com/Twarga/Tplayer.git
cd Tplayer
npm install

Common scripts

npm run dev         # hot-reload dev app
npm run typecheck   # tsc --noEmit
npm run build       # compile main + preload + renderer
npm run lint        # eslint

📦 Packaging

npm run package:linux   # Linux AppImage
npm run package:win     # Windows NSIS installer
npm run package:dir     # Unpacked directory (fast smoke test)

Artifacts land in release/. Tagged pushes (vX.Y.Z) trigger the GitHub Actions release workflow, which builds the Linux AppImage and Windows installer and publishes them to GitHub Releases.


🔧 Troubleshooting

AppImage won’t run

chmod +x Tplayer-0.x.y.AppImage
./Tplayer-0.x.y.AppImage
# if your kernel rejects the default sandbox:
./Tplayer-0.x.y.AppImage --no-sandbox

YouTube import fails

yt-dlp --version           # confirm yt-dlp is installed and on PATH
pip install -U yt-dlp      # or your package manager's upgrade path

Media keys don’t work (Linux)

→ Confirm MPRIS is enabled on your desktop. Quick check:

playerctl --list-all       # should list 'tplayer' while the app is running

Library scan is slow the first time

→ Expected — first-run parses ID3/tag metadata for every file. Subsequent scans are incremental and fast.

Last.fm scrobbles don’t show up

→ Open Settings → Last.fm and confirm it shows Connected. Offline scrobbles are queued locally and flushed when the network returns.

Playback is silent on Linux

→ Tplayer uses the Chromium audio backend, so it follows the same output routing as Firefox or Chromium. Check PipeWire/PulseAudio output device.

ffmpeg not found

# Debian / Ubuntu
sudo apt install ffmpeg

# Fedora
sudo dnf install ffmpeg

# Arch
sudo pacman -S ffmpeg

🗺 Roadmap

  • Local playback, library scan, queue, EQ, favorites
  • YouTube video and playlist import, download history
  • Last.fm now-playing and scrobble
  • MPRIS Linux integration
  • Packaging — Linux AppImage + Windows NSIS
  • GitHub Pages landing page + release workflow
  • Virtualized grids & single-transaction queue
  • macOS packaging
  • Lyrics provider integration
  • Smart playlists / auto-mixes
  • Mobile remote control (MPRIS already exposed)

See docs/planning/remake.md for the complete roadmap and design notes.


❓ FAQ

Is Tplayer free?

Yes. Tplayer is free and open source under the MIT license. No accounts, no paid tiers, no telemetry.

Does it work offline?

Yes. Local playback, library browsing, queue, and EQ all work fully offline. Only YouTube import and Last.fm scrobbling need the network.

What audio formats are supported?

MP3, FLAC, M4A/AAC, OGG, and WAV. YouTube imports default to high-quality M4A via yt-dlp + FFmpeg.

Which operating systems are supported?

Linux is the primary target (AppImage). Windows installer ships as well. macOS packaging is planned.

Does Tplayer upload or collect my music?

No. Tplayer is fully local-first. Your files and listening history never leave your machine unless you enable Last.fm scrobbling.

Where do imported YouTube tracks live?

In the same library you already browse, tagged with source = 'youtube' in the database so the Home view can surface recent imports separately.

Why Electron and not a native toolkit?

Electron + React lets the UI move fast and stay editorial on Linux and Windows from a single codebase. Performance-critical work (scanning, queue, EQ, yt-dlp orchestration) happens in the Node main process, not the renderer.


📚 Project docs

Document Purpose
docs/brand.md Public identity: voice, colors, screenshot direction
docs/planning/remake.md Completed MVP work and post-MVP release plan
docs/release-checklist.md Release requirements and manual testing steps
docs/production-readiness.md B1–B10 production-preparation summary
docs/repository-hygiene.md Ignore list and clean-repo rules
CONTRIBUTING.md Local setup, commit scope, and contribution rules

🙌 Contributing

Contributions are welcome — especially around packaging, platform support, and UI polish. By participating in this project, you agree to abide by the Code of Conduct.

See CONTRIBUTING.md for setup, commit scope, and repo-hygiene rules. Before opening a pull request:

npm run typecheck
npm run build

Keep commits small and task-focused. UI changes should stay inside the warm-dark editorial direction described in docs/brand.md.


🔒 Security

If you discover a security issue, please do not open a public issue. See SECURITY.md for the private disclosure flow.


📄 License

MIT © Twarga


🙏 Acknowledgments

Tplayer stands on the shoulders of an incredible open-source ecosystem. Special thanks to:

  • yt-dlp — for making YouTube import reliable and respectful
  • FFmpeg — for doing the media heavy lifting
  • better-sqlite3 — fast, synchronous SQLite for Node
  • music-metadata — for clean tag parsing
  • electron-vite — for the nicest Electron DX today
  • Radix UI — for accessible headless primitives
  • Lucide — for the icon set
  • The Last.fm, MPRIS, and D-Bus communities for keeping desktop Linux media alive

Made with 🎵 and ☕ by Twarga
Without music, life would be a mistake.