{"id":20673706,"url":"https://github.com/cpg314/mpv-web-remote","last_synced_at":"2026-06-04T17:31:14.695Z","repository":{"id":188131897,"uuid":"677714523","full_name":"cpg314/mpv-web-remote","owner":"cpg314","description":"Web remote control for mpv","archived":false,"fork":false,"pushed_at":"2024-08-04T17:37:01.000Z","size":231,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-17T14:25:06.518Z","etag":null,"topics":["mpv","remote-control","rust","video-player","webapp"],"latest_commit_sha":null,"homepage":"https://c.pgdm.ch/code","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cpg314.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-MIT","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-08-12T11:47:21.000Z","updated_at":"2025-01-12T11:44:54.000Z","dependencies_parsed_at":"2024-05-04T14:49:57.648Z","dependency_job_id":null,"html_url":"https://github.com/cpg314/mpv-web-remote","commit_stats":null,"previous_names":["cpg314/mpv-web-remote"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cpg314%2Fmpv-web-remote","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cpg314%2Fmpv-web-remote/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cpg314%2Fmpv-web-remote/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cpg314%2Fmpv-web-remote/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cpg314","download_url":"https://codeload.github.com/cpg314/mpv-web-remote/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242900056,"owners_count":20203704,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["mpv","remote-control","rust","video-player","webapp"],"created_at":"2024-11-16T20:42:19.323Z","updated_at":"2025-03-10T18:06:22.491Z","avatar_url":"https://github.com/cpg314.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mpv-web-remote\n\nSimple zero-dependency web remote for the [mpv media player](https://mpv.io/), using the [JSON IPC interface](https://mpv.io/manual/stable/#json-ipc).\n\n![Screenshot](screenshot.png)\n\nA single binary on the host machine connects to the mpv [unix socket](https://en.wikipedia.org/wiki/Unix_domain_socket) and exposes a remote control via a web server, which can be accessed from any device on the same network (e.g. a smartphone). The web app announces itself via the [media session API](https://developer.mozilla.org/en-US/docs/Web/API/Media_Session_API), allowing control even when the app is in the background, or from connected devices (e.g. a smartwatch).\n\n![Screenshot](mediasession.png)\n\nThe client code can also be used separately to interface with mpv from Rust in other use cases.\n\n## Features\n\nFor now, only the following basic functions are supported:\n\n- Play/pause\n- Toggle full-screen\n- Rewind 10 seconds (can be changed with the `--rewind-s` option)\n- Visualize progress (current time, total time, percentage)\n- Preview (updated every 3 seconds)\n- Seek (by clicking on the progress bar)\n\n## Installation\n\nFirst, edit your `~/.config/mpv/mpv.conf` to add\n\n```\ninput-ipc-server=~/mpv\n```\n\nThe `.deb` and Arch Linux/Manjaro packages in the [releases page](https://github.com/cpg314/mpv-web-remote/releases) will install `mpv-web-remote` as well as a `systemd` service.\n\nIt should suffice to enable it with\n\n```console\n$ systemctl --user enable --now mpv-web-remote\n$ systemctl --user status mpv-web-remote\nINFO [mpv_rs::mpv] Connected to socket\nINFO [mpv_rs] Starting web server on http://0.0.0.0:3000\n```\n\nThe web server will then be enabled shortly after a new instance of mpv is started and binds to the socket.\n\nWith the default parameters, the control interface will be accessible on \u003chttp://[ip]:3000\u003e.\n\n\u003e [!WARNING]  \n\u003e There is currently no authentication.\n\n### Alternative: Manual installation\n\n```console\n$ cp mpv-web-remote /usr/local/bin/\n$ cp mpv-web-remote.service ~/.config/systemd/user/\n$ systemctl --user daemon-reload \u0026\u0026 systemctl --user enable --now mpv-web-remote\n```\n\n### Alternative: Without systemd\n\nThe server can also be started manually:\n\n```console\n$ mpv-web-remote --help\nUsage: mpv-web-remote [OPTIONS] \u003cSOCKET\u003e\n\nArguments:\n  \u003cSOCKET\u003e\n\nOptions:\n      --addr \u003cADDR\u003e                        [default: 0.0.0.0:3000]\n  -d, --debug\n      --rewind-offset-s \u003cREWIND_OFFSET_S\u003e  Interval for backward seek [s] [default: 10]\n      --template \u003cTEMPLATE\u003e                Path to HTML template\n  -h, --help                               Print help\n```\n\n## Implementation details\n\nThere are two components:\n\n- the interface with mpv\n- the web server\n\nThe web server is straightforward and is implemented with [axum](https://docs.rs/axum/latest/axum/). For page interactions, we simply use [jQuery](https://jquery.com/).\n\nThe mpv interface takes the form\n\n```rust\nimpl Mpv {\n    pub fn connect(socket: impl AsRef\u003cPath\u003e) -\u003e Result\u003cSelf, Error\u003e;\n    pub fn send(\u0026mut self, mut request: Request) -\u003e Result\u003cResponse, Error\u003e;\n    pub fn wait_event(\u0026self, filter: impl Fn(\u0026Event) -\u003e bool);\n}\n```\n\nThe `connect` constructor connects to the socket and creates a thread responsible for reading replies and events from the servers into a buffer. In particular, we are robust against changes to this implementation detail:\n\n\u003e \"Currently, the mpv-side IPC implementation does not service the socket while a command is executed and the reply is written. It is for example not possible that other events, that happened during the execution of the command, are written to the socket before the reply is written.\n\u003e\n\u003e This might change in the future. The only guarantee is that replies to IPC messages are sent in sequence.\"\n\nThe `send` method writes a request to the socket, serialized using [`serde_json`](https://docs.rs/serde_json/latest/serde_json/). It then blocks until the server responds to that request.\n\nA selection of [commands](https://mpv.io/manual/stable/#list-of-input-commands) is implemented:\n\n```rust\nimpl Request {\n    pub fn playback_time() -\u003e Self;\n    pub fn get_property(property: \u0026str) -\u003e Self;\n    pub fn seek(target: f32, flags: \u0026str) -\u003e Self;\n    pub fn set_property\u003cT: Into\u003cserde_json::Value\u003e\u003e(property: \u0026str, value: T) -\u003e Self;\n    pub fn show_text(text: \u0026str) -\u003e Self;\n    pub fn observe_property(id: i64, property: \u0026str) -\u003e Self;\n    pub fn screenshot\u003cP: AsRef\u003cPath\u003e + ?Sized\u003e(filename: \u0026P) -\u003e Self;\n}\n```\n\nA generic response takes the form\n\n```rust\n#[derive(Deserialize, Debug)]\npub struct Response {\n    pub request_id: i64,\n    pub data: Option\u003cserde_json::Value\u003e,\n    pub error: String,\n}\n```\n\nand can be downcast to the expected data type\n\n```rust\nimpl Response {\n    pub fn into_inner\u003cT: DeserializeOwned\u003e(self) -\u003e Result\u003cT, Error\u003e;\n}\n```\n\nThis could also be encapsulated into higher-level methods (e.g. `get_playback_time() -\u003e f64`).\n\nFinally, the `wait_event` method simply blocks until an event occurs. This is for example useful to only trigger a screenshot at the new position after a seek has finished.\n\n## Existing solutions\n\nA quick search will reveal two \"mpv remote\" Android apps using the aforementioned mpv control interface. Naturally, they also require an additional component to run on the host machine to expose the API to the app.\n\n- \u003chttps://github.com/husudosu/mpv-remote-app\u003e, where a Node.JS server (\u003chttps://github.com/husudosu/mpv-remote-node\u003e) runs as an mpv plugin and provides an API over HTTP.\n- \u003chttps://github.com/mcastorina/mpv-remote-app\u003e, where a separate Python server exposes an API over a network socket.\n\nThe [mpvipc](https://crates.io/crates/mpvipc) crate provides a similar and more complete interface, but the above was an opportunity to experiment with a different implementation, under a more permissive license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcpg314%2Fmpv-web-remote","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcpg314%2Fmpv-web-remote","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcpg314%2Fmpv-web-remote/lists"}