Metadata-Version: 2.4
Name: py-media-server
Version: 0.3.0
Summary: A simple media server for streaming video files
Home-page: https://github.com/pandiyarajk/py-media-server
Author: Pandiyaraj Karuppasamy
Author-email: Pandiyaraj Karuppasamy <pandiyarajk@live.com>
License: MIT
Project-URL: Homepage, https://github.com/pandiyarajk/py-media-server
Project-URL: Bug Reports, https://github.com/pandiyarajk/py-media-server/issues
Project-URL: Source, https://github.com/pandiyarajk/py-media-server
Keywords: media,server,streaming,video,http
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: End Users/Desktop
Classifier: Topic :: Multimedia :: Video
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Operating System :: OS Independent
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: author
Dynamic: home-page
Dynamic: license-file
Dynamic: requires-python

# py-media-server

A simple, lightweight media server for streaming video files over HTTP with a modern web interface.

## Features

- 🎬 Stream video files (MP4, MKV, AVI, MOV, M4V, WebM) from any directory
- 📂 Recursive scanning — subfolders are browsed, filtered and searched
- 🔍 Search, sort (name / newest / largest / longest) and folder filter,
  all preserved in the URL so a view can be bookmarked or shared
- ⏯️ Resume where you left off, with a *Continue watching* row and progress
  bars on tiles
- 💬 Sidecar subtitles (`.srt` / `.vtt`) discovered automatically and served
  as WebVTT, with language labels
- ⚠️ Codec compatibility check via ffprobe, with on-demand transcoding for
  files the browser cannot play natively
- ▶️ Full custom player — play/pause, ±10s skip, next/previous, seek bar,
  volume, playback speed, fullscreen and keyboard shortcuts
- ⏭️ Auto-advance to the next video when one finishes
- 🖼️ Automatic thumbnail generation using FFmpeg
- 📱 Responsive web interface that works on mobile and desktop
- ⚡ Range request support for efficient video streaming
- 🔒 Threaded TCP server for concurrent connections
- 🎨 Modern, dark-themed UI

## Installation

### From PyPI (when published)

```bash
pip install py-media-server
```

### From source

```bash
git clone https://github.com/pandiyarajk/py-media-server.git
cd py-media-server
pip install -e .
```

## Requirements

- Python 3.11+
- FFmpeg and ffprobe (optional)

FFmpeg is optional but unlocks three features: thumbnail generation, codec
inspection (duration, resolution, "may not play" warnings) and on-demand
transcoding. Without it the server still browses and streams — the affordances
that would not work are simply not rendered.

The server looks for `ffmpeg`/`ffprobe` on `PATH` first, then in common
install locations (`C:fmpegin`, Homebrew, `/usr/local/bin`, the winget
shim directory, etc.), so a normal install is picked up even when it was never
added to `PATH`. If it lives somewhere unusual, point at it directly:

```bash
py-media-server ~/Videos --ffmpeg /opt/custom/ffmpeg/bin
# or the binary itself:
py-media-server ~/Videos --ffmpeg /opt/custom/ffmpeg/bin/ffmpeg
```

`PY_MEDIA_SERVER_FFMPEG` (path to the binary or its directory) works the same
way as an environment variable.

To install FFmpeg:
- **Windows**: Download from [ffmpeg.org](https://ffmpeg.org/download.html) or use `choco install ffmpeg`
- **macOS**: `brew install ffmpeg`
- **Linux**: `sudo apt-get install ffmpeg` or `sudo yum install ffmpeg`

## Usage

### Basic usage

Serve media files from the current directory:

```bash
py-media-server
```

Or specify a directory:

```bash
py-media-server /path/to/your/movies
```

### Custom port

```bash
py-media-server /path/to/your/movies --port 9000
```

### Custom host and port

```bash
py-media-server ~/Videos --host 192.168.1.100 --port 8080
```

### Help

```bash
py-media-server --help
```

## Command-line Options

```
positional arguments:
  directory             Directory containing media files to serve (default: current directory)

optional arguments:
  -h, --help            show this help message and exit
  -p PORT, --port PORT  Port to run the server on (default: 8000)
  --host HOST           Host to bind the server to (default: 0.0.0.0)
  --ffmpeg PATH         Path to ffmpeg, or the directory holding it, for
                        installs not on PATH or in a common location
  -v, --version         show program's version number and exit
```

## How it Works

1. **Start the server**: Point it to a directory containing video files
2. **Open your browser**: Navigate to `http://localhost:8000`
3. **Browse and play**: Click on any video thumbnail to start streaming

The server will:
- Scan the directory **and its subfolders** for supported video formats
  (directories beginning with `.` are skipped)
- Generate thumbnails automatically (stored in the `.thumbs` subdirectory,
  alongside cached probe metadata and watch progress)
- Serve videos with range request support for smooth playback
- Handle concurrent connections efficiently

### Library view

The index page offers a search box, a sort selector and a folder filter. The
active view is written to the URL fragment, so a filtered listing can be
bookmarked or shared. Files you have started appear in a **Continue watching**
row, and every tile shows a progress bar plus badges for resolution, duration,
subtitles and playback warnings.

### Subtitles

Sidecar files next to the video are picked up automatically:

```
Shows/S01/ep01.mkv
Shows/S01/ep01.srt          -> "Subtitles"
Shows/S01/ep01.en.srt       -> "EN"
Shows/S01/ep01.English.vtt  -> "English"
```

SRT is converted to WebVTT on the fly, so no pre-processing is needed.
Encodings other than UTF-8 (including BOM-prefixed and CP1252 files) are
decoded rather than rejected.

### Compatibility and transcoding

When ffprobe is available the server inspects each file as you open it and
flags anything the browser is unlikely to play — HEVC video, AC3/DTS audio, or
an MKV container. The player then offers a **Play anyway (transcode)** button,
which streams a converted copy from ffmpeg. Only the parts that need it are
re-encoded: an MKV of h264/AAC is remuxed, AC3 audio alone is re-encoded
without touching the video, and a full transcode is the last resort.

Two transcodes run at once; further requests get a `503` rather than
overloading the machine.

## Player

Clicking a tile opens the player at `/play/<filename>`. The page is served with
the whole library as its playlist, so next/previous move through the same
sorted listing shown on the home page (disabled at the ends).

### Controls

| Button | Action |
|---|---|
| ⏮ | Previous video |
| ⏪ | Back 10 seconds |
| ▶ / ⏸ | Play / pause |
| ⏩ | Forward 10 seconds |
| ⏭ | Next video |
| 🔊 | Mute, with a volume slider |
| 1x | Playback speed (0.5x – 2x) |
| ⛶ | Fullscreen |

A draggable seek bar shows elapsed and total time.

### Keyboard shortcuts

| Key | Action |
|---|---|
| `Space` / `K` | Play / pause |
| `←` / `→` | Seek 10 seconds |
| `↑` / `↓` | Volume up / down |
| `N` | Next video |
| `P` | Previous video |
| `M` | Mute |
| `C` | Cycle subtitle track |
| `F` | Fullscreen |

## Development

### Setup development environment

```bash
git clone https://github.com/pandiyarajk/py-media-server.git
cd py-media-server
pip install -e ".[dev]"
```

### Run tests

```bash
pytest
```

### Run tests with coverage

```bash
pytest --cov=py_media_server --cov-report=html
```

## Project Structure

```
py-media-server/
├── py_media_server/
│   ├── __init__.py
│   ├── server.py
│   └── templates.py
├── tests/
│   ├── __init__.py
│   └── test_server.py
├── setup.py
├── pyproject.toml
├── README.md
├── LICENSE
└── MANIFEST.in
```

## Security Notice

⚠️ **Warning**: This server is intended for local network use only. It does not include authentication or encryption. Do not expose it to the public internet without proper security measures.

## License

MIT License - see LICENSE file for details

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## Changelog

### 0.3.0 (2026-08-15)
- ffmpeg/ffprobe are discovered in common install locations, and via
  `--ffmpeg` / `PY_MEDIA_SERVER_FFMPEG`, when absent from PATH
- Recursive scanning of subfolders
- Search, sort and folder filtering, with the view reflected in the URL
- Resume playback, "Continue watching" row and per-tile progress bars
- Sidecar subtitle discovery with SRT-to-WebVTT conversion
- Codec compatibility warnings via ffprobe
- On-demand transcoding for files the browser cannot play
- Optional features are hidden when ffmpeg is unavailable rather than
  rendered broken
- Page markup and scripts split out into `templates.py`
- Minimum supported Python raised to 3.11

### 0.2.0 (2026-08-15)
- Full custom player: play/pause, ±10s skip, next/previous, seek bar, volume,
  playback speed, fullscreen, keyboard shortcuts, auto-advance
- Unmatched routes now return 404 instead of closing the connection with no
  response
- Range requests are clamped to the file size
- Filenames are escaped when embedded in page scripts

### 0.1.0 (2026-04-19)
- Initial release
- Basic video streaming functionality
- Thumbnail generation
- Web interface
- Command-line interface
