Initial commit: Media Server for remote media control
FastAPI REST API server for controlling system-wide media playback on Windows, Linux, macOS, and Android. Features: - Play/Pause/Stop/Next/Previous track controls - Volume control and mute - Seek within tracks - Current track info (title, artist, album, artwork) - WebSocket real-time status updates - Script execution API - Token-based authentication - Cross-platform support Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
383
README.md
Normal file
383
README.md
Normal file
@@ -0,0 +1,383 @@
|
||||
# Media Server
|
||||
|
||||
A REST API server for controlling system media playback on Windows, Linux, macOS, and Android.
|
||||
|
||||
## Features
|
||||
|
||||
- Control any media player via system-wide media transport controls
|
||||
- Play/Pause/Stop/Next/Previous track
|
||||
- Volume control and mute
|
||||
- Seek within tracks
|
||||
- Get current track info (title, artist, album, artwork)
|
||||
- Token-based authentication
|
||||
- Cross-platform support
|
||||
|
||||
## Requirements
|
||||
|
||||
- Python 3.10+
|
||||
- Platform-specific dependencies (see below)
|
||||
|
||||
## Installation
|
||||
|
||||
### Windows
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
Required packages: `winsdk`, `pywin32`, `pycaw`, `comtypes`
|
||||
|
||||
### Linux
|
||||
|
||||
```bash
|
||||
# Install system dependencies
|
||||
sudo apt-get install python3-dbus python3-gi libdbus-1-dev libglib2.0-dev
|
||||
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### macOS
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
No additional dependencies - uses built-in `osascript`.
|
||||
|
||||
### Android (Termux)
|
||||
|
||||
```bash
|
||||
# In Termux
|
||||
pkg install python termux-api
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
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. Test the connection:
|
||||
```bash
|
||||
curl http://localhost:8765/api/health
|
||||
```
|
||||
|
||||
5. Test with authentication:
|
||||
```bash
|
||||
curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:8765/api/media/status
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Configuration file locations:
|
||||
- Windows: `%APPDATA%\media-server\config.yaml`
|
||||
- Linux/macOS: `~/.config/media-server/config.yaml`
|
||||
|
||||
### config.yaml
|
||||
|
||||
```yaml
|
||||
host: 0.0.0.0
|
||||
port: 8765
|
||||
api_token: your-secret-token-here
|
||||
poll_interval: 1.0
|
||||
log_level: INFO
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
All settings can be overridden with environment variables (prefix: `MEDIA_SERVER_`):
|
||||
|
||||
```bash
|
||||
export MEDIA_SERVER_HOST=0.0.0.0
|
||||
export MEDIA_SERVER_PORT=8765
|
||||
export MEDIA_SERVER_API_TOKEN=your-token
|
||||
export MEDIA_SERVER_LOG_LEVEL=DEBUG
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### Health Check
|
||||
|
||||
```
|
||||
GET /api/health
|
||||
```
|
||||
|
||||
No authentication required. Returns server status and platform info.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
"platform": "Windows",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
```
|
||||
|
||||
### Get Media Status
|
||||
|
||||
```
|
||||
GET /api/media/status
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"state": "playing",
|
||||
"title": "Song Title",
|
||||
"artist": "Artist Name",
|
||||
"album": "Album Name",
|
||||
"album_art_url": "https://...",
|
||||
"duration": 240.5,
|
||||
"position": 120.3,
|
||||
"volume": 75,
|
||||
"muted": false,
|
||||
"source": "Spotify"
|
||||
}
|
||||
```
|
||||
|
||||
### 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 |
|
||||
| `/api/media/next` | POST | - | Next track |
|
||||
| `/api/media/previous` | POST | - | Previous track |
|
||||
| `/api/media/volume` | POST | `{"volume": 75}` | Set volume (0-100) |
|
||||
| `/api/media/mute` | POST | - | Toggle mute |
|
||||
| `/api/media/seek` | POST | `{"position": 60.0}` | Seek to position (seconds) |
|
||||
|
||||
### Script Execution
|
||||
|
||||
The server supports executing pre-defined scripts via API.
|
||||
|
||||
#### List Scripts
|
||||
|
||||
```
|
||||
GET /api/scripts/list
|
||||
Authorization: Bearer <token>
|
||||
```
|
||||
|
||||
**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,
|
||||
"script": "lock_screen",
|
||||
"exit_code": 0,
|
||||
"stdout": "",
|
||||
"stderr": ""
|
||||
}
|
||||
```
|
||||
|
||||
### Configuring Scripts
|
||||
|
||||
Add scripts in your `config.yaml`:
|
||||
|
||||
```yaml
|
||||
scripts:
|
||||
lock_screen:
|
||||
command: "rundll32.exe user32.dll,LockWorkStation"
|
||||
label: "Lock Screen"
|
||||
description: "Lock the workstation"
|
||||
timeout: 5
|
||||
shell: true
|
||||
|
||||
shutdown:
|
||||
command: "shutdown /s /t 0"
|
||||
label: "Shutdown"
|
||||
description: "Shutdown the PC immediately"
|
||||
timeout: 10
|
||||
shell: true
|
||||
|
||||
restart:
|
||||
command: "shutdown /r /t 0"
|
||||
label: "Restart"
|
||||
description: "Restart the PC"
|
||||
timeout: 10
|
||||
shell: true
|
||||
|
||||
hibernate:
|
||||
command: "shutdown /h"
|
||||
label: "Hibernate"
|
||||
description: "Hibernate the PC"
|
||||
timeout: 10
|
||||
shell: true
|
||||
|
||||
sleep:
|
||||
command: "rundll32.exe powrprof.dll,SetSuspendState 0,1,0"
|
||||
label: "Sleep"
|
||||
description: "Put PC to sleep"
|
||||
timeout: 10
|
||||
shell: true
|
||||
```
|
||||
|
||||
Script configuration options:
|
||||
|
||||
| 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 |
|
||||
| `icon` | No | Custom MDI icon (e.g., `mdi:power`) |
|
||||
| `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) |
|
||||
|
||||
## Running as a Service
|
||||
|
||||
### Windows Task Scheduler (Recommended)
|
||||
|
||||
Run in **Administrator PowerShell** from the project root:
|
||||
|
||||
```powershell
|
||||
.\media_server\service\install_task_windows.ps1
|
||||
```
|
||||
|
||||
To remove the scheduled task:
|
||||
|
||||
```powershell
|
||||
Unregister-ScheduledTask -TaskName "MediaServer" -Confirm:$false
|
||||
```
|
||||
|
||||
### Windows Service
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
### 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
|
||||
|
||||
```
|
||||
python -m media_server.main [OPTIONS]
|
||||
|
||||
Options:
|
||||
--host TEXT Host to bind to (default: 0.0.0.0)
|
||||
--port INTEGER Port to bind to (default: 8765)
|
||||
--generate-config Generate default config file and exit
|
||||
--show-token Show current API token and exit
|
||||
```
|
||||
|
||||
## Security Recommendations
|
||||
|
||||
1. **Use HTTPS in production** - Set up a reverse proxy (nginx, Caddy) with SSL
|
||||
2. **Strong tokens** - Default tokens are 32 random characters; don't use weak tokens
|
||||
3. **Firewall** - Only expose the port to trusted networks
|
||||
4. **Secrets management** - Don't commit tokens to version control
|
||||
|
||||
## Supported Media Players
|
||||
|
||||
### Windows
|
||||
- Spotify
|
||||
- Windows Media Player
|
||||
- VLC
|
||||
- Groove Music
|
||||
- Web browsers (Chrome, Edge, Firefox)
|
||||
- Any app using Windows Media Transport Controls
|
||||
|
||||
### Linux
|
||||
- Any MPRIS-compliant player:
|
||||
- Spotify
|
||||
- VLC
|
||||
- Rhythmbox
|
||||
- Clementine
|
||||
- Web browsers
|
||||
- MPD (with MPRIS bridge)
|
||||
|
||||
### macOS
|
||||
- Spotify
|
||||
- Apple Music
|
||||
- VLC (partial)
|
||||
- QuickTime Player
|
||||
|
||||
### 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
|
||||
|
||||
## License
|
||||
|
||||
MIT License
|
||||
Reference in New Issue
Block a user