Metadata-Version: 2.4
Name: px7-music
Version: 1.2.0
Summary: Terminal music player — stream YouTube audio from your CLI
Author-email: px7nn <px7nnn@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/px7nn/px7-music
Project-URL: Repository, https://github.com/px7nn/px7-music
Project-URL: Issues, https://github.com/px7nn/px7-music/issues
Keywords: music,cli,youtube,terminal,streaming
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Environment :: Console
Classifier: Topic :: Multimedia :: Sound/Audio
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: yt-dlp>=2024.0.0
Requires-Dist: python-mpv>=1.0.0
Requires-Dist: python-vlc>=3.0.0
Dynamic: license-file

<div align="center">

<img width="600" alt="PX7 Terminal Music" src="https://github.com/user-attachments/assets/f1607e3a-e1fe-42df-a455-155aca1a77c3" />

<br>

![](https://img.shields.io/badge/interface-CLI-black?style=for-the-badge&color=03A907&labelColor=000000)
&nbsp;
![](https://img.shields.io/pypi/v/px7-music?style=for-the-badge&color=03A907&labelColor=000000) 


<br>

</div>


# PX7 Terminal Music

Stream music from YouTube directly in your terminal. No browser, no GUI, no nonsense.  
  
PX7 is a lightweight CLI music player that searches YouTube via `yt-dlp` and streams audio through `mpv` or `vlc` — no downloads, no accounts, no ads. Just type a song name and play.


```
>> search radiohead
>> play 2
```

## Features

- Search and stream directly, no ads
- Persistent favorites and playlists saved across sessions
- Queue shuffling and hands-free autoplay mode
- MPV and VLC support

## Preview

<p align="center">
  <img width="415" src="https://github.com/user-attachments/assets/6475eaf6-691f-4a3f-b4c9-1c0e846506c4" />
</p>

## Requirements

- **Python 3.10+**
- MPV *(recommended)* or VLC


## Installation

### Install via pip (Recommended)

```
pip install px7-music
```

Start the application:
```
px7-music
```
You will see a prompt:
```
>> 
```

## Usage

```
command [arguments] [--flags]
```

### Search & Play

| Command | Args | Description |
|---------|------|-------------|
| `search` / `/s` | `<query>` | Search YouTube and fill the results |
| `play` | `[index]` | Play a track from the current results and load them into queue |

> `play` with no arguments defaults to `play 1`.


**Search flags:**

| Flag | Default | Description |
|------|---------|-------------|
| `--limit=<n>` | `6` | Number of results to fetch |
| `--no-postfix` | off | Disable the auto-appended `"song"` keyword |
| `--p` | off | Fetch tracks from a YouTube playlist URL instead of searching |

<details>
<summary><b>Examples</b></summary>

```
>> /s https://youtube.com/playlist?list=... --p
>> search hotel california --limit=1
>> /s my dear melancholy
>> play 2
```

</details>

---

### Playback Controls

| Command | Description |
|---------|-------------|
| `pause` | Pause the current track |
| `resume` | Resume a paused track |
| `next` | Skip to the next track in queue |
| `prev` | Go back to the previous track |
| `seek` | Show current playback position |
| `seek <position>` | Jump to a position in the current track |

<details>
<summary><b>Seek formats</b></summary>

```
>> seek           # show current position
>> seek 1:30      # jump to 1 min 30 sec (mm:ss)
>> seek 90        # jump to 90 seconds
>> seek +30       # skip forward 30 seconds
>> seek -10       # rewind 10 seconds
```

</details>

---

### Queue & Info

| Command | Description |
|---------|-------------|
| `queue` | List all tracks in the current queue |
| `current` / `now` | Show info about the currently playing track |
| `load` | Load last results into queue and reset playback |
| `shuffle` | Shuffle the queue (current track stays at top) |

<details>
<summary><b>Examples</b></summary>

```
>> /s the weeknd
>> load
>> shuffle
>> play 1
```
> **Note:** Viewing `queue`, `favs`, or a playlist loads them as the active results, so `play <index>` works directly after them.

</details>

---

### Favorites

Save tracks across sessions. Favorites persist to `~/.px7/.px7_favorites.json`.  
New favorites appear at the top (newest first).

| Command | Args | Description |
|---------|------|-------------|
| `fav add` | | Add the currently playing track |
| `fav add` | `<index>` | Add a track from the queue by index |
| `fav add` | `all` | Add all queued tracks |
| `fav remove` | `<index>` | Remove a favorite by index |
| `fav remove` | `all` | Clear all favorites *(asks for confirmation)* |
| `favs` | | List all saved favorites |

**Favs flags:**

| Flag | Default | Description |
|------|---------|-------------|
| `--order=<by>` | newest first | Sort by: `name`, `date-added`, `duration` |
| `--limit=<n>` | all | Show only the top N favorites |
| `--reverse` | off | Reverse the sort direction |

> **Tip:** `favs` loads your favorites as results, so you can `load` → `play` them directly.

<details>
<summary><b>Examples</b></summary>

```
>> fav add
>> fav add 3
>> fav add all
>> fav remove 2
>> favs
>> favs --order=name
>> favs --order=duration --limit=5
>> favs --order=date-added --reverse
```

</details>

---

### Playlists

Organize tracks into named playlists. Playlists persist to `~/.px7/.px7_playlists.json`.  
New tracks in a playlist appear at the top (newest first).

| Command | Args | Description |
|---------|------|-------------|
| `pl` / `pl list` | | List all playlists |
| `pl create` | `<name>` | Create a new playlist |
| `pl delete` | `<name>` | Delete a playlist *(asks for confirmation)* |
| `pl rename` | `<old> -> <new>` | Rename a playlist |
| `pl add` | `<name>` | Add the currently playing track to a playlist |
| `pl add` | `<name> <index>` | Add a queue track by index to a playlist |
| `pl add` | `<name> all` | Add all queued tracks to a playlist |
| `pl remove` | `<name> <index>` | Remove a track from a playlist by index |
| `pl show` | `<name>` | Display tracks in a playlist |
| `pl <name>` | | Shorthand for `pl show <name>` |
| `pl load` | `<name>` | Load a playlist into the queue |

**pl show / pl load flags:**

| Flag | Default | Description |
|------|---------|-------------|
| `--order=<by>` | newest first | Sort by: `name`, `date-added`, `duration` |
| `--limit=<n>` | all | Limit number of tracks shown or loaded |
| `--reverse` | off | Reverse the sort direction |

> **Tip:** `pl load` sets the loaded playlist as active results, so `load` → `play` and `shuffle` work directly after it.

<details>
<summary><b>Examples</b></summary>

```
>> pl create Chill Mix
>> pl add Chill Mix
>> pl add Chill Mix 3
>> pl add Chill Mix all
>> pl Chill Mix
>> pl load Chill Mix
>> pl load Chill Mix --order=name --reverse
>> pl remove Chill Mix 2
>> pl rename Chill Mix -> Evening Vibes
>> pl delete Evening Vibes
```

</details>

---


### Volume

```bash
>> volume         # print current volume
>> volume 70      # set volume to 70
```

---

### Auto-Play Mode

Hands-free mode that plays through the queue automatically.

```
>> autoplay
```
> Alias: `/a`

<details>
<summary><b>Auto-Play Keybinds</b></summary>

| Key | Action |
|-----|--------|
| `N` / `>` / `.` | Next track |
| `P` / `<` / `,` | Previous track |
| `SPACE` | Pause / Resume |
| `+` / `=` | Volume up (+10) |
| `-` / `_` | Volume down (−10) |
| `R` | Force refresh display |
| `Q` / `X` | Quit autoplay mode |

</details>

---

### Utility

| Command | Description |
|---------|-------------|
| `latency` | Check network latency |
| `clear` / `cls` | Clear the screen and redraw the banner |
| `help` | Show the help screen |
| `exit` | Quit PX7 Music |

---

<details>
<summary><b>How It Works</b></summary>

1. `search` queries YouTube via `yt-dlp` in metadata-only mode (fast, no download)
2. Results are stored as "last results"; `play <index>` loads them into the queue and starts streaming
3. `play <index>` fetches the direct audio stream URL and pipes it to mpv or vlc
4. Auto-play uses a thread-safe event queue to advance tracks without blocking the input loop
5. Favorites and playlists are saved to `~/.px7/` and persist between sessions

</details>

<details>
<summary><b>Project Structure</b></summary>

```
px7_music/
├── config.py               # yt-dlp options, defaults, file paths
├── main.py                 # entry point, command registration, main loop
├── core/
│   ├── handler.py          # command handlers (search, play, volume, fav, pl)
│   ├── parser.py           # command parser and flag parser
│   ├── latency.py          # network latency check
│   ├── seek_handler.py     # seek command parsing and dispatch
│   └── youtube.py          # yt-dlp search and stream URL extraction
├── library/
│   ├── favorites.py        # favorites persistence (load, save, add, remove)
│   └── playlists.py        # playlists persistence (create, delete, rename, add, remove)
├── player/
│   ├── player_base.py      # abstract Player interface
│   ├── player.py           # MPV and VLC backend implementations
│   ├── playback.py         # queue state, playback control, autoplay events
│   └── auto_play_mode.py   # autoplay UI and input listener thread
└── utility/
    ├── docs.py             # help text and installation guide
    └── utils.py            # ANSI codes, spinner, screen utilities
```

</details>

<details>
<summary><b>Dependencies</b></summary>

| Package | Purpose |
|---------|---------|
| `yt-dlp` | YouTube search and stream URL extraction |
| `python-mpv` | MPV player bindings *(optional)* |
| `python-vlc` | VLC player bindings *(optional)* |

> At least one of `python-mpv` or `python-vlc` must be installed and its corresponding player binary must be present on your system.

</details>


## Known Limitations

- Streams directly from YouTube; subject to rate limiting or regional restrictions


## License

MIT — do whatever you want, just don't remove the header.
