
如何为 mpv 编写第一个 JavaScript 脚本JS 与 Lua 环境的关键差异【免费下载链接】mpv Command line media player项目地址: https://gitcode.com/GitHub_Trending/mp/mpvmpv 的脚本文档以 Lua 为主体但 DOCS/man/javascript.rst 明确说明JavaScript 支持与 Lua 支持几乎完全一致API 细节与通用脚本编写都参照 Lua 文档只有少数加载方式、错误处理与语言特性上的差异。本文按照这条文档指引走一遍完整流程确认当前 mpv 编译了 JavaScript 后端、把第一个.js脚本放到正确的位置、验证它确实被加载并生效最后列出 JS 与 Lua 环境之间必须知道的关键差异。先确认这个 mpv 带 JavaScript 后端JavaScript 后端是可选的构建特性。在 meson.options 中它定义为javascript选项类型是feature默认值automeson.build 中会查找 MuJS 依赖版本要求不低于 1.0.0找不到则该特性为否。构建配置完成后mpv 的构建摘要summary里会打印javascript: yes/no一项用它核对当前构建是否启用。运行时也有直接的症状把脚本交给 mpv 加载时若扩展名无法匹配到任何已编译的脚本后端控制台会打印一条错误——按 DOCS/man/lua.rst Script location 一节的说法要么是扩展名拼错了要么是对应后端没有编译进你的 mpv。源码中的错误串为Cant load unknown script: 文件见 player/scripting.c。对.js文件看到这条错误就说明这个 mpv 缺 JavaScript 后端需要先解决编译问题后面所有步骤都以此为前提。mpv 如何找到并加载 JS 脚本javascript.rst 的第一条规则脚本文件带.js扩展名时mpv 会尝试把它作为 JavaScript 加载除此之外文档中所有 Lua 的脚本选项、脚本目录、加载方式同样适用于 JavaScript 文件。具体有自动加载把脚本放进 mpv 配置目录的scripts子目录通常是~/.config/mpv/scripts/命令行指定通过--script选项传入脚本路径扩展名为.disable的条目总是被忽略目录也可以代表一个脚本mpv 会在其中加载main.js。若目录里同时存在main.lua和main.js只会加载其中一个具体是哪个取决于 mpv 内部实现且可能随时变化脚本名由去掉扩展名、把所有非字母数字字符替换为_得到文档以my-tools.lua→my_tools为例JS 文件同理运行时可用mp.get_script_name()取到。写第一个 JS 脚本直接采用官方文档的例子播放器被暂停时退出全屏模式。把下面内容保存为一个.js文件文件名可以任意本文以~/.config/mpv/scripts/unfull.js为例末尾额外加了一行print方便加载时确认function on_pause_change(name, value) { if (value true) mp.set_property(fullscreen, no); } mp.observe_property(pause, bool, on_pause_change); print(unfull.js loaded);这段代码里有两个知识点mp、mp.msg等模块不需要require。mp、mp.utils、mp.msg、mp.options、mp.input在 JS 环境中是预加载的可直接使用——这正是与 Lua 的第一个差异。生命周期脚本主体在启动时先执行一遍随后 mpv 进入事件循环你注册的观察者如mp.observe_property由事件循环驱动。lua.rst 特别提醒脚本与播放器初始化并行启动顶层执行时部分属性可能还没有有意义的值因此不要在脚本顶层直接读这些属性而应在mp.observe_property或事件处理器中读取。随后像平时一样启动 mpv 即可video.mp4替换成你要播放的媒体文件也可用mpv --script .js 文件路径 video.mp4显式加载该脚本mpv video.mp4验证脚本真的运行了加载成功终端打印unfull.js loaded。print是mp.msg.info的别名按 lua.rst 对日志级别的说明默认情况下除v、debug、trace外的消息都会显示所以info级别可见。行为符合文档示例播放中进入全屏然后暂停播放器退出全屏。加载失败控制台打印错误前文的Cant load unknown script一类。脚本加载失败不会阻止 mpv 继续启动只是该脚本不生效。脚本内部如果抛出 JavaScript 错误可以用try { ... } catch(e) { ... }捕获当错误是用Error(...)构造器创建时e.stack提供堆栈跟踪便于定位。JS 与 Lua 环境的关键差异除下述差异外两侧 API 一致javascript.rst Scripting APIs - identical to Lua 一节列出的mp.command、mp.commandv、mp.command_native、mp.get_property/mp.set_property家族、mp.register_event、mp.observe_property、mp.add_key_binding、mp.add_hook、mp.osd_message、mp.options.read_options、mp.input.get等函数在 JS 中签名与语义相同细节以 Lua 文档为准。方面LuaJavaScript模块加载需要require mp.msg等五个模块预加载无需任何 setup错误表示返回nil或value, error两个值返回undefined错误原因经mp.last_error()获取仅部分函数提供文档中标注(LE)一次性定时器mp.add_timeout(seconds, fn)id setTimeout(fn, ms)注意 Lua 用秒、JS 用毫秒周期定时器mp.add_periodic_timer(seconds, fn)id setInterval(fn, ms)JSONmp.utils.parse_json/mp.utils.format_jsonJSON.parse/JSON.stringify语言LuaECMAScript 5两条转换规则标准 JS API 优先。setTimeout、JSON.stringify直接可用反向地mp.add_timeout和mp.utils.format_json在 JS 环境中不存在。语言级别是 ES5脚本后端是 MuJS一个兼容的极简 ES5 解释器。例如String.substring有实现而常见但非标准的String.substr没有。写新语法前先确认 MuJS 的语言特性支持。JS 环境还有几处 Lua 文档没有的机制dump与print类似但会递归展开对象和数组mp.last_error()在更新了 last error 的 API 调用后返回空字符串表示成功、非空字符串表示失败原因文件函数mp.utils.read_file(fname [,max])、mp.utils.write_file(fname, str)、mp.utils.append_file(fname, str)。它们只接受文本内容出错时抛出异常write_file/append_file的路径必须以file://开头防止参数写错的简单保护例如mp.utils.write_file(file://~/abc.txt, hello world)CommonJSrequire(id)id总是按追加.js处理以./或../开头的 id 相对发起require的脚本解析其余 id 先按绝对路径如/x/y、~/x尝试再按mp.module_paths数组顺序搜索全局模块。由于缺少fs、process等 node.js 核心模块大多数 node.js 模块无法运行——这套机制是为共享 mpv 脚本设计的不是 node.js 的替代品init.jsmpv 为每个脚本初始化 JS 环境之后、加载脚本之前会运行 mpv 配置目录根部的init.js可用它统一更新所有脚本的环境如mp.module_paths.push(/foo)。注意用--no-config启动时该文件被忽略更新搜索路径要用push而不是整体重新赋值否则会清掉已有的搜索路径。边界与限制mpv 中的 JavaScript没有标准库与 mpv 之外的一切交互都局限在可用 API 上通常经由mp.utils语言停留在 ES5MuJS 未实现的标准特性不可用mp.utils.file_info(path)与 Lua 一致不展开~~/foo这类 meta 路径其他 JS 文件函数会展开定时器永远异步回调setTimeout(fn)在返回之前绝不会调用fn回调发生在本次事件循环迭代末尾或之后的迭代因此setTimeout(fn)也可以当作一次性的 idle 观察者使用。第一个脚本跑通后API 细节可以继续查 Lua 文档JS 复用同一套 API想看print、dump、定时器与require的默认实现可以直接读 player/javascript/defaults.js。【免费下载链接】mpv Command line media player项目地址: https://gitcode.com/GitHub_Trending/mp/mpv创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考