diff --git a/README.md b/README.md index 021cdb4..992c0cd 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,58 @@ A REST API server for controlling system media playback on Windows, Linux, macOS ## Features +- **Built-in Web UI** for real-time media control and monitoring - 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) +- WebSocket support for real-time updates - Token-based authentication - Cross-platform support +## Web UI + +The media server includes a built-in web interface for controlling and monitoring media playback. + +### Features + +- **Real-time status updates** via WebSocket connection +- **Album artwork display** with automatic updates +- **Playback controls** - Play, pause, next, previous +- **Volume control** with mute toggle +- **Seekable progress bar** - Click to jump to any position +- **Connection status indicator** - Know when you're connected +- **Token authentication** - Saved in browser localStorage +- **Responsive design** - Works on desktop and mobile +- **Dark theme** - Easy on the eyes + +### Accessing the Web UI + +1. Start the media server: + ```bash + python -m media_server.main + ``` + +2. Open your browser and navigate to: + ``` + http://localhost:8765/ + ``` + +3. Enter your API token when prompted (get it with `media-server --show-token`) + +4. Start playing media in any supported player and watch the UI update in real-time! + +### Remote Access + +To access the Web UI from other devices on your network: + +1. Find your computer's IP address (e.g., `192.168.1.100`) +2. Navigate to `http://192.168.1.100:8765/` from any device on the same network +3. Enter your API token + +**Security Note:** For remote access over the internet, use a reverse proxy with HTTPS (nginx, Caddy) to encrypt traffic. + ## Requirements - Python 3.10+ @@ -71,13 +115,17 @@ Requires Termux and Termux:API apps from F-Droid. python -m media_server.main ``` -4. Test the connection: - ```bash - curl http://localhost:8765/api/health - ``` +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. Test with authentication: +5. Or test via API: ```bash + # Health check (no auth required) + curl http://localhost:8765/api/health + + # Get media status curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:8765/api/media/status ``` diff --git a/media_server/main.py b/media_server/main.py index 8154f12..cee0d56 100644 --- a/media_server/main.py +++ b/media_server/main.py @@ -4,10 +4,13 @@ import argparse import logging import sys from contextlib import asynccontextmanager +from pathlib import Path import uvicorn from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware +from fastapi.responses import FileResponse +from fastapi.staticfiles import StaticFiles from . import __version__ from .config import settings, generate_default_config, get_config_dir @@ -69,6 +72,16 @@ def create_app() -> FastAPI: app.include_router(media_router) app.include_router(scripts_router) + # Mount static files and serve UI at root + static_dir = Path(__file__).parent / "static" + if static_dir.exists(): + app.mount("/static", StaticFiles(directory=str(static_dir)), name="static") + + @app.get("/", include_in_schema=False) + async def serve_ui(): + """Serve the Web UI.""" + return FileResponse(static_dir / "index.html") + return app diff --git a/media_server/static/index.html b/media_server/static/index.html new file mode 100644 index 0000000..f1e3033 --- /dev/null +++ b/media_server/static/index.html @@ -0,0 +1,801 @@ + + + + + + Media Server + + + + + + + +
+
+

Media Server

+

Enter your API token to connect to the media server.

+ + +
+

To get your token, run:

+ media-server --show-token +
+
+
+
+ +
+
+

Media Server

+
+ + Disconnected +
+
+ +
+
+ Album Art +
+ +
+
No media playing
+
+
+
+ + + + Idle +
+
+ +
+
+ 0:00 + 0:00 +
+
+
+
+
+ +
+ + + +
+ +
+ + +
50%
+
+ +
+ Source: Unknown +
+
+
+ + + +