2026-05-23 17:58:51 +08:00
2026-05-23 17:25:03 +08:00
2026-05-23 17:58:51 +08:00

speakerlib

speakerlib.lua 是一个面向 CC: Tweaked 的扬声器播放器。

它支持:

  • 直接播放 dfpwm
  • 对普通音频 URL 进行远程转码后播放
  • 自动或手动分配 main/left/right 扬声器
  • 通过 os.queueEvent 发送状态事件和控制事件
  • UI 模式和 -noui 模式

基本用法

speaker <url> [options]

示例:

speaker https://example.com/test.dfpwm
speaker https://example.com/test.mp3 -volume 1.5
speaker https://example.com/test.mp3 -pause -id music_1
speaker https://example.com/test.mp3 -noui
speaker https://example.com/test.mp3 -mainspeaker speaker_0 -leftspeaker left -rightspeaker right
speaker https://example.com/test.mp3 -speaker '{"main":["speaker_0"],"left":["left"],"right":["right"]}'

参数说明

必填参数

<url>

  • 要播放的音频 URL。
  • 只支持 http://https://

可选参数

-lefturl <url>

  • 指定左声道单独使用的音频 URL。
  • 不传时,左声道默认跟主 url 一样。

-righturl <url>

  • 指定右声道单独使用的音频 URL。
  • 不传时,右声道默认跟主 url 一样。

-server <url>

  • 指定远程转码接口。
  • 默认值:http://newgmapi.liulikeji.cn/api/ffmpeg

-noui

  • 不显示播放器界面。
  • 此模式下不会启动 UI 刷新协程。

-debug

  • 打开调试输出。

-pause

  • 启动后默认暂停。
  • 程序会先完成检测、转码、下载并发出 speakerlib_ready
  • 收到恢复事件后才真正开始播放。

-volume <number>

  • 设置音量。
  • 支持 03 的小数。
  • 例如:0.111.53

-id <string>

  • 指定本次播放实例的 id。
  • 所有事件都会携带这个 id。
  • 不传时会自动生成随机 id。

-speaker <spec>

  • 手动指定扬声器分组。
  • 优先级最高。
  • 一旦使用,不再采用默认自动检测结果。

可用形式:

-speaker speaker_0

表示把 speaker_0 加入 main

-speaker speaker_0,speaker_1

表示把多个扬声器加入 main

-speaker '{"main":["speaker_0"],"left":["left"],"right":["right"]}'

表示按 JSON 指定 main/left/right

-mainspeaker <name>

  • 手动指定 main 分组扬声器。

-leftspeaker <name>

  • 手动指定 left 分组扬声器。

-rightspeaker <name>

  • 手动指定 right 分组扬声器。

说明:

  • 只要出现 -mainspeaker-leftspeaker-rightspeaker 里的任意一个,就会先清空默认自动检测结果。
  • 然后只使用你手动传入的扬声器。

默认扬声器规则

不传 -speaker / -mainspeaker / -leftspeaker / -rightspeaker 时,程序会自动检测外设:

  1. 名为 left 且类型为 speaker 的外设进入 left
  2. 名为 right 且类型为 speaker 的外设进入 right
  3. 如果没有同时检测到 leftright
  4. 则所有扬声器都进入 main
  5. 如果同时检测到 leftright
  6. 其他剩余扬声器进入 main

事件总规则

所有 speakerlib_* 事件都遵循同一个规则:

  • 事件名后面的第一个参数一定是 id

也就是:

eventName, id, ...

例如:

speakerlib_stop, "music_1"
speakerlib_seek, "music_1", 12.5
speakerlib_state, "music_1", "{...json...}"

播放器发出的事件

speakerlib_downloading

表示开始进入资源准备阶段。

格式:

speakerlib_downloading, id, url

参数:

  • id: 当前播放实例 id
  • url: 主音频 URL

speakerlib_ready

表示资源已经准备完成,可以立即进入真正播放。

注意:

  • 表示“DFPWM 数据已经准备好”
  • 配合 -pause 时,收到这个事件后再发 resume会立即开始播放

格式:

speakerlib_ready, id, format, total

参数:

  • id: 当前播放实例 id
  • format: dfpwmaudio
  • total: 总时长,单位秒

speakerlib_play_start

表示真正开始播放。

注意:

  • 这个事件是在真正开始往扬声器写第一段音频前发出的
  • 如果使用 -pause,不会在 ready 时提前发出

格式:

speakerlib_play_start, id, url, json

参数:

  • id: 当前播放实例 id
  • url: 主音频 URL
  • json: JSON 字符串

json 内容示例:

{
  "url": "https://example.com/test.mp3",
  "volume": 1.5,
  "mode": "ui",
  "speakers": {
    "main": ["speaker_0"],
    "left": ["left"],
    "right": ["right"]
  }
}

speakerlib_play_pause

表示当前播放已进入暂停状态。

格式:

speakerlib_play_pause, id

speakerlib_play_resume

表示当前播放已从暂停恢复。

格式:

speakerlib_play_resume, id

speakerlib_play_end

表示音频自然播放结束。

格式:

speakerlib_play_end, id

speakerlib_play_stop

表示播放被停止。

格式:

speakerlib_play_stop, id

说明:

  • 点击 UI 的 [Exit]
  • 发送 speakerlib_stop
  • 或按 Esc

都会进入这个事件。

speakerlib_state

表示当前播放器状态快照。

格式:

speakerlib_state, id, json

参数:

  • id: 当前播放实例 id
  • json: JSON 字符串

基础字段:

{
  "id": "music_1",
  "url": "https://example.com/test.mp3",
  "total": 120.5,
  "progress": 18.0,
  "volume": 1.5,
  "mode": "ui",
  "paused": false,
  "open": true,
  "speakers": {
    "main": ["speaker_0"],
    "left": ["left"],
    "right": ["right"]
  }
}

附加字段会按时机出现,例如:

{
  "format": "audio",
  "ready": true,
  "playing": true,
  "action": "seek",
  "stopped": true,
  "finished": true
}

常见附加字段说明:

  • format: dfpwmaudio
  • ready: 资源已准备好
  • playing: 已开始播放
  • action = "seek": 刚执行过跳转
  • stopped: 已被停止
  • finished: 本次播放器生命周期已结束

控制事件

你可以从别的程序里通过 os.queueEvent(...) 控制播放器。

speakerlib_stop

停止播放。

格式:

os.queueEvent("speakerlib_stop", id)

speakerlib_pause

暂停播放。

格式:

os.queueEvent("speakerlib_pause", id)

speakerlib_resume

恢复播放。

格式:

os.queueEvent("speakerlib_resume", id)

speakerlib_seek

跳转到指定播放时间。

格式:

os.queueEvent("speakerlib_seek", id, seconds)

参数:

  • seconds: 目标时间,单位秒,可以是小数

示例:

os.queueEvent("speakerlib_seek", "music_1", 30)
os.queueEvent("speakerlib_seek", "music_1", 12.5)

speakerlib_volume

动态修改音量。

格式:

os.queueEvent("speakerlib_volume", id, volume)

参数:

  • volume: 03,支持小数

示例:

os.queueEvent("speakerlib_volume", "music_1", 0.5)
os.queueEvent("speakerlib_volume", "music_1", 2)

典型控制流程

启动并记录 id

shell.run("speaker", "https://example.com/test.mp3", "-id", "music_1")

等待 ready 后开始播放

适用于 -pause 启动:

shell.run("speaker", "https://example.com/test.mp3", "-id", "music_1", "-pause")

另一个程序里:

while true do
    local e, id, a, b = os.pullEvent()
    if e == "speakerlib_ready" and id == "music_1" then
        os.queueEvent("speakerlib_resume", "music_1")
        break
    end
end

监听状态

while true do
    local e, id, json = os.pullEvent("speakerlib_state")
    local data = textutils.unserializeJSON(json)
    print(id, data.progress, data.total, data.paused)
end

停止播放

os.queueEvent("speakerlib_stop", "music_1")

UI 说明

-noui 模式下:

  • 顶部显示当前阶段状态
  • 右上角 [Exit] 可停止播放
  • 进度条支持点击和拖动跳转
  • 中间按钮可暂停/恢复
  • URL 只显示一行,超出部分用 ...

程序结束时会自动清屏。

Description
No description provided
Readme 55 KiB
Languages
Lua 100%