mirror of
https://github.com/NotAShelf/mpvrc.git
synced 2026-04-15 15:33:47 +00:00
meta: rename to 'mpvrc'
mrc is taken :( Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I2cf0cab8dce04cd04981177d43b9b9b76a6a6964
This commit is contained in:
parent
8c48acf693
commit
1f1a94f747
9 changed files with 375 additions and 255 deletions
410
README.md
410
README.md
|
|
@ -1,120 +1,235 @@
|
|||
# MRC - MPV Remote Control
|
||||
# mpvrc - MPV Remote Control
|
||||
|
||||
[](https://opensource.org/licenses/MPL-2.0)
|
||||
[](https://crates.io/crates/mpvrc)
|
||||
|
||||
[mpv video player]: https://mpv.io/
|
||||
|
||||
**MRC** is a fast, robust JSON IPC wrapper for the [mpv video player]. It
|
||||
provides:
|
||||
|
||||
- Type-safe MPV IPC communication
|
||||
- Command-line interface with interactive mode
|
||||
- Secure remote control over HTTPS
|
||||
- Async Support with Tokio for high performance
|
||||
mpvrc is an unofficial command-line tool and library for controlling the
|
||||
[mpv video player] via its JSON IPC socket interface. Generally designed as a
|
||||
scriptable playback controller and a real-time interactive REPL in addition to a
|
||||
TLS-encrypted HTTP API for _remote_ control. mpvrc has you covered for anything
|
||||
that is even vaguely related to controlling a MPV instance.
|
||||
|
||||
## Features
|
||||
|
||||
- **Complete MPV Control**: Play, pause, seek, playlist management, and property
|
||||
access
|
||||
- **Interactive CLI**: Real-time command interface with help system
|
||||
- **Secure Remote Access**: TLS-encrypted server with token authentication
|
||||
- **Flexible Configuration**: Custom socket paths and environment-based setup
|
||||
The project is equipped with various neat features such as, but not limited to:
|
||||
|
||||
- **Full playback control**: play, pause, stop, seek, skip, and playlist
|
||||
management
|
||||
- **Interactive REPL**: vi-style editing, command history, and keyboard
|
||||
shortcuts
|
||||
- **HTTP server**: TLS-encrypted remote control with token authentication
|
||||
- **Library API**: use MRC as a Rust crate in your own projects
|
||||
|
||||
It's also async-first, for high-performance concurrency.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. **MPV** with IPC support (any recent version)
|
||||
2. **Rust** 1.92.0+ (or Nix for shell-based development)
|
||||
|
||||
## Installation
|
||||
|
||||
### From source
|
||||
|
||||
```bash
|
||||
# Clone and build using a recent cargo version
|
||||
$ git clone https://github.com/notashelf/mpvrc.git
|
||||
$ cd mpvrc
|
||||
|
||||
# Build in release mode
|
||||
$ cargo build --release
|
||||
```
|
||||
|
||||
### With Nix
|
||||
|
||||
The recommended way of building mpvrc is using Nix to acquire a developer shell.
|
||||
|
||||
```bash
|
||||
# Clone and build using cargo from the provided shell
|
||||
$ git clone https://github.com/notashelf/mpvrc.git
|
||||
$ cd mpvrc
|
||||
$ nix develop
|
||||
$ cargo build --release
|
||||
```
|
||||
|
||||
### From crates.io
|
||||
|
||||
You can also get mpvrc from <https://crates.io>.
|
||||
|
||||
```bash
|
||||
# Install to ~/.cargo/bin
|
||||
$ cargo install mpvrc --locked
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Prerequisites
|
||||
### 1. Start MPV with IPC
|
||||
|
||||
1. **Install MPV** with IPC support enabled
|
||||
2. **Install Rust** (edition 2024+)
|
||||
|
||||
### Installation
|
||||
Using mpvrc is quite simple. Start `mpv` with an IPC socket first:
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://github.com/notashelf/mrc.git
|
||||
cd mrc
|
||||
|
||||
# Build the project
|
||||
cargo build --release
|
||||
|
||||
# Or install directly
|
||||
cargo install --path .
|
||||
# `/tmp/mpvsocket` is the default socket path for mpvrc
|
||||
$ mpv --idle --input-ipc-server=/tmp/mpvsocket
|
||||
```
|
||||
|
||||
### Basic Usage
|
||||
### 2. Control playback
|
||||
|
||||
1. **Start MPV with IPC socket**:
|
||||
Then, once the socket is up, you may use `mpvrc` to control MPV.
|
||||
|
||||
```bash
|
||||
mpv --idle --input-ipc-server=/tmp/mpvsocket
|
||||
```
|
||||
```bash
|
||||
# Play/pause
|
||||
$ mpvrc play
|
||||
$ mpvrc pause
|
||||
|
||||
2. **Use the CLI**:
|
||||
# Navigation
|
||||
$ mpvrc next
|
||||
$ mpvrc prev
|
||||
|
||||
```bash
|
||||
# Basic playback control
|
||||
cargo run --bin cli play
|
||||
cargo run --bin cli pause
|
||||
cargo run --bin cli next
|
||||
# Seek 2 minutes forward
|
||||
$ mpvrc seek 120
|
||||
|
||||
# Load files
|
||||
cargo run --bin cli add ~/Music/song.mp3 ~/Videos/movie.mkv
|
||||
# Add files to playlist
|
||||
$ mpvrc add ~/Videos/movie.mkv ~/Videos/episode1.mkv
|
||||
|
||||
# Interactive mode
|
||||
cargo run --bin cli interactive
|
||||
```
|
||||
# View playlist
|
||||
$ mpvrc list
|
||||
|
||||
## Usage Guide
|
||||
# Interactive mode
|
||||
$ mpvrc interactive
|
||||
```
|
||||
|
||||
### CLI Commands
|
||||
## CLI Options
|
||||
|
||||
| Command | Description | Example |
|
||||
| :--------------------- | -------------------------- | :---------------------------: |
|
||||
| `play [index]` | Start/resume playback | `mrc play` or `mrc play 2` |
|
||||
| `pause` | Pause playback | `mrc pause` |
|
||||
| `stop` | Stop and quit MPV | `mrc stop` |
|
||||
| `next` | Skip to next playlist item | `mrc next` |
|
||||
| `prev` | Skip to previous item | `mrc prev` |
|
||||
| `seek <seconds>` | Seek to position | `mrc seek 120` |
|
||||
| `add <files...>` | Add files to playlist | `mrc add song1.mp3 song2.mp3` |
|
||||
| `remove [index]` | Remove playlist item | `mrc remove 0` |
|
||||
| `move <from> <to>` | Move playlist item | `mrc move 0 3` |
|
||||
| `clear` | Clear playlist | `mrc clear` |
|
||||
| `list` | Show playlist | `mrc list` |
|
||||
| `prop <properties...>` | Get properties | `mrc prop volume duration` |
|
||||
| `interactive` | Enter interactive mode | `mrc interactive` |
|
||||
```plaintext
|
||||
Usage: mpvrc [OPTIONS] <COMMAND>
|
||||
|
||||
Options:
|
||||
-s, --socket <PATH> Path to MPV IPC socket [default: /tmp/mpvsocket]
|
||||
-y, --yes Skip confirmation prompts for destructive commands
|
||||
-d, --debug Enable debug logging
|
||||
-h, --help Print help
|
||||
-V, --version Print version
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
<!--markdownlint-disable MD013-->
|
||||
|
||||
| Command | Description | Example |
|
||||
| :------------------- | ------------------------------ | :----------------------------- |
|
||||
| `play [index]` | Start/resume playback | `mpvrc play` or `mpvrc play 2` |
|
||||
| `pause` | Pause playback | `mpvrc pause` |
|
||||
| `stop` | Stop and quit MPV | `mpvrc stop` |
|
||||
| `next` | Skip to next playlist item | `mpvrc next` |
|
||||
| `prev` | Skip to previous item | `mpvrc prev` |
|
||||
| `seek <seconds>` | Seek to position in seconds | `mpvrc seek 120` |
|
||||
| `add <files...>` | Add files to playlist | `mpvrc add a.mp3 b.mp3` |
|
||||
| `remove [index]` | Remove item (default: current) | `mpvrc remove 0` |
|
||||
| `move <from> <to>` | Move playlist item | `mpvrc move 0 3` |
|
||||
| `clear` | Clear playlist | `mpvrc clear` |
|
||||
| `list` | Show playlist | `mpvrc list` |
|
||||
| `prop <props...>` | Get property values | `mpvrc prop volume` |
|
||||
| `interactive` | Enter interactive REPL | `mpvrc interactive` |
|
||||
| `completion <shell>` | Generate shell completions | `mpvrc completion zsh` |
|
||||
|
||||
<!--markdownlint-enable MD013-->
|
||||
|
||||
### Shell Completions
|
||||
|
||||
Generate completions for your shell:
|
||||
|
||||
```bash
|
||||
# Zsh
|
||||
$ mpvrc completion zsh > ~/.zsh/completions/_mpvrc
|
||||
|
||||
# Bash
|
||||
$ mpvrc completion bash > /etc/bash_completion.d/mpvrc
|
||||
|
||||
# Fish
|
||||
$ mpvrc completion fish > ~/.config/fish/completions/mpvrc.fish
|
||||
```
|
||||
|
||||
### Interactive Mode
|
||||
|
||||
Enter interactive mode for real-time control:
|
||||
|
||||
```bash
|
||||
$ cargo run --bin cli interactive
|
||||
Entering interactive mode. Type 'exit' to quit.
|
||||
$ mpvrc interactive
|
||||
Entering interactive mode. Type 'help' for commands or 'exit' to quit.
|
||||
Socket: /tmp/mpvsocket
|
||||
|
||||
mpv> play
|
||||
mpv> seek 60
|
||||
mpv> set volume 80
|
||||
mpv> get filename
|
||||
mpv> help
|
||||
mpv> list
|
||||
0 | Episode 1 | /path/to/episode1.mkv
|
||||
> 1 | Episode 2 | /path/to/episode2.mkv
|
||||
2 | Episode 3 | /path/to/episode3.mkv
|
||||
mpv> exit
|
||||
```
|
||||
|
||||
### Library Usage
|
||||
Keyboard shortcuts in interactive mode:
|
||||
|
||||
Basic example:
|
||||
- `Ctrl+C` - Interrupt current command
|
||||
- `Ctrl+L` - Clear screen
|
||||
- `Ctrl+D` - Exit (EOF)
|
||||
|
||||
## Server Mode
|
||||
|
||||
Run MRC as a TLS-encrypted HTTP server for remote control:
|
||||
|
||||
### 1. Generate TLS certificates
|
||||
|
||||
```bash
|
||||
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
|
||||
openssl pkcs12 -export -out identity.pfx -inkey key.pem -in cert.pem
|
||||
```
|
||||
|
||||
### 2. Configure environment
|
||||
|
||||
```bash
|
||||
export TLS_PFX_PATH="./identity.pfx"
|
||||
export TLS_PASSWORD="your_password"
|
||||
export AUTH_TOKEN="your_secret_token"
|
||||
```
|
||||
|
||||
### 3. Start server
|
||||
|
||||
```bash
|
||||
mpvrc server --bind 127.0.0.1:8080 --socket /tmp/mpvsocket
|
||||
```
|
||||
|
||||
### 4. Send commands
|
||||
|
||||
```bash
|
||||
curl -k -H "Authorization: Bearer your_secret_token" \
|
||||
-d "play" https://127.0.0.1:8080/
|
||||
```
|
||||
|
||||
## Library Usage
|
||||
|
||||
Add MRC to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
mpvrc = "0.2"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
serde_json = "1"
|
||||
```
|
||||
|
||||
Control MPV from Rust:
|
||||
|
||||
```rust
|
||||
use mrc::{playlist_next, set_property, get_property};
|
||||
use mpvrc::{get_property, playlist_next, set_property};
|
||||
use serde_json::json;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Set volume to 50%
|
||||
set_property("volume", &json!(50), None).await?;
|
||||
// Set volume
|
||||
set_property("volume", &json!(75), None).await?;
|
||||
|
||||
// Get current filename
|
||||
if let Some(filename) = get_property("filename", None).await? {
|
||||
println!("Playing: {}", filename);
|
||||
println!("Now playing: {}", filename);
|
||||
}
|
||||
|
||||
// Skip to next track
|
||||
|
|
@ -124,134 +239,67 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
}
|
||||
```
|
||||
|
||||
### Server Mode
|
||||
|
||||
For remote control over HTTPS:
|
||||
|
||||
1. **Generate TLS certificates**:
|
||||
|
||||
```bash
|
||||
# Create self-signed certificate
|
||||
openssl req -x509 -newkey rsa:4096 -keyout private_key.pem -out certificate.pem -days 365 -nodes
|
||||
|
||||
# Convert to PKCS#12 format
|
||||
openssl pkcs12 -export -out identity.pfx -inkey private_key.pem -in certificate.pem
|
||||
```
|
||||
|
||||
2. **Set environment variables**:
|
||||
|
||||
```bash
|
||||
export TLS_PFX_PATH="./identity.pfx"
|
||||
export TLS_PASSWORD="your_pfx_password"
|
||||
export AUTH_TOKEN="your_secure_token"
|
||||
```
|
||||
|
||||
3. **Start the server**:
|
||||
|
||||
```bash
|
||||
cargo run --bin server
|
||||
# Server starts on https://127.0.0.1:8080
|
||||
```
|
||||
|
||||
4. **Make requests**:
|
||||
|
||||
```bash
|
||||
# Using curl
|
||||
curl -k -H "Authorization: Bearer your_secure_token" \
|
||||
-d "pause" https://127.0.0.1:8080/
|
||||
|
||||
# Using any HTTP client
|
||||
POST https://127.0.0.1:8080/
|
||||
Authorization: Bearer your_secure_token
|
||||
Content-Type: text/plain
|
||||
|
||||
play
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Description | Default | Required |
|
||||
| -------------- | -------------------------------- | ------- | ----------- |
|
||||
| `TLS_PFX_PATH` | Path to PKCS#12 certificate file | - | Server only |
|
||||
| `TLS_PASSWORD` | Password for PKCS#12 file | - | Server only |
|
||||
| `AUTH_TOKEN` | Authentication token for server | - | Server only |
|
||||
| Variable | Description | Required |
|
||||
| -------------- | ------------------------------- | -------- |
|
||||
| `TLS_PFX_PATH` | Path to PKCS#12 certificate | Server |
|
||||
| `TLS_PASSWORD` | Password for PKCS#12 file | Server |
|
||||
| `AUTH_TOKEN` | Bearer token for authentication | Server |
|
||||
|
||||
### Socket Path
|
||||
### Custom Socket Path
|
||||
|
||||
By default, MRC uses `/tmp/mpvsocket`. You can customize this:
|
||||
|
||||
```rust
|
||||
// In your code
|
||||
use mrc::set_property;
|
||||
|
||||
set_property("volume", &json!(50), Some("/your/socket/path")).await?;
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
### Building
|
||||
Use `-s` or `--socket` to specify a different MPV socket:
|
||||
|
||||
```bash
|
||||
# Development build
|
||||
cargo build
|
||||
# As of 0.3.0, mvrc supports custom socket path
|
||||
$ mpvrc -s /var/run/mpv/socket play
|
||||
```
|
||||
|
||||
## Building & Development
|
||||
|
||||
The recommended developer setup for working with mpvrc is using Nix. Use
|
||||
`nix develop` or `direnv allow` to enter a reproducible devshell with the
|
||||
expected tooling, then work with Rust sources as usual:
|
||||
|
||||
```bash
|
||||
# Build
|
||||
$ cargo build
|
||||
|
||||
# Release build
|
||||
cargo build --release
|
||||
$ cargo build --release
|
||||
|
||||
# Run tests
|
||||
cargo test
|
||||
$ cargo test
|
||||
|
||||
# Check linting
|
||||
cargo clippy
|
||||
```
|
||||
|
||||
### Testing MPV IPC
|
||||
|
||||
Test IPC communication manually:
|
||||
|
||||
```bash
|
||||
# Send raw command to MPV socket
|
||||
echo '{ "command": ["get_property", "volume"] }' | socat - /tmp/mpvsocket
|
||||
|
||||
# Expected response
|
||||
{"data":50,"error":"success","request_id":0}
|
||||
# Lint
|
||||
$ cargo clippy --all-targets
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Socket not found error**:
|
||||
|
||||
- Ensure MPV is running: `mpv --idle --input-ipc-server=/tmp/mpvsocket`
|
||||
- Check socket exists: `ls -la /tmp/mpvsocket`
|
||||
|
||||
**Server certificate errors**:
|
||||
|
||||
- Verify certificate files exist and are readable
|
||||
- Check environment variables are set correctly
|
||||
- Test certificate: `openssl pkcs12 -info -in identity.pfx`
|
||||
|
||||
**Permission denied**:
|
||||
|
||||
- Check socket permissions: `ls -la /tmp/mpvsocket`
|
||||
- Run MPV with appropriate user permissions
|
||||
|
||||
### Debug Mode
|
||||
|
||||
Enable debug logging:
|
||||
### Socket not found
|
||||
|
||||
```bash
|
||||
RUST_LOG=debug cargo run --bin cli interactive
|
||||
# Verify MPV is running with IPC
|
||||
ls -la /tmp/mpvsocket
|
||||
|
||||
# Restart MPV with correct socket path
|
||||
mpv --idle --input-ipc-server=/tmp/mpvsocket
|
||||
```
|
||||
|
||||
### Debug output
|
||||
|
||||
```bash
|
||||
mpvrc -d interactive
|
||||
# or
|
||||
RUST_LOG=debug mpvrc interactive
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the Mozilla Public License 2.0 - see the
|
||||
[LICENSE](LICENSE) file for details.
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
- [MPV Media Player](https://mpv.io/) for the excellent IPC interface
|
||||
This project is made available under Mozilla Public License (MPL) version 2.0.
|
||||
See [LICENSE](LICENSE) for more details on the exact conditions. An online copy
|
||||
is provided [here](https://www.mozilla.org/en-US/MPL/2.0/).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue