docs: comprehensive README update with all API endpoints and features
Lint & Test / test (push) Successful in 9s

- Add display control API endpoints and monitor response schema
- Add header links section with CRUD API and configuration
- Add visualizer API endpoints (status, devices, device selection)
- Add album artwork endpoint documentation
- Add audio devices endpoint
- Add script/callback CRUD endpoints (create, update, delete)
- Add browser folder management CRUD endpoints
- Add play-folder and download endpoints
- Add WebSocket protocol documentation (all message types)
- Add full config.yaml example with all sections
- Document Dynamic WebGL background feature
- Fix all markdown lint warnings (duplicate headings, table alignment,
  missing code fence languages, blank lines around fences)
This commit is contained in:
2026-03-23 02:33:03 +03:00
parent c76ffb9997
commit 02168519b7
+277 -80
View File
@@ -7,10 +7,12 @@ A REST API server for controlling system media playback on Windows, Linux, macOS
- **Built-in Web UI** for real-time media control and monitoring
- **Installable PWA** - Add to home screen on mobile for a native app experience
- **Audio Visualizer** - Real-time spectrum analyzer with beat-reactive album art effects
- **Dynamic WebGL Background** - Audio-reactive animated background with album art color extraction
- **Media Browser** - Browse and play media files from configured folders
- **Display Control** - Monitor brightness and power management
- **Quick Actions & Scripts** - Execute custom scripts with one click
- **Callbacks** - Trigger commands on media events (play, pause, volume, etc.)
- **Header Links** - Configurable quick-access links in the UI header
- Control any media player via system-wide media transport controls
- Play/Pause/Stop/Next/Previous track
- Volume control and mute
@@ -28,7 +30,7 @@ The media server includes a built-in web interface for controlling and monitorin
![Web UI](docs/web-ui.PNG)
### Features
### Web UI Highlights
- **Real-time status updates** via WebSocket connection
- **Album artwork display** with glow effect and automatic updates
@@ -40,7 +42,9 @@ The media server includes a built-in web interface for controlling and monitorin
- **Connection status indicator** - Know when you're connected
- **Token authentication** - Saved in browser localStorage
- **Audio spectrum visualizer** - Real-time frequency bars with beat-reactive album art scaling and glow (on-demand WASAPI loopback capture)
- **Dynamic WebGL background** - Fragment shader-based animated background that reacts to audio beats and extracts colors from album art (toggle on/off in header)
- **Display control** - Monitor brightness adjustment and power on/off
- **Header quick links** - Configurable external URLs with icons shown in the header bar
- **Installable PWA** - Add to home screen on mobile/desktop for standalone app experience with safe area support for notched phones
- **Responsive design** - Works on desktop, tablet, and mobile
- **Dark and light themes** - Toggle between dark and light modes with dynamic status bar theming
@@ -51,12 +55,14 @@ The media server includes a built-in web interface for controlling and monitorin
### Accessing the Web UI
1. Start the media server:
```bash
python -m media_server.main
```
2. Open your browser and navigate to:
```
```text
http://localhost:8765/
```
@@ -78,12 +84,15 @@ The Web UI includes a real-time audio spectrum visualizer that captures system a
- **On-demand capture** - Audio capture starts only when a client enables the visualizer, and stops when the last client disconnects
- **Beat-reactive effects** - Album art pulses and glows in response to bass frequencies
- **Dynamic WebGL background** - Animated shader background that reacts to bass frequencies and adapts colors from current album art
- **Configurable device** - Select which audio output device to capture in Settings
Requires `soundcard` and `numpy` Python packages. Enable in `config.yaml`:
```yaml
visualizer_enabled: true
visualizer_fps: 30 # Frame rate (10-60)
visualizer_bins: 32 # Frequency bins (8-128)
# visualizer_device: "Speakers" # optional: specific device name
```
@@ -135,7 +144,7 @@ The Media Browser feature allows you to browse and play media files from configu
![Media Browser](docs/media-browser.PNG)
### Browser Features
### Browser Highlights
- **Folder Configuration** - Mount multiple media folders (music/video directories)
- **Recursive Navigation** - Browse through folder hierarchies with breadcrumb navigation
@@ -143,13 +152,14 @@ The Media Browser feature allows you to browse and play media files from configu
- **Thumbnail Display** - Automatically generated thumbnails from album art (lazy-loaded)
- **Metadata Extraction** - View title, artist, album, duration, bitrate, file size, and more
- **Remote Playback** - Play files on the PC running the media server (not in the browser)
- **Play All** - Play all media files in the current folder
- **Play All** - Play all media files in the current folder (generates M3U playlist)
- **File Download** - Download individual media files directly from the browser
- **Search & Filter** - Real-time search across files in the current folder
- **Pagination** - Navigate large folders with configurable page sizes (25, 50, 100, 200, 500)
- **Last Path Memory** - Automatically returns to your last browsed location
- **Folder Management** - Create, edit, and delete media folders from the UI
### Configuration
### Browser Setup
Add media folders in your `config.yaml`:
@@ -179,9 +189,9 @@ When you play a file from the Media Browser:
### Media Player Compatibility
**⚠️ Important Limitation:** Not all media players expose their playback information to the Windows Media Session API. This means some players will open and play the file, but the Media Server UI won't show playback status, track information, or allow remote control.
**Important Limitation:** Not all media players expose their playback information to the Windows Media Session API. This means some players will open and play the file, but the Media Server UI won't show playback status, track information, or allow remote control.
**Compatible Players** (work with playback tracking):
**Compatible Players** (work with playback tracking):
- **VLC Media Player** - Full support
- **Groove Music** (Windows 10/11 built-in) - Full support
@@ -189,39 +199,84 @@ When you play a file from the Media Browser:
- **Chrome/Edge/Firefox** - Full support for web players
- **foobar2000** - Full support (with proper configuration/plugins)
**Limited/No Support:**
**Limited/No Support:**
- **Windows Media Player Classic** - Opens files but doesn't expose session info
- **Windows Media Player** (classic version) - Limited session support
**Recommendation:** Set **VLC Media Player** or **Groove Music** as your default audio player for the best experience with the Media Browser.
#### Changing Your Default Media Player (Windows)
#### Changing Your Default Media Player (on Windows)
1. Open Windows Settings Apps Default apps
1. Open Windows Settings > Apps > Default apps
2. Search for "Music player" or "Video player"
3. Select VLC Media Player or Groove Music
4. Files opened from Media Browser will now use the selected player
### API Endpoints
## Display Control
The Media Browser exposes several REST API endpoints:
The Display Control feature allows you to manage monitor brightness and power state from the Web UI or via API.
| Endpoint | Method | Description |
|--------------------------|--------|-----------------------------------|
| `/api/browser/folders` | GET | List configured media folders |
| `/api/browser/browse` | GET | Browse directory contents |
| `/api/browser/metadata` | GET | Get media file metadata |
| `/api/browser/thumbnail` | GET | Get thumbnail image |
| `/api/browser/play` | POST | Open file with default player |
- **Brightness adjustment** - Set brightness (0-100%) for each monitor
- **Power management** - Turn monitors on or off
- **Multi-monitor support** - See all connected monitors with model, manufacturer, and resolution info
- **Technology**: DDC-CI on Windows, XRandR/ACPI on Linux, IOKit on macOS
All endpoints require bearer token authentication.
### Display API
### Security Notes
| Endpoint | Method | Body | Description |
|------------------------------------------|----------|---------------------------|--------------------------------------------------|
| `/api/display/monitors` | GET | - | List monitors (use `?refresh=true` to refresh) |
| `/api/display/brightness/{monitor_id}` | POST | `{"brightness": 0-100}` | Set monitor brightness |
| `/api/display/power/{monitor_id}` | POST | `{"on": true\ | false}` |
- **Path Traversal Protection** - All paths are validated to prevent directory traversal attacks
- **Folder Restrictions** - Only configured folders are accessible
- **Authentication Required** - All endpoints require a valid API token
**Monitor response:**
```json
{
"id": 0,
"name": "Monitor Name",
"brightness": 100,
"power_supported": true,
"power_on": true,
"model": "Model Number",
"manufacturer": "Manufacturer",
"resolution": "1920x1080",
"is_primary": true
}
```
## Header Links
Configure quick-access links that appear in the Web UI header bar with custom icons.
### Links Setup
Add links in your `config.yaml`:
```yaml
links:
spotify:
url: "https://open.spotify.com"
icon: "mdi:spotify"
label: "Spotify"
settings:
url: "https://your-server.com/settings"
icon: "mdi:cog"
label: "Settings"
description: "System settings"
```
### Links API
| Endpoint | Method | Body | Description |
|-----------------------------------|----------|-------------------------------------|------------------|
| `/api/links/list` | GET | - | List all links |
| `/api/links/create/{link_name}` | POST | `{url, icon, label, description}` | Create link |
| `/api/links/update/{link_name}` | PUT | `{url, icon, label, description}` | Update link |
| `/api/links/delete/{link_name}` | DELETE | - | Delete link |
All connected WebSocket clients receive a `links_changed` notification when links are modified.
## Requirements
@@ -230,7 +285,7 @@ All endpoints require bearer token authentication.
## Installation
### Windows
### Installing on Windows
```bash
pip install -r requirements.txt
@@ -238,7 +293,7 @@ pip install -r requirements.txt
Required packages: `winsdk`, `pywin32`, `pycaw`, `comtypes`
### Linux
### Installing on Linux
```bash
# Install system dependencies
@@ -247,7 +302,7 @@ sudo apt-get install python3-dbus python3-gi libdbus-1-dev libglib2.0-dev
pip install -r requirements.txt
```
### macOS
### Installing on macOS
```bash
pip install -r requirements.txt
@@ -255,7 +310,7 @@ pip install -r requirements.txt
No additional dependencies - uses built-in `osascript`.
### Android (Termux)
### Installing on Android (Termux)
```bash
# In Termux
@@ -268,26 +323,31 @@ Requires Termux and Termux:API apps from F-Droid.
## Quick Start
1. Generate configuration with API token:
```bash
python -m media_server.main --generate-config
```
2. View your API token:
```bash
python -m media_server.main --show-token
```
3. Start the server:
```bash
python -m media_server.main
```
4. **Open the Web UI** (recommended):
- Navigate to `http://localhost:8765/` in your browser
- Enter your API token from step 2
- Start playing media and control it from the web interface!
5. Or test via API:
```bash
# Health check (no auth required)
curl http://localhost:8765/api/health
@@ -296,13 +356,14 @@ Requires Termux and Termux:API apps from F-Droid.
curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:8765/api/media/status
```
## Configuration
## Configuration Reference
Configuration file locations:
- Windows: `%APPDATA%\media-server\config.yaml`
- Linux/macOS: `~/.config/media-server/config.yaml`
### config.yaml
### Full config.yaml Example
```yaml
host: 0.0.0.0
@@ -316,29 +377,75 @@ api_tokens:
poll_interval: 1.0
log_level: INFO
# Audio device for system volume control (null = default device)
audio_device: null
# Audio visualizer (requires soundcard + numpy)
visualizer_enabled: true
visualizer_fps: 30
visualizer_bins: 32
visualizer_device: null # null = auto-detect loopback
# Media folders for browser
media_folders:
music:
path: "C:\\Users\\YourUsername\\Music"
label: "My Music"
enabled: true
# Thumbnail size: "small" (150x150), "medium" (300x300), or "both"
thumbnail_size: "medium"
# Custom scripts (execute via API/UI)
scripts:
lock_screen:
command: "rundll32.exe user32.dll,LockWorkStation"
label: "Lock Screen"
description: "Lock the workstation"
icon: "mdi:lock"
timeout: 5
shell: true
# Callbacks (execute after media actions)
callbacks:
on_turn_off:
command: "rundll32.exe user32.dll,LockWorkStation"
timeout: 5
shell: true
# Header quick links
links:
spotify:
url: "https://open.spotify.com"
icon: "mdi:spotify"
label: "Spotify"
```
### Authentication
The media server supports multiple API tokens with friendly labels. This allows you to:
- Issue different tokens for different clients (Home Assistant, mobile apps, web UI, etc.)
- Identify which client is making requests in the server logs
- Revoke individual tokens without affecting other clients
**Token labels** appear in all server logs, making it easy to track and debug client connections:
```
```text
2026-02-06 03:36:20,806 - media_server.services.websocket_manager - [home_assistant] - INFO - WebSocket client connected
2026-02-06 03:28:24,258 - media_server.routes.scripts - [mobile] - INFO - Executing script: lock_screen
```
**Viewing your tokens:**
```bash
python -m media_server.main --show-token
```
Output:
```
```text
Config directory: C:\Users\...\AppData\Roaming\media-server
API Tokens:
@@ -363,13 +470,14 @@ export MEDIA_SERVER_LOG_LEVEL=DEBUG
### Health Check
```
```text
GET /api/health
```
No authentication required. Returns server status and platform info.
**Response:**
```json
{
"status": "healthy",
@@ -380,12 +488,13 @@ No authentication required. Returns server status and platform info.
### Get Media Status
```
```text
GET /api/media/status
Authorization: Bearer <token>
```
**Response:**
```json
{
"state": "playing",
@@ -401,12 +510,21 @@ Authorization: Bearer <token>
}
```
### Album Artwork
```text
GET /api/media/artwork
Authorization: Bearer <token>
```
Returns current album artwork as PNG/JPEG/WebP binary. Also accepts token as a query parameter.
### Media Controls
All control endpoints require authentication and return `{"success": true}` on success.
| Endpoint | Method | Body | Description |
|----------|--------|------|-------------|
|-------------------------|----------|------------------------|--------------------------------|
| `/api/media/play` | POST | - | Resume playback |
| `/api/media/pause` | POST | - | Pause playback |
| `/api/media/stop` | POST | - | Stop playback |
@@ -419,42 +537,39 @@ All control endpoints require authentication and return `{"success": true}` on s
| `/api/media/turn_off` | POST | - | Execute on_turn_off callback |
| `/api/media/toggle` | POST | - | Execute on_toggle callback |
### Script Execution
### Visualizer API
The server supports executing pre-defined scripts via API and the Web UI. Scripts and callbacks can be managed directly from the Web UI — add, edit, delete, and execute with real-time output display.
| Endpoint | Method | Body | Description |
|-----------------------------------|----------|-----------------------------------------|----------------------------------------|
| `/api/media/visualizer/status` | GET | - | Check availability and running state |
| `/api/media/visualizer/devices` | GET | - | List loopback audio devices |
| `/api/media/visualizer/device` | POST | `{"device_name": "..." \ | null}` |
### Audio Devices
```text
GET /api/audio/devices
Authorization: Bearer <token>
```
Returns a list of available audio output devices.
### Script Management
Scripts can be managed via API or directly from the Web UI (Quick Actions tab).
![Script and Callback Management](docs/scripts-management.PNG)
#### List Scripts
| Endpoint | Method | Body | Description |
|----------------------------------------|----------|---------------------------------------------------------|--------------------|
| `/api/scripts/list` | GET | - | List all scripts |
| `/api/scripts/execute/{script_name}` | POST | `{"args": []}` | Execute a script |
| `/api/scripts/create/{script_name}` | POST | `{command, label, description, icon, timeout, shell}` | Create a script |
| `/api/scripts/update/{script_name}` | PUT | `{command, label, description, icon, timeout, shell}` | Update a script |
| `/api/scripts/delete/{script_name}` | DELETE | - | Delete a script |
```
GET /api/scripts/list
Authorization: Bearer <token>
```
**Execute response:**
**Response:**
```json
[
{
"name": "lock_screen",
"label": "Lock Screen",
"description": "Lock the workstation",
"timeout": 5
}
]
```
#### Execute Script
```
POST /api/scripts/execute/{script_name}
Authorization: Bearer <token>
Content-Type: application/json
{"args": []}
```
**Response:**
```json
{
"success": true,
@@ -465,7 +580,7 @@ Content-Type: application/json
}
```
### Configuring Scripts
### Script Config Options
Add scripts in your `config.yaml`:
@@ -507,10 +622,10 @@ scripts:
shell: true
```
Script configuration options:
Script fields:
| Field | Required | Description |
|-------|----------|-------------|
|-----------------|------------|--------------------------------------------------------|
| `command` | Yes | Command to execute |
| `label` | No | User-friendly display name (defaults to script name) |
| `description` | No | Description of what the script does |
@@ -519,9 +634,21 @@ Script configuration options:
| `working_dir` | No | Working directory for the command |
| `shell` | No | Run in shell (default: true) |
### Configuring Callbacks
### Callback Management
Callbacks are optional commands executed after media actions. Add them in your `config.yaml`:
Callbacks are commands executed after media actions. They can be managed via API or the Web UI (Quick Actions tab).
| Endpoint | Method | Body | Description |
|-------------------------------------------|----------|--------------------------------------------|--------------------------|
| `/api/callbacks/list` | GET | - | List all callbacks |
| `/api/callbacks/execute/{callback_name}` | POST | - | Execute (for debugging) |
| `/api/callbacks/create/{callback_name}` | POST | `{command, timeout, working_dir, shell}` | Create a callback |
| `/api/callbacks/update/{callback_name}` | PUT | `{command, timeout, working_dir, shell}` | Update a callback |
| `/api/callbacks/delete/{callback_name}` | DELETE | - | Delete a callback |
### Callback Config Options
Add callbacks in your `config.yaml`:
```yaml
callbacks:
@@ -586,7 +713,7 @@ callbacks:
Available callbacks:
| Callback | Triggered by | Description |
|----------|--------------|-------------|
|-----------------|-------------------------|---------------------------------|
| `on_play` | `/api/media/play` | After play succeeds |
| `on_pause` | `/api/media/pause` | After pause succeeds |
| `on_stop` | `/api/media/stop` | After stop succeeds |
@@ -599,15 +726,70 @@ Available callbacks:
| `on_turn_off` | `/api/media/turn_off` | Callback-only action |
| `on_toggle` | `/api/media/toggle` | Callback-only action |
Callback configuration options:
Callback fields:
| Field | Required | Description |
|-------|----------|-------------|
|-----------------|------------|--------------------------------------------------------|
| `command` | Yes | Command to execute |
| `timeout` | No | Execution timeout in seconds (default: 30, max: 300) |
| `working_dir` | No | Working directory for the command |
| `shell` | No | Run in shell (default: true) |
### Browser API
| Endpoint | Method | Body | Description |
|---------------------------------------------|----------|----------------------------------------|--------------------------------------------|
| `/api/browser/folders` | GET | - | List configured media folders |
| `/api/browser/browse` | GET | - | Browse directory (query: folder_id, path) |
| `/api/browser/metadata` | GET | - | Get file metadata (query: file_path) |
| `/api/browser/thumbnail` | GET | - | Get thumbnail image (query: file_path) |
| `/api/browser/download` | GET | - | Download file (query: folder_id, path) |
| `/api/browser/play` | POST | `{"file_path": "..."}` | Open file with default player |
| `/api/browser/play-folder` | POST | `{"folder_id": "...", "path": ""}` | Play all files in folder (M3U) |
| `/api/browser/folders/create` | POST | `{folder_id, label, path, enabled}` | Create folder config |
| `/api/browser/folders/update/{folder_id}` | PUT | `{label, path, enabled}` | Update folder config |
| `/api/browser/folders/delete/{folder_id}` | DELETE | - | Delete folder config |
All endpoints require bearer token authentication.
### Security Notes
- **Path Traversal Protection** - All paths are validated to prevent directory traversal attacks
- **Folder Restrictions** - Only configured folders are accessible
- **Authentication Required** - All endpoints require a valid API token
- **Output Limits** - Script stdout/stderr capped at 10KB
### WebSocket
```text
WebSocket /api/media/ws
Authorization: Bearer <token>
```
The WebSocket connection provides real-time updates and low-latency control.
**Messages from server:**
| Type | Data | Description |
|---------------------|------------------------|----------------------------------------|
| `status` | Media status object | Initial status on connection |
| `status_update` | Media status object | Status changes during playback |
| `audio_data` | `[0.1, 0.2, ...]` | Visualizer frequency data (30 fps) |
| `scripts_changed` | `{}` | Scripts were created/updated/deleted |
| `links_changed` | `{}` | Links were created/updated/deleted |
| `pong` | - | Response to client ping |
| `error` | `{"message": "..."}` | Error messages |
**Messages from client:**
| Type | Data | Description |
|-----------------------|------------------------|------------------------------------------------------------|
| `ping` | - | Keepalive ping |
| `get_status` | - | Request current status |
| `volume` | `{"volume": 0-100}` | Low-latency volume control via WebSocket |
| `enable_visualizer` | - | Subscribe to audio data (starts capture) |
| `disable_visualizer` | - | Unsubscribe from audio data (stops capture on last client) |
## Running as a Service
### Windows Task Scheduler (Recommended)
@@ -624,20 +806,23 @@ To remove the scheduled task:
Unregister-ScheduledTask -TaskName "MediaServer" -Confirm:$false
```
### Windows Service
### Windows Service (Alternative)
Install:
```bash
python -m media_server.service.install_windows install
```
Start/Stop:
```bash
python -m media_server.service.install_windows start
python -m media_server.service.install_windows stop
```
Remove:
```bash
python -m media_server.service.install_windows remove
```
@@ -645,24 +830,27 @@ python -m media_server.service.install_windows remove
### Linux (systemd)
Install:
```bash
sudo ./service/install_linux.sh install
```
Enable and start for your user:
```bash
sudo systemctl enable media-server@$USER
sudo systemctl start media-server@$USER
```
View logs:
```bash
journalctl -u media-server@$USER -f
```
## Command Line Options
```
```text
python -m media_server.main [OPTIONS]
Options:
@@ -681,15 +869,19 @@ Options:
## Supported Media Players
### Windows
### Players on Windows
- Spotify
- Windows Media Player
- VLC
- Groove Music
- Web browsers (Chrome, Edge, Firefox)
- foobar2000
- AIMP
- Web browsers (Chrome, Edge, Firefox, Opera, Brave)
- Any app using Windows Media Transport Controls
### Linux
### Players on Linux
- Any MPRIS-compliant player:
- Spotify
- VLC
@@ -698,28 +890,33 @@ Options:
- Web browsers
- MPD (with MPRIS bridge)
### macOS
### Players on macOS
- Spotify
- Apple Music
- VLC (partial)
- QuickTime Player
### Android (via Termux)
### Players on Android (via Termux)
- System media controls
- Limited seek support
## Troubleshooting
### "No active media session"
- Ensure a media player is running and has played content
- On Windows, check that the app supports media transport controls
- On Linux, verify MPRIS with: `dbus-send --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.ListNames | grep mpris`
### Permission errors on Linux
- Ensure your user has access to the D-Bus session bus
- For systemd service, the `DBUS_SESSION_BUS_ADDRESS` must be set correctly
### Volume control not working
- Windows: Run as administrator if needed
- Linux: Ensure PulseAudio/PipeWire is running