- Python 97.5%
- Makefile 2.5%
| mpvremote | ||
| .gitignore | ||
| markdown-linter.py | ||
| mpvremote2.sh | ||
| README.md | ||
mpvremote
A Python 3 curses TUI that acts as a TV-style remote control for a running mpv instance, driven over its UNIX-socket IPC interface.
Any device that can connect to your MPV machine via SSH and run a curses TUI in an SSH shell — a phone, a laptop, a potato with a terminal — can be a remote controller for your MPV. No X forwarding, no web server, no extra dependencies: just SSH in and drive your media player from the couch.
How it works
mpv exposes a JSON IPC interface when launched with --input-ipc-server.
mpvremote connects to that socket, polls playback properties (title, position,
volume, loop state, ...) and sends commands (seek, pause, queue, ...) — the
same interface mpv's own scripting API uses, but from a terminal UI.
+----------------+ ssh +----------------+ AF_UNIX +----------------+
| Any device | -----------> | MPV machine | -----------> | mpv |
| (curses TUI) | | python3 -m | /tmp/ | --input-ipc- |
| | <----------- | mpvremote | mpv-socket | server=... |
+----------------+ +----------------+ +----------------+
Requirements
- Python 3.6+ (standard library only — no pip installs)
- mpv running with IPC enabled
- Terminal with curses support (any Linux SSH session)
Quick start
On the MPV machine, launch mpv with the IPC socket:
mpv --input-ipc-server=/tmp/mpv-socket video.mkv
Or make it permanent in mpv.conf:
input-ipc-server=/tmp/mpv-socket
Then, from any device, SSH in and run the remote from the repo root:
ssh user@mpv-machine
cd mpvremote
python3 -m mpvremote
Configuration
The IPC socket and video extensions are set in mpvremote/config.py. The media
directory defaults to ~/Videos and can be changed in the app's Settings view
(x). The selected path is stored in ~/.config/mpvremotemedia.
| Setting | Default | Description |
|---|---|---|
SOCKET |
/tmp/mpv-socket |
Path to mpv's IPC socket |
VIDEO_EXTS |
mp4 mkv avi webm |
File extensions treated as video |
Keybindings
Main view (the remote)
| Key | Action |
|---|---|
Space |
Pause / resume |
h/l, ←/→ |
Seek -10s / +10s |
j/k |
Volume -5 / +5 |
s |
Cycle subtitles |
n/p |
Next / previous track |
r |
Toggle loop current file |
R |
Toggle loop playlist |
e |
Playlist view |
o |
Queue view |
x |
Settings (media directory) |
c |
Show controls help |
q |
Quit |
Playlist view
| Key | Action |
|---|---|
Up/Down |
Navigate |
Enter |
Skip to selected item |
Del/d |
Remove selected item |
Esc/q/← |
Back to main view |
Queue view
| Key | Action |
|---|---|
| type | Incremental search of MEDIA_DIR |
Up/Down |
Navigate |
Enter |
Queue selected video (append-play) |
Backspace |
Delete search character |
Esc |
Clear search / back to main view |
Status bar
The top status bar shows the current playback state:
> Playing | 1:23 / 5:00 | L:F+P | My Video Title | Vol: 50
| Segment | Meaning |
|---|---|
> Playing |
Playback state (|| Paused when paused) |
1:23 / 5:00 |
Current position / duration |
L:F+P |
Loop state (see below) |
| Title | Media title of the current file |
Vol: 50 |
Volume level |
Loop indicators:
| Indicator | Meaning |
|---|---|
L:-- |
No looping |
L:F |
Current file loops |
L:P |
Playlist loops |
L:F+P |
Both file and playlist looping |
Views
- Main — the remote: playback controls with a scrolling feedback log
- Playlist — the current mpv playlist; skip to or remove entries
- Queue — search your media library and append videos to the playlist
The media library in MEDIA_DIR is scanned at startup and rescanned in the
background every 2 minutes, so newly added files show up without a restart.
Project layout
mpvremote/
├── mpvremote/
│ ├── __init__.py # Package exports
│ ├── __main__.py # Entry point: socket check + curses bootstrap
│ ├── app.py # App shell: drawing, colors, views, media rescan
│ ├── config.py # Socket path, media dir, extensions, key bindings
│ ├── mpv_client.py # Minimal mpv JSON IPC client (AF_UNIX socket)
│ └── views.py # MainView, PlaylistView, QueueView
License
GPLv3