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
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:
exit() is internally registered for the shutdown event and sets mp.keep_running = false.