找回密码
立即注册
搜索
发回帖 发新帖

6706

积分

0

好友

850

主题
发表于 17 小时前 | 查看: 5| 回复: 0

装好 LX Music,界面干净,搜歌有结果,点播放却弹「换源失败」。它自己不存一首歌,音频全凭一段你亲手导进去的 JavaScript 脚本返回。这篇讲清它为什么长这样:源怎么接、服务怎么搭、桌面和安卓怎么同步,以及这套设计要你付什么账。

下载、安装、打开。第一眼挺讨喜:左边是搜索、歌单、排行榜、我的列表,中间是列表,底下一条播放栏。深色主题,图标克制,没有开屏广告,没有登录弹窗,也没有「开通会员」的角标。

搜一首歌,结果出来了,歌手、专辑、时长都对。点播放。

「换源失败,请尝试手动换源」。

换一首,一样。再换一首,还是一样。

第一次遇到这行字的人,多半会往三个方向猜:装错了包、网络抽风、软件坏了。三个都不对。它一点没坏,这就是它正常的样子。

作者对这件事的态度写在文档里:软件内的默认设置和界面操作不以新手友好为目标,装好之后建议先按自己的习惯把设置翻一遍,顺便读一遍播放列表机制和快捷键。这话说得很直,也很少见——多数软件会把「新手引导」当作必须做的功课,它反过来主动抬高门槛。

抬高门槛的意思不是为难人,是筛人。一个需要你自己接源的播放器,用户里注定有一部分会在第一步就走掉,剩下的那部分人不需要被哄。所以它没有新手向导,没有一键配置,没有「猜你喜欢」,也没有任何东西在你看不见的地方替你决定。

一、装完是个空壳,这件事是设计

LX Music 的中文名叫洛雪音乐助手,是一个开源的音乐播放器。桌面版用 Electron 加 Vue 3 写,跑在 Windows、macOS、Linux 上;安卓版是另一个独立项目,界面重画过,逻辑重写过。两端都免费,都没有账号体系。

但它自己不含任何音频。

播放按钮按下去之后,程序做的事只有一件:把这首歌的歌名、歌手、歌曲 ID 交给「源」,等对方返回一个链接,然后拿这个链接去解码播放。源没接上,就没有链接;没有链接,就没有声音。

所以它的使用顺序和别人是反的。别家是「装好就能听,想听更多就付费」,它是「装好是个壳,先把源接上,才有得听」。

这个顺序会让相当一部分人第一次就放弃。我见过最典型的抱怨是「搜得到为什么放不了」——因为搜索和播放在这套架构里是两条完全不同的链路:搜索走的是平台公开的检索接口,只要联网就有结果;播放走的是源脚本,没装源就没有第三步。

也正是这个顺序,让它在一个人挤人的赛道里活了下来。它把「音频从哪来」这件事,从软件内部搬到了软件外部。

搬出去之后,很多东西跟着变了。它不需要版权授权,所以敢免费、敢无广告、敢不注册;它不需要为曲库付钱,所以没有动力往你界面上塞任何东西。界面冷淡到有点孤僻,不是因为作者有洁癖,是这个结构里本来就没有需要推销的货。

软件早年内置过几个平台的源,后来因为版权投诉,把所有内置源都拿掉了。这件事的结果比过程重要:它从「一个能听歌的软件」变成了「一个能被接上源的播放器」。 听什么,交给你。

顺带说一句它没变的部分:本地文件不需要源也能放。你把硬盘上攒的无损拖进「我的列表」,它照放不误,歌词封面自己配。只有当你加的本地文件坏了、被删了,它才会拿歌名去搜一首在线的顶上——这时候才轮到源出场。

所以「免费」这个词得说清楚。软件本身确实不收钱,也没有任何地方能让你付钱,它连捐赠都不收。但它把成本换了一种形式收:你要花时间接源、维护源、琢磨为什么不出声。这笔时间账,第一次用的人往往算漏了。嫌麻烦的人觉得它难用,愿意折腾的人觉得它省心,分歧就在这儿——两边算的根本不是同一本账。

LX Music 空壳架构示意:源通过接口为播放器提供音频、歌词、歌图

二、一个音乐 App,其实是三样东西

要看懂它为什么长成这样,得先把「音乐 App」这个词拆开。

一个能听歌的软件,里面其实装着三样东西:曲库,音频文件本身;检索,歌名、歌手、专辑、歌单、排行榜这些信息;播放器,解码、列表、歌词、音效、界面这一整套。

平时说的「我买了会员」,买的只是曲库的使用权。检索信息大部分是公开的,未登录状态下去平台自己的服务里问,一样能拿到结果。播放器更不值钱,它是一段可以被重写的代码。

三样捆在一起卖,是商业模式的选择,不是技术上的必然。拆开看,每一件都能独立存在:曲库可以只是硬盘上的一堆文件,检索可以只是几个 HTTP 接口,播放器可以只是一个能解码、能管列表、能滚歌词的壳。

LX Music 做后两件,把第一件留空。这就是它的全部设计。

先看检索这一层。 它要面对的第一个麻烦是各家字段不统一。同一个概念,在这家叫 songmid,在那家叫 hash,换一家又变成一串数字 id;歌手字段有的给数组,有的给一个用斜杠拼起来的字符串;封面有的直接给图,有的给一个需要再拼前缀的相对路径。

于是软件里得有一层归一化:把六路来源的返回结果,塞进同一个「音乐信息」结构里——统一的 ID、统一的歌名、统一的歌手、统一的专辑、统一的时长、统一的音质标签。这层做得干净,界面上就看不出来源差异;做得不干净,就会出现同名歌曲混乱、封面错位、时长显示 00:00 这种小毛病。

再看播放器这一层。 它拿到的不是一个文件,是一个链接。这就决定了它必须做流式播放:能边下边播,而不是等整首下完再响。切歌的时候要做预取,提前把下一首的地址取好,否则每次切歌都要等一两秒握手。解码要能吃 mp3、aac、flac 这些常见格式,flac24bit 这种高码率还得看设备撑不撑。

列表逻辑也在这层。它默认的规矩是「听到即入库」:你在搜索、歌单、排行榜里点一首歌,它会先把这首歌加进「试听列表」,再播放。试听列表是临时的、会被新歌挤掉的,收藏是长期的、要你手动加的。两个列表分开,是为了让你随手试听的行为不污染收藏。

还有个反直觉的设计叫「稍后播放」。加进去的歌进入一个优先级最高的队列,点「下一曲」会按序消耗它,但回不到队列里的历史——「上一曲」找不回来。而且只要你切歌不是通过上一曲、下一曲,而是直接双击了别的列表里的歌,这个队列会被直接清空。它的定位是「临时插队」,不是「第二个播放列表」,用之前得知道这条。

歌词也在这层处理,而且是四份:原文、翻译、罗马音、逐字。逐字那份格式很特别,[00:00.000]<0,36>测<36,36>试,方括号里是整句起点,尖括号里是每个字的起止毫秒。有了它才能做卡拉 OK 那种一个字一个字点亮的效果,普通 LRC 只能整句高亮。

音效同样是这层的东西。多段均衡器、卷积混响(自己选一份 wav 脉冲响应文件当空间)、声像扩展、变调。默认全关,因为这些处理都吃性能,也会改变原曲的味道。

拆到这儿就能看出区别了:曲库型播放器的产品经理在谈版权,接口型播放器的作者在谈解码和列表。 前者卖的是内容,后者磨的是工具。

对比一下更清楚:

维度 曲库型播放器 接口型播放器
听歌的前提 会员有效 源能返回地址
装完的状态 能听 壳
失效的表现 会员到期 换源失败
谁在维护曲库 平台 你自己

第四行是这张表里最硬的一行。「谁在维护」决定了你在这件事里到底是用户,还是半个运维。

音乐 App 拆解示意:曲库、检索、播放器三者分离,源脚本补上曲库空缺

三、自定义源,是一个跑在沙箱里的脚本

「源」不是配置文件,不是订阅链接,也不是一个填进去的网址。它是一个 .js 文件。

用 JavaScript 写,ES6+ 语法,UTF-8 编码。导入之后,这段代码会在 LX Music 里跑起来。它拿不到你的文件系统,也调不动 Electron 的能力,它被允许做的事情只有三件:发请求、返回地址、报告自己支持什么。

这个边界值得留意。它决定了源脚本能干什么,也决定了源脚本干不了什么——它不能读你的本地文件,不能往你的硬盘写东西,不能偷偷起一个后台服务。它能做的就是把一个 HTTP 请求发出去,把回来的东西整理一下交回去。

整个交互是一套事件收发。脚本启动时会拿到一个全局对象 globalThis.lx,里面装着:

成员 作用
EVENT_NAMES 事件名常量:inited、request、updateAlert
on(name, handler) 注册回调,等应用来找
send(name, data) 主动向应用发事件
request(url, opts, cb) 发 HTTP 请求,不受跨域限制
utils buffer、crypto、zlib 三组工具

那个「不受跨域限制」是个关键让步。浏览器里发请求会被同源策略拦,源脚本没有这个烦恼,因为它的请求实际上由主进程代发。没有这条,绝大多数平台接口都对接不了。

两个事件构成一次握手。

inited 是脚本对应用说的第一句话,也是一份能力声明:我支持哪些源、每个源支持哪几档音质、要不要打开开发者工具。它必须在脚本跑完之后主动发出去。发出去之前只要抛过一次错,这个脚本就算初始化失败,直接作废——没有重试,没有降级,你在设置里只会看到一个永远转圈的「初始化中」。

request 是应用反过来找脚本:我要这一首,给我地址。回调必须返回 Promise,返回别的都不认。

还有一个 updateAlert 事件,是给源作者用的:脚本发现自己的接口变了,可以主动弹一个更新提示,带上更新日志和更新地址。一次运行只能调一次,日志长度有上限,超出的部分会被丢掉。这是这套体系里少见的「作者与用户之间的广播通道」——毕竟软件本体不维护源,源过期了只能靠源自己喊一声。

一个最小的骨架长这样:

/**
 * @name 示例音乐源
 * @description 只演示结构,不含任何真实接口
 * @version 1.0.0
 * @author 尧哥
 */
const { EVENT_NAMES, request, on, send } = globalThis.lx

// 声明这个源支持哪几档音质
const qualitys = {
  kw: { '128k': '128', '320k': '320', flac: 'flac', flac24bit: 'flac24bit' },
}

// 应用来要地址
on(EVENT_NAMES.request, ({ source, action, info }) => {
  if (action !== 'musicUrl') return Promise.reject(new Error('unsupported'))
  return new Promise((resolve, reject) => {
    request('https://example.com/api', { method: 'get' }, (err, resp) => {
      if (err) return reject(err)
      resolve(resp.body.url)
    })
  })
})

// 报告自己已就绪
send(EVENT_NAMES.inited, {
  openDevTools: false,
  sources: {
    kw: {
      name: '酷我音乐',
      type: 'music',
      actions: ['musicUrl'],
      qualitys: ['128k', '320k', 'flac', 'flac24bit'],
    },
  },
})

三十行,一个能跑的空壳。文件开头那段注释不是随便写的,@name 会变成源列表里显示的名字,@description 是名字下面那行小字,导入之后你在设置里看到的就是它们。

真实可用的源,是在这个骨架上不断填请求、签名、解密、兜错。

源用 6 个键区分:kw 是酷我,kg 是酷狗,tx 是 QQ 音乐,wy 是网易云,mg 是咪咕,local 是本地音乐。前五个只支持 musicUrl 一个动作;local 多两个,lyric 和 pic——本地文件没有平台能问,歌词和封面得自己想办法,可以读同目录下的同名文件,也可以去网上找。

音质四档:128k、320k、flac、flac24bit。这里有个容易被忽略的点:界面上能选哪几档,不是软件定的,是脚本在 inited 里声明的。 脚本只报 128k,你的设置里就只有 128k 一项。脚本报了 flac,实际返回的却是 128k 的地址,软件也照播不误——协议里写得很直白,它只负责转发,不校验对方给的对不对。

看完这些成员,utils 那部分是全场最值得琢磨的。里面给了 md5、aesEncrypt、rsaEncrypt、randomBytes,给了 inflate 和 deflate,还给了 buffer.from 和 bufToString。

一个「取个播放地址」的接口,为什么要配 MD5、AES、RSA 和解压?

因为真实的平台接口不裸奔。参数要签名,响应被压缩,个别字段加过密。作者把这套工具做进宿主环境,等于用代码承认了一件事:写源的本质,是去对接一个并不打算配合你的接口。 这不是给新手准备的玩具,这是给能看懂网络请求的人准备的工具箱。

源脚本与应用的事件交互时序图:inited 声明能力,request 请求地址,初始化失败即作废

写源工具链示意:签名、加密、解压、二进制转换是真实接口对接的必备能力

四、自己写源,会撞上什么

如果你打算自己动手,先把预期调对:这不是写完就能一直用的事,这是一件需要跟着接口不断修补的事。

第一道坎是签名。平台接口通常要求带上时间戳和签名参数,签名算法可能是参数排序拼串后做一次 MD5,也可能是对某个关键字段做 AES 加密。utils 里那几个方法就是为这一步准备的——md5 算摘要,aesEncrypt 造加密串,randomBytes 生成随机串防重放。

第二道坎是响应格式。返回的可能是嵌套 JSON,也可能是被压缩过的二进制;可能直接给地址,也可能给一个还得再请求一次的中间 ID。inflate 和 bufToString 是给这类情况兜底的,buffer.from 则用来处理 base64 和二进制之间的转换。

第三道坎是风控。同一个接口,请求太密会被限;请求头缺字段会被拒;换了 IP 之后行为不一致也会被拦。这些都没有文档,只能靠试。更麻烦的是它不对称:你花一晚上调通的东西,对方改一个参数名就全废,而你收到的是一个和「网络不通」看起来一样的报错。

写不出地址时,LX Music 给出的报错只有三句,得会分辨:

  • 换源失败,请尝试手动换源:所有勾选的源都没返回地址。要么脚本初始化就没成功,要么它依赖的接口整体挂了。
  • 请求异常,可以多试几次:请求根本没走通。网络、系统代理、对方风控,都可能有份。
  • 音频加载出错,5 秒后切换下一首:地址拿到了,但那个地址在你这儿打不开。过期、防盗链、地域限制是常见原因。Windows 上如果开着系统代理,也会固定出现这句,把「Internet 选项」里的代理勾掉就好。

源在设置里其实只有三种状态:名字后面转圈的「初始化中」、打勾的正常状态、以及勾着但一直失败。三种状态对应三条完全不同的排查路径,混着查是最浪费时间的。

排查顺序也有讲究。先看源状态:如果名字后面一直显示「初始化中」,问题在脚本自己身上,往下就不用查了,翻代码比改网络快——多半是它在 inited 之前抛了错,或者依赖的接口第一次请求就失败。如果源显示正常但全都不出声,去手动换一次源,能出声说明是某一个源的问题,不能出声说明是网络或者脚本整体失效。最后才去查网络代理——这一步排在最末,是因为它最容易被误判,也最难被证伪。

还有一件常被忽略的事:源可以同时装好几个。 设置里勾选多个源,一个返回失败会往下试另一个;也可以在播放失败时手动换。这解释了为什么有些人的源列表里塞了七八个文件——不是因为贪心,是因为没有哪个能长久稳定,多备几个才能扛住下一次失效。

桌面版留了一条调试通道:inited 里把 openDevTools 打开,脚本能获得一个开发者工具窗口,console.log 直接可见。安卓版没有这个选项,出问题只能靠猜——这也是我建议先在桌面端把源调通、再往手机上搬的原因。

顺带一个常被踩的坑:歌单不能跨源打开。你从这家平台复制的歌单链接,必须在「打开歌单」的对话框里把歌单源切到对应平台,否则它会以为什么都没找到。歌单的检索和歌曲的播放是两套接口,源只管后者。

LX Music 三种报错场景示意:换源失败、请求异常、加载出错,排查顺序先看源状态

五、桌面和安卓,不是同一份代码

桌面版和安卓版看着像同一个软件的两套皮肤,其实是两个仓库、两套实现。

桌面版基于 Electron 30 以上加 Vue 3,覆盖 Windows 7 及以上、macOS、Linux。安卓版是独立的移动端项目,跟桌面版共享的只有「源脚本」这套协议和同步协议,界面和内部逻辑各写各的。

数据存在哪,是个实用信息:

系统 默认数据目录
Windows %APPDATA%/lx-music-desktop
macOS ~/Library/Application Support/lx-music-desktop
Linux ~/.config/lx-music-desktop

Windows 上有个小机关:程序目录里如果存在一个叫 portable 的文件夹,软件会自动改用它存数据。等于自带绿色版——整套拷进 U 盘,换台机器插上就能接着用,歌单、设置、下载记录都在里面。换机迁移也可以直接拷这个目录,比找导出按钮省事。

安装本身有两个坑,都跟权限有关。一是别选「为使用这台电脑的任何人安装」,选「仅为我安装」,装到当前用户目录下,否则容易在写配置时被拦。二是别在同一个系统里装好几份,残留的旧文件会把数据目录和注册表搅在一起,表现出来就是装完打不开、或者打开的是旧界面。

两端各自还有几样只有自己才有的东西。桌面版有独立的桌面歌词窗口,能横排也能竖排,可以锁位、调透明度、分别设置已唱和未唱的颜色,暂停或主窗口全屏时可以自动隐藏——写东西的时候把歌词贴在屏幕角落,比来回切窗口舒服。快捷键也分两档:窗口聚焦时才生效的本地键,和系统级的全局键,全局那档默认是关的,需要自己去设置里打开。

安卓版拿手的是移动场景:通知栏控制、定时关闭、后台播放。这些在桌面版上没有,也没必要有。所以这两端不是「谁替代谁」,是两个界面各自贴着自己的使用场景重画了一遍,共同点只剩数据格式和源协议。

两端真正的差异在源脚本的运行环境上:

差异 桌面版 安卓版
调试开关 inited 可开开发者工具 无此选项
工具方法 全部可用 部分不可用
宿主 API 完整 极少
内置对象 未冻结 只能扩展,不能覆盖

最后一行值得多说两句。安卓版把预加载脚本和源脚本放在同一个环境里跑,为了不让源脚本碰到预加载脚本的东西,除了三个 toString,其余的 JavaScript 内置属性全部冻结。结果是 Array.prototype.push = ... 这种覆盖写法直接无效,但 Array.prototype.myPush = ... 这种扩展写法是允许的。

这条限制带来的实际后果是:桌面版能跑的源,拷到安卓上大概率跑不起来。 得找专门标注了移动端的,或者自己改。导入方式也不一样,安卓受存储权限限制,得在设置里走「本地导入」挑文件,没法像桌面那样把文件拖进去。

两端要真正连成一套,靠的不是账号,是同步服务——下一节说。

桌面版与安卓版架构差异对比:两套独立代码,通过自建同步服务对齐数据

六、可自建的不只是源

标题里说「可自建服务」,指的不止是源。这套软件把自己拆成了好几个能被你接管的部件。

第一个是同步服务。 它解决的是「桌面收藏的歌,手机上怎么看到」。桌面版里有个「数据同步」设置,能做两种角色:服务端模式,让本机在局域网里给别的设备提供同步;客户端模式,去连另一个服务端。安卓版只有客户端模式。

局域网这套操作很朴素:桌面端选服务端模式、启用,它会显示一个地址和一个端口(默认 23332);手机端把这个地址填进「同步服务地址」,注意填完要按一下回车让它生效,再点「启用同步」。首次同步时如果两边列表都不空,桌面端会弹一个窗口让你选合并方式,之后就不用了,会自动按两边内容合并。

连不上时有个很干脆的验证方法:手机浏览器打开 http://桌面地址:23332/hello,能返回一行 Hello~ 就说明网络通了,问题在别处。通不了再看三件事——两边是不是连在同一个路由器下、电脑防火墙有没有拦这个端口、路由器是不是开了 AP 隔离(公共网络里常见)。

有服务器的话,官方还放出了一个独立的同步服务项目,可以部署上去,长期用、跨网络用。配上域名和 SSL 之后,客户端填 https://你的域名 就行。要注意这个功能官方标了实验性,而且传输是明文的——局域网里凑合,公网上务必套一层加密,别裸着暴露端口。

第二个是开放 API。 设置里打开之后,本机会起一个 HTTP 服务,默认只监听 127.0.0.1,端口 23330。它把播放器变成了一个可以被程序调用的对象:

接口 用途
/status 当前状态:歌名、歌手、专辑、进度、时长、播放速率
/lyric 当前 LRC 歌词全文
/lyric-all 原文、翻译、罗马音、逐字歌词四份一起给
/play、/pause、/skip-next、/skip-prev 播放控制
/seek、/volume、/mute 进度、音量、静音
/collect、/uncollect 收藏与取消收藏
/subscribe-player-status SSE 长连接,状态一变就推

/status 支持 filter 参数只取你要的字段,别每次都拉全量。要实时状态就别轮询,官方明确建议走 SSE:

# 只拿三个字段
curl "http://127.0.0.1:23330/status?filter=status,name,progress"

# 状态一变就推过来,长连接不关
curl -N "http://127.0.0.1:23330/subscribe-player-status?filter=status,name,progress"

第三个是 Scheme URL。 以 lxmusic:// 开头的协议链接,在浏览器里点一下就能唤起软件,可以直接搜索、开歌单、播放指定歌曲。作者还配了一个油猴脚本,装上之后网页上的歌能直接丢给桌面版放。

还有一个更土但更好用的东西:启动参数。给桌面快捷方式加一个搜索参数,双击就能直接搜某首歌,不用先打开软件再敲键盘。配合 Scheme URL 一起用,等于把「想起一首歌到听见」这段路压到了一步。

这几样凑齐,它的身份就变了。它不只是一个你点着用的播放器,还是一个可以被编排的音频节点。

想象几个具体用法:直播的时候,脚本订阅 /status,把当前播放的歌曲名推到屏幕上;写稿卡住了,用一个全局快捷键切下一首,不用切窗口;家里那套自动化,语音说一句「放点安静的」,由它去执行;甚至可以在自己的笔记软件里做一个按钮,点一下就把当前在放的歌记进日志。

这些事在任何一家平台的客户端上都做不到,因为它们不会把控制权交出来。它们的接口是给自家 App 用的,你的脚本进不去。

最后提醒一句边界:开放 API 默认只绑本机。别为了远程访问把它绑到 0.0.0.0、再往路由器上做端口映射——那等于把你电脑上的播放控制权随手放到了公网上,而它没有鉴权。

LX Music 开放 API 接口地图:23330 端口提供状态、歌词、控制、收藏与 SSE 订阅

七、它的代价,写在协议里

讲到这儿,该把不好听的部分摆出来了。

先说法律边界。 它的许可协议是 Apache 2.0 加一份补充条款,补充部分有四条绕不开:

  • 使用过程中产生的版权数据,务必在 24 小时内清除;
  • 项目只用于技术可行性的探索与研究,不接商业合作,也不收捐赠;
  • 禁止在违反当地法律法规的情况下使用;
  • 协议原文里写着「音乐平台不易,请尊重版权,支持正版」。

这四条不是摆设,是作者给自己的定位。他做的从来不是正版替代品,而是一个研究用的播放器壳。这篇文章也不会提供任何具体的源地址——那种东西今天能用、下周就废,写进来只会让文章比软件先过期,还容易把读者带到不该去的地方。

再说技术边界。

源会失效,而且会经常失效。这不是 bug,是这套架构的固有成本:接口在产品侧随时可能改,改了你这边就断。你得接受「今天能听,明天可能要折腾半小时」这个节奏。也正是这个节奏,让它的用户群天然分层——愿意动手的人留下来了,只想听歌的人三天就卸了。

返回的音画不匹配,它管不了。协议里写得很清楚:它只是把歌名歌手交出去,对方返回什么链接,它就当那是这首歌。所以偶尔会出现播出来是另一首歌、或者干脆是一段静音的情况。这是设计上的已知缺陷,不是偶发故障,你也没法靠重装解决。

检索和播放的粒度也不一致。搜索能同时看到六个平台的结果,点下去却只能由当前勾选的源去取;歌单要对应平台的源才能打开;同一个歌单里混着不同平台的歌,换源的时候会出现「这首能放、那首不能放」。

下载和缓存这类边角也常有小事故。最常见的是下载报 ENOENT: no such file or directory——它想往你设置的目录里写文件,但那个目录没有写权限,或者盘符已经拔掉了。换个目录就好,不用重装。安卓上还有一类怪现象:每首歌放到一半自动切下一首,官方给的办法是去设置里关掉「音频卸载」,然后完全重启 App。这些都不是设计缺陷,是宿主环境的差异没抹平。

平台覆盖也有明确的缺口:目前没有 iOS 版,也没有 HarmonyOS NEXT 版的计划。苹果手机用户和纯血鸿蒙用户,这条路走不通。

还有一条要提前知道的信息:作者的开发精力已经主要转向新项目 Any Listen,那个项目实现了 LX Music 的大部分功能,还多了 WebDAV 相关的能力。LX Music 现在仍然可以正常下载和使用,但如果你打算长期依赖它,心里得有个数——别把它当成一个会一直往前跑的东西,也别把全部收藏只存在它一家手里。同步服务那套自建方案,某种程度上就是为这种情况准备的:数据在你自己的机器上,换个客户端还能接着用。

LX Music 四条使用边界:版权数据 24 小时清除、非商业、源会失效、无 iOS 与鸿蒙版

八、谁该装,谁别折腾

说到取舍,其实只有三类人真正需要它。

第一类,本地曲库为主的人。 你手上有一堆自己攒的无损文件,缺一个干净、不要会员、不偷偷上传的桌面播放器。LX Music 的 local 源就是为这个准备的:本地文件不用联网也能放,标签读不出来会退回文件名,歌词封面可以自己配。这条路它做得挺稳,而且跟版权无关,不会跟着接口一起失效。

第二类,愿意为「能改」付时间的人。 你会看网络请求,能读别人的脚本,出问题愿意翻日志而不是发帖问「为什么不能用」。这套东西对你来说不是软件,是一套工具,改起来比用起来有意思。

第三类,有服务器、想自己掌控数据的人。 你不接受歌单存在别人的云上,宁可自己部署一个同步服务。那它给的很对味:源是你的、同步服务是你的、控制接口只在本机,换客户端也不丢东西。

举个最平常的落地场景:一台不吃灰的旧笔记本接一块移动硬盘,专门装无损;LX Music 常驻在上面,开着服务端模式的同步;手机连同一个局域网填上地址,收藏双向合并;客厅那台小主机上写个脚本订阅 /status,把当前在放的歌名显示在屏幕上。整套东西加起来不花一分钱,也没有任何一个环节的数据经过别人的服务器。

这套方案的技术门槛其实很低,真正的门槛在心理上——你得接受「这件事由我负责」。源失效了是你的问题,同步连不上是你的问题,歌单丢了是你的问题。商业产品把这些都接过去了,代价是你要按月付钱,并且接受它的界面、它的推荐、它的开屏。两边都在做交换,只是换的东西不一样。

反过来说,三类人别折腾:

只想点开就听的人,别装。它需要你先做一步准备工作,这一步对不愿意动手的人是硬门槛,而且这一步没有官方答案。

需要车机、投屏、全家桶自动同步的人,别装。它的双端同步要你自己搭服务,跨设备体验跟商业产品差着量级。

不能接受「随时可能失效」的人,别装。付费买的就是稳定,这件事它给不了,也不打算给。

适合与不适合使用 LX Music 的三类人对照图:本地曲库、愿意改、要掌控;只想听、要全家桶、不接受失效

至于我自己,用法很朴素:桌面上常驻,本地文件为主,偶尔接个源听点买不到的现场版。它替代不了任何一个音乐会员,但它补上了会员给不了的那部分——一个不属于任何人、只属于我这台机器的播放器。

回头看,这套设计最聪明的地方,不在技术难度,在责任划分。它把「放什么」交出去,把「怎么放」攥在手里,于是它既不用为内容负责,也不必为内容妥协。界面干净、没有广告、不收一分钱,都是这个划分的自然结果。

代价是你要多干一点活。这笔交易划不划算,取决于你是想买一个结果,还是想留一个选择权——这也是云栈社区里常被拿出来聊的话题。

把曲库掏空之后,剩下的部分才看得出一个播放器的手艺。

—— 尧哥

参考

  1. LX Music 桌面版文档:https://lxmusic.toside.cn/desktop/ — 技术栈、平台支持与文档总入口
  2. 自定义源脚本编写说明:https://lxmusic.toside.cn/desktop/custom-source — 事件、动作、音质与工具方法的权威定义
  3. 开放 API 服务:https://lxmusic.toside.cn/desktop/open-api — 本机接口、字段与 SSE 订阅
  4. 许可协议:https://lxmusic.toside.cn/desktop/license — Apache 2.0 补充条款全文



上一篇:OpenBot 多 Agent 常驻协作工作台:工位、队列与文件传输拆解
下一篇:给 Claude Code 装上 ccstatusline:Token、Git 和上下文一目了然
您需要登录后才可以回帖 登录 | 立即注册

关闭

站长推荐上一条 /1 下一条

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-11-2 20:20 , Processed in 0.082680 second(s), 43 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表