Skip to content

davidj4tech/mopidy-mpv

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Mopidy-Mpv

A Mopidy backend that plays URIs through an external mpv process over mpv's JSON-IPC socket, bypassing GStreamer entirely.

It handles the mpv: URI scheme: a PlaybackProvider that drives mpv via IPC plus a minimal LibraryProvider (just enough lookup() for frontends to enqueue mpv: URIs — it does not browse or search). Pair it with Mopidy-YouTube / Mopidy-Stream for discovery and route the things you want mpv to play through the mpv: scheme.

Why

mpv + yt-dlp is far more robust at playing YouTube (and other ytdl sources) than Mopidy's GStreamer pipeline — especially behind PO-token / signature challenges. Letting mpv own resolution and decoding, while Mopidy stays the queue/now-playing brain, sidesteps the GStreamer breakage.

YouTube-flavoured bodies are normalised to a watch URL so mpv's ytdl_hook resolves them:

mpv:youtube:video:ID  ->  https://www.youtube.com/watch?v=ID
mpv:yt:<full-url>      ->  <full-url>          (handed straight to ytdl_hook)
mpv:https://…          ->  https://…           (as-is)
mpv:file:///…          ->  file:///…           (as-is)

How it expects to run

mpv is managed externally (systemd/runit), started idle with an IPC socket and an audio device — Mopidy only connects to it:

mpv --idle=yes --no-video --no-terminal \
    --input-ipc-server=$XDG_RUNTIME_DIR/mopidy-mpv.sock \
    --ao=pulse --audio-device=pulse/<your-sink>

The backend holds a persistent IPC connection but reconnects on failure: if the mpv process restarts at runtime, the next play re-establishes the socket (re-arming property observers) instead of silently no-op'ing — so you never have to bounce Mopidy to recover.

Config

[mpv]
enabled = true
ipc_socket = $XDG_RUNTIME_DIR/mopidy-mpv.sock
mpv_command =          # optional; blank = mpv is managed externally

Installation

Requirements

  • Mopidy ≥ 3.4 and Python ≥ 3.9 (pykka ≥ 4.0 comes in as a dependency).
  • mpv installed and on PATH, managed externally (see How it expects to run).
  • For YouTube/yt-dlp sources: yt-dlp available to mpv's ytdl_hook, and a JavaScript runtime (deno or node) for signature/n-challenge solving.

Install the extension

Not on PyPI yet — install from the repository.

From GitHub:

pip install git+https://github.com/davidj4tech/mopidy-mpv.git

Or for development, clone and install editable:

git clone https://github.com/davidj4tech/mopidy-mpv.git
cd mopidy-mpv
pip install -e .

Install it into the same environment as Mopidy so it's discovered via the mopidy.ext entry point. Verify it loaded:

mopidy deps | grep -i mpv     # should list Mopidy-Mpv

Enable & configure

Add the [mpv] section to your mopidy.conf (see Config), point ipc_socket at the socket your externally-managed mpv exposes, then start mpv (How it expects to run) and restart Mopidy.

Usage

This backend has no UI of its own — you drive it by enqueuing mpv: URIs through any Mopidy frontend (MPD, the HTTP/JSON-RPC API, Iris, etc.). mpv does the resolving and decoding; Mopidy stays the queue / now-playing brain.

Using an MPD client (mpc) against Mopidy's MPD frontend:

# A YouTube video — yt: takes a full URL, normalised for mpv's ytdl_hook
$ mpc add "mpv:yt:https://www.youtube.com/watch?v=dQw4w9WgXcQ"
$ mpc play
> Never Gonna Give You Up
[playing] #1/1   0:03/3:32 (1%)

# Shorthand forms the backend also accepts
$ mpc add "mpv:youtube:video:dQw4w9WgXcQ"

# A direct internet-radio stream or a local file
$ mpc add "mpv:https://stream.example.com/radio.mp3"
$ mpc add "mpv:file:///home/me/Music/track.flac"

Via Mopidy's HTTP JSON-RPC API:

$ curl -s http://localhost:6680/mopidy/rpc -H 'Content-Type: application/json' \
    -d '{"jsonrpc":"2.0","id":1,"method":"core.tracklist.add",
         "params":{"uris":["mpv:yt:https://youtu.be/dQw4w9WgXcQ"]}}'
$ curl -s http://localhost:6680/mopidy/rpc -H 'Content-Type: application/json' \
    -d '{"jsonrpc":"2.0","id":2,"method":"core.playback.play"}'

For search / browse, pair with Mopidy-YouTube or Mopidy-Stream (this backend is lookup-only): discover a track there, then route it through the mpv: scheme to play it via mpv.

Status

Working PoC. Provides backend + mixer; no playlists/browse provider by design.

About

Mopidy backend that plays mpv: URIs through an external mpv via JSON-IPC — bypasses GStreamer for robust YouTube/yt-dlp playback, with reconnect-on-failure

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages