mpv supports JavaScript scripts via the MuJS embedded interpreter (ECMAScript 5). The JavaScript scripting interface is nearly identical to the Lua interface — the sameDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/mpv-player/mpv/llms.txt
Use this file to discover all available pages before exploring further.
mp, mp.utils, mp.msg, mp.options, and mp.input modules are available with the same APIs. This page covers the differences and JavaScript-specific additions.
This page focuses on what is different from Lua scripting. Refer to the Lua scripting reference for full API documentation.
Script location
Use the.js extension. Everything else — script directories, main.js entry points, loading from ~/.config/mpv/scripts/, and the --script flag — is the same as Lua.
Quick example
A script that exits fullscreen whenever playback is paused:Differences from Lua
No module imports required
All modules are preloaded. There is norequire call needed to access mp, mp.utils, mp.msg, mp.options, or mp.input:
Error handling
Where Lua returnsnil, error on failure, JavaScript returns undefined and makes the error available via mp.last_error():
(LE) support this pattern. An empty string from mp.last_error() means success.
Standard JS APIs replace some Lua equivalents
| Lua | JavaScript |
|---|---|
mp.add_timeout(seconds, fn) | id = setTimeout(fn, ms) |
mp.add_periodic_timer(seconds, fn) | id = setInterval(fn, ms) |
utils.parse_json(str) | JSON.parse(str) |
utils.format_json(v) | JSON.stringify(v) |
utils.to_string(v) | dump(v) |
mp.get_next_timeout() | see event loop |
mp.dispatch_events() | see event loop |
No standard library
There is no access tofs, process, or other Node.js-style built-ins. Filesystem interaction goes through mp.utils, and subprocess execution through mp.command_native.
Language features: ECMAScript 5
The MuJS interpreter implements ES5. Standard ES5 methods likeString.prototype.substring work; non-standard extensions like String.prototype.substr do not. Consult the MuJS documentation for details.
Timers
Standard HTML/Node.js-style timers are available globally:duration defaults to 0. Timers always fire asynchronously — setTimeout(fn) will never call fn before returning, and setInterval never fires twice in the same event loop iteration.
CommonJS modules and require
mpv’s JavaScript supports CommonJS-style modules. A module is a .js file that assigns properties to its pre-existing exports object:
Module resolution
- Paths starting with
./or../are relative to the calling script. - Absolute paths (e.g.
~/fooor/usr/local/lib/foo) are resolved directly. - All other IDs are looked up as global module IDs in
mp.module_paths.
.js extension is always appended to the ID. For example, require("./foo") loads ./foo.js.
mp.module_paths
A global array of directories searched for top-level module IDs. Empty by default, except for directory scripts where it includes <script-dir>/modules/.
Notes
- Modules are cached: calling
requirefor the same ID twice returns the sameexportsobject. globalis not defined, but the top-levelthisis the global object.- Functions and variables declared at the module level do not pollute the global object.
- Some Node.js-compatible modules with minimal dependencies may work, but most will not.
Custom initialization
Before loading any script, mpv looks forinit.js in the mpv configuration directory (e.g. ~/.config/mpv/init.js). Code there runs in the same environment as scripts and can modify global state for all scripts, such as adding to mp.module_paths:
--no-config.
Additional JavaScript-only APIs
mp.last_error()
Returns an empty string if the last (LE)-marked API call succeeded, or a non-empty error reason string on failure.
print and dump
Error.stack
Stack traces are available inside catch blocks when the error was created with the Error constructor:
exit()
Exits the script at the end of the current event loop iteration (registered for the shutdown event). Does not terminate mpv or other scripts.
mp.get_time_ms()
Same as mp.get_time() but returns milliseconds instead of seconds.
mp.get_script_file()
Returns the filename of the current script.
mp.utils.getenv(name)
Returns the value of an environment variable, or undefined if not set.
mp.utils.get_user_path(path)
Expands mpv meta-paths (like ~~desktop/ or ~~home/) into a platform-specific filesystem path.
File I/O
read_file, write_file, and append_file expand mpv meta-paths internally and throw on errors. They handle text content only.
mp.utils.compile_js(fname, content_str)
Compiles JavaScript source code from a string without loading from the filesystem. Returns a callable function:
Scripting API quick reference
All of the following are available to JavaScript with the same behavior as Lua. Functions marked(LE) support mp.last_error() for error checking.
- Commands
- Properties
- Events & bindings
- Utilities
- mp.utils
- mp.msg
- mp.options / mp.input
The event loop
The built-in event loop polls mpv events, processes timers, and waits for new events. You can replace it by defining a globalmp_event_loop function:
| Function | Description |
|---|---|
mp.wait_event(wait) | Block for up to wait seconds, returns next event or {event: "none"} |
mp.dispatch_event(e) | Call registered handlers for the given event |
mp.process_timers() | Fire due timers; returns ms until next timer, or -1 |
mp.notify_idle_observers() | Call idle observers (call before sleeping) |
mp.peek_timers_wait() | Like mp.process_timers() but without firing |
mp.keep_running | Set to false to exit the loop |
exit() is internally registered for the shutdown event and sets mp.keep_running = false.