Metadata-Version: 2.4
Name: musickit
Version: 0.6.2
Summary: Self-hosted music toolkit: convert / audit / retag rips into a clean tagged library, browse + play via a Textual TUI (local / internet radio / Subsonic-client / AirPlay), and stream over Tailscale via a Subsonic-compatible HTTP server.
Keywords: audio,music,ffmpeg,subsonic,tui,library-manager,musicbrainz,airplay,tailscale
Author: Morten Hansen
Author-email: Morten Hansen <morten@winterop.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Multimedia :: Sound/Audio
Classifier: Topic :: Multimedia :: Sound/Audio :: Conversion
Classifier: Topic :: Multimedia :: Sound/Audio :: Players
Classifier: Typing :: Typed
Requires-Dist: typer>=0.24.2
Requires-Dist: mutagen>=1.47.0
Requires-Dist: rich>=14.0.0
Requires-Dist: pillow>=11.0.0
Requires-Dist: httpx>=0.28.1
Requires-Dist: pydantic>=2.10.0
Requires-Dist: textual>=1.0.0
Requires-Dist: av>=13.0.0
Requires-Dist: sounddevice>=0.5.0
Requires-Dist: numpy>=2.0.0
Requires-Dist: fastapi>=0.136.1
Requires-Dist: uvicorn[standard]>=0.46.0
Requires-Dist: zeroconf>=0.148.0
Requires-Dist: pyatv>=0.17.0
Requires-Dist: watchdog>=6.0.0
Requires-Dist: tomli-w>=1.2.0
Requires-Python: >=3.13
Project-URL: Homepage, https://github.com/winterop-com/musickit
Project-URL: Repository, https://github.com/winterop-com/musickit
Project-URL: Documentation, https://winterop-com.github.io/musickit
Project-URL: Issues, https://github.com/winterop-com/musickit/issues
Project-URL: Changelog, https://github.com/winterop-com/musickit/releases
Description-Content-Type: text/markdown

# musickit

[![CI](https://github.com/winterop-com/musickit/actions/workflows/ci.yml/badge.svg)](https://github.com/winterop-com/musickit/actions/workflows/ci.yml)
[![PyPI version](https://img.shields.io/pypi/v/musickit)](https://pypi.org/project/musickit/)
[![Python 3.13+](https://img.shields.io/badge/python-3.13+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Documentation](https://img.shields.io/badge/docs-mkdocs-blue.svg)](https://winterop-com.github.io/musickit/)

Python 3.13 CLI for converting audio rips into a clean tagged library, browsing and playing it via a Textual TUI, and streaming it over Tailscale via a Subsonic-compatible HTTP server.

## Install

The lowest-friction way is [`uvx`](https://docs.astral.sh/uv/) — it downloads, caches, and runs the latest published `musickit` in one step. No install step required:

```bash
uvx musickit --help
```

For daily / persistent use (PATH-installed, no per-run network check):

```bash
uv tool install musickit
musickit --help
```

You'll also need `ffmpeg` and `ffprobe` on `$PATH` for the convert pipeline:

```bash
brew install ffmpeg            # macOS
sudo apt install ffmpeg        # Debian / Ubuntu
```

## Quickstart

```bash
uvx musickit convert ./input ./output       # convert
uvx musickit library audit ./output         # audit
uvx musickit tui ./output                   # TUI
uvx musickit serve ./output                 # Subsonic server
```

## Screenshots

The TUI: artist browser on the left, drilled into an album, 48-band visualizer at the top.

![Drilled-in album view](docs/screenshots/album-tracks.svg)

Fullscreen visualizer (`f`):

![Fullscreen visualizer](docs/screenshots/fullscreen-viz.svg)

More screenshots in the [TUI guide](https://winterop-com.github.io/musickit/guides/tui/).

## Documentation

Full docs are at **[docs/](docs/index.md)** — built with MkDocs Material. Run them locally:

```bash
make docs-serve     # http://127.0.0.1:8000
```

Or jump straight to:

- [Architecture](docs/architecture.md) — how all the pieces fit together (process model, data flow, audio subprocess, SQLite index, FFT visualizer)
- [Quickstart](docs/guides/quickstart.md) — end-to-end walkthrough including iPhone + Tailscale + Amperfy
- [musickit convert](docs/guides/convert.md) — codec / bitrate / enrichment matrix
- [musickit library](docs/guides/library.md) — audit rules + auto-fix + SQLite index
- [musickit tui](docs/guides/tui.md) — TUI: local + radio + Subsonic-client + AirPlay
- [musickit serve](docs/guides/serve.md) — Subsonic API + Tailscale + clients
- [Edge cases](docs/edge-cases.md) — every weirdness encountered on real rips
- [Roadmap](docs/roadmap.md) — what's next
- [Development](docs/guides/development.md) — directory layout + test patterns + commit style

## Status

v0.5.0 · ruff + mypy + pyright clean, full pytest suite green. Five top-level commands — `convert`, `library`, `inspect`, `tui`, `serve` — with `library` carrying the read / mutate / manage subcommands (`tree`, `audit`, `fix`, `cover`, `cover-pick`, `retag`, `index`). The TUI ships local-library playback, internet radio, Subsonic-client mode, AirPlay output (incl. pause + volume routing), mDNS discovery, ReplayGain normalisation, an incremental `/`-filter, in-place tag editing (`e` for track / album-wide), a 48-band FFT visualiser, and click-to-seek on the progress bar. Audio decoder + sounddevice callback run in a separate process so UI work in the main interpreter can't stall playback. The server is OpenSubsonic-compatible (`multipleGenres`, `transcodeOffset`, `songLyrics` extensions) and tested against Symfonium / Amperfy / play:Sub / Feishin clients on iOS / Android / desktop. A persistent SQLite library index at `<root>/.musickit/index.db` makes cold starts skip the filesystem walk + tag read; the filesystem watcher does per-album incremental rescans.

## License

See LICENSE in the repo root.
