From a0d138bb93942e0665c8dca267421f7f1784febd Mon Sep 17 00:00:00 2001 From: "alexei.dolgolyov" Date: Fri, 6 Feb 2026 03:25:08 +0300 Subject: [PATCH] Add built-in Web UI for media control and monitoring - Add static file serving to FastAPI application - Create responsive web interface with real-time updates - Features: - Real-time status updates via WebSocket - Album artwork display with automatic updates - Playback controls (play, pause, next, previous) - Volume control with mute toggle - Seekable progress bar - Token authentication with localStorage persistence - Dark theme and responsive design - Auto-reconnect WebSocket support - Update README with Web UI documentation - Zero dependencies (vanilla HTML/CSS/JavaScript) Co-Authored-By: Claude Sonnet 4.5 --- README.md | 58 ++- media_server/main.py | 13 + media_server/static/index.html | 801 +++++++++++++++++++++++++++++++++ 3 files changed, 867 insertions(+), 5 deletions(-) create mode 100644 media_server/static/index.html 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 +
+
+
+ + + +