Skip to content

1.9.1

Choose a tag to compare

@github-actions github-actions released this 09 Oct 03:46
· 18 commits to main since this release

发布说明摘自 CHANGELOG.md 的 1.9.1 一节。

新增

  • 品牌图标(详见 ADR-0069):
    新增品牌图形资产,落地到浏览器标签页与 Emby 默认头像;界面内(顶栏、日志)仍只有文字。

    • public/logo.png(512×512 透明底)作为浏览器标签页图标(favicon),
      public/index.html 与 public/login.html 各加一条 <link rel="icon">;README 顶部也引用这张图。
    • server/modules/emby/assets/default-avatar.png 换成同一张品牌图(仍是 606×606 透明底,
      Emby 默认头像口径不变)。
    • 对客户端的影响:浏览器标签页多一个图标;Emby 默认头像换图 —— 尺寸与 tag 口径不变
      (tag 仍是文件内容 md5),客户端会因内容变化重新拉一次头像。不涉及任何 Emby 端点契约。
  • 「关于」页内嵌公告(详见 ADR-0068):
    「设置 → 关于」页新增一张公告卡,内容取自仓库里的 notice.html —— 交流群地址、贡献者名单
    这类内容与代码分开维护,改仓库里那个文件即生效,不需要重新发版。

    • 新增端点:GET /api/panel/notice → {html, url, error?}(带 5 分钟缓存)。
      html 默认取自 https://raw.githubusercontent.com/<repo>/main/notice.html,经取源候选
      (APP_MIRRORS,与面板更新、插件库共用,见 ADR-0067)。
    • 新增环境变量 PANEL_NOTICE_URL 可覆盖取回地址(显式给出时不套镜像前缀);置 off / none / -
      关闭这张卡。
    • 内容为空或取不到 → 整张卡不显示;内容以隔离的内嵌 frame 渲染,不执行脚本、样式与面板隔离。
    • 对客户端的影响:仅面板「关于」页多一张卡;不涉及 Emby 端点。
      ⚠️ 走第三方代理时取回的内容可能与仓库原文不同,故按不可信内容渲染(不跑脚本)。
  • 字幕插件(第五类插件)与 Emby 标准字幕端点(契约变更记录见 docs/emby-compat.md;
    插件侧契约见插件仓库 media-bridge-plugins/docs/plugin-contract.md「七、字幕插件的动作」):
    面板新增第五类插件 subtitle,并落地 Emby 标准的字幕取用端点。

    • 新增端点:GET /api/emby/Videos/{ItemId}/{MediaSourceId}/Subtitles/{Index}/Stream.{Format}
      (含带 StartPositionTicks 的变体)—— {Format} ∈ srt/ass/ssa/vtt。面板从版本 Id 载荷里
      取出该轨的 ref,交给字幕插件的 fetch 动作取回内容后回字节
      (Content-Type 优先取插件给的,没给才按 Format 兜底)。
    • 详情 / 播放信息里挂字幕轨:条目详情、PlaybackInfo 的 MediaSources[].MediaStreams[]
      追加 Type:'Subtitle' 的流(Index / Codec / Language / DisplayTitle / DeliveryUrl 等),
      轨来自字幕插件 tracks 动作的申报。版本 Id 载荷由 {r, v?} 扩为 {r, v?, s?}
      (s = 流序号 → 字幕 ref 的映射;无字幕则不写,载荷与旧版完全一致)。
    • 影响哪些端点:GET /api/emby/Users/{UserId}/Items/{ItemId}(详情)、
      POST /api/emby/Items/{ItemId}/PlaybackInfo,以及上面新增的字幕内容端点。
    • 对客户端的影响:装并启用字幕插件后,版本会多出字幕轨、客户端可选中取用;没装字幕插件
      则一切与从前完全一样
      (不出字幕轨、载荷不变)。字幕插件是软依赖 —— 没装 / 没在跑 /
      tracks 失败都只降级(不出字幕轨、记一行日志),不破坏详情本身。
    • 真机对照见 docs/emby-realdevice/23-subtitles.md(未复测:
      本仓库内没有真机样本,落地依据是 Emby 官方端点形状 + 插件契约,不是抓包)。
  • 取源候选:内置公共 gh 代理,国内默认直连(详见 ADR-0067):

    • 改的是什么:从 GitHub 取东西时,默认先试内置公共 gh 代理(https://gh-proxy.com、
      https://ghfast.top),失败再退到官方直连;单次请求 20 秒超时。面板更新与插件库共用这一套:
      • 应用代码(查最新版本 + 下版本包 + 下校验);插件库(取清单 index.json + 取插件包)。
    • 新增环境变量 APP_MIRRORS(逗号分隔、有序)可覆盖;置 off / none / - 只走官方。
    • 影响哪些端点:面板侧「版本与更新」、容器首启的取源,以及 GET /api/plugins/library 的
      sourceUrl 与插件安装取包(不涉及 Emby 端点)。
    • 对客户端的影响:国内部署无需再手工找代理即可取源(含插件库);原来只有显式 PLUGIN_*_URL
      才能指定源,现在留空即走候选、失败自动降级;在意校验的用户可关掉镜像。
    • ⚠️ 安全口径:走第三方代理时包体与其校验值(应用代码 .sha256、插件 md5)同源,校验
      只防传输损坏、不防代理替换(有意接受的取舍,见 ADR-0067);要真实校验就把
      APP_SOURCE_URL(或 PLUGIN_INDEX_URL / PLUGIN_SOURCE_URL)指向自己信任的镜像。
    • 引导脚本在 docker/(不入库),本次同改;需重推镜像才对新容器生效。

变更

  • 品牌净化:对外 DTO 的自家字段与不透明 Id 前缀去掉 catpaw(契约变更记录见
    docs/emby-compat.md):

    • 改的是什么:ProviderIds.Catpaw → ProviderIds.MediaBridge;非标准字段
      CatpawSource → MediaBridgeSource(其 LineFilter 子对象同改);版本 / 媒体源 Id 前缀
      catpaw: → mbp:(catpawSourceId / parseCatpawSourceId → mbpSourceId / parseMbpSourceId);
      媒体库(Views)Id 前缀 catpawhome_ → mbphome_;PresentationUniqueKey 前缀 p-catpaw- → p-mbp-。
      另:面板自述 GET /api/meta 的 service 由 catpaw-panel 改为 mbp-panel;登录 cookie 名
      catpaw_panel → mbp_panel;备份包 manifest 的 service 同步改为 mbp-panel(旧备份包不再接受还原)。
    • 影响哪些端点:GET /api/emby/Users/{UserId}/Items/{ItemId}(详情)、POST /api/emby/Items/{ItemId}/PlaybackInfo、
      拉流 / 下载 / 字幕各端点里出现的版本 Id,以及 GET /Users/{UserId}/Views(库 Id)。
    • 对客户端的影响:改的全是不透明标识或面板自用字段(客户端只当字符串、或直接忽略),
      客户端无需改动;但客户端若缓存了旧的库 Id / 版本 Id,换版后对不上会取不到内容,清一次客户端缓存 /
      重新拉库列表
      即可。服务端数据无迁移:这些前缀都是运行时现算、不落库(emby.db 五表无任何
      catpaw 列),故不注册迁移任务、数据版本不动。
    • 真机对照见 docs/emby-realdevice/04 /
      10 / 23(未复测)。
    • 同时清掉面板自身文案 / 注释 / 示例里点名具体源的写法(设置项提示、聚合层注释、develop.md 的
      source 示例、package.json 关键词、CONTRIBUTING.md 术语表),面板不点名任何源、也不假设源的形态。
      这些不进契约、对客户端无影响。
  • 仓库与镜像改名,统一到 MediaBridge / mediabridge:

    • GitHub 仓库 dlushu/media-bridge-panel → dlushu/MediaBridge:自更新取 Release 的默认仓库路径
      (APP_REPO)随之改为 dlushu/MediaBridge,package.json 的 repository.url 与 README 同步更新。
      旧地址由 GitHub 重定向仍可访问,已装环境无需改动。
    • Docker Hub 镜像 dlushu/media-bridge-panel → dlushu/mediabridge(Docker Hub 名称须小写,
      故用 mediabridge)。旧镜像名不再更新,用旧名的部署需把 docker run / compose 里的镜像名换成
      dlushu/mediabridge 后再拉取。数据卷名 media_bridge-data、容器名、发布资产名
      media-bridge-panel-<版本>.tar.gz、备份文件名等均未变,改名不影响已有数据。
  • 登录态有效期可调,且改为「滑动过期」(语义与取舍见 ADR-0064):
    面板会话的有效期不再写死 30 天,可在「面板设置 → 安全」页按「数值 + 单位(分钟 / 小时 / 天)」调整,
    默认 15 分钟、最大 30 天。语义由"到点强制退出"改为空闲计时 —— 从最后一次操作起算,
    一直在用就自动顺延,只有空闲满这一时长才需要重新登录(会话在用到有效期的 1/4 时自动续签)。
    密码 / 登录接口的响应形状不变,iat 字段对前端不可见(会话是 HttpOnly cookie)。

  • 登录改为独立页面 /login.html:未登录访问面板会跳到该页,登录后跳回原地址。
    「记住密码」有两条路:① 浏览器 / 密码管理器的表单记忆(真实 <form> + 命名输入框 + autocomplete);
    ② 页上的**「记住密码」勾选框** —— 勾选且登录成功后,密码经 Base64 混淆存进本机浏览器存储
    (localStorage),下次打开登录页自动预填,取消勾选即清除。混淆不是加密(防随手翻看、防不了懂行的人),
    默认不勾,请按设备信任程度取舍。

  • 开源协议由 MIT 改为 AGPL-3.0。

修复

  • 测速汇总行口径写错:成功 N(含 M 个无结果) 里 M 其实不在 N 里
    (计数是三桶互斥:有结果 / 无结果 / 失败),M > N 时读来矛盾。按业务口径
    「无结果 = 站活着、不算失败」改为 成功 N+M(其中 M 个无结果),数字对得上总数。
    只改日志措辞,okCount / emptyCount 的 API 口径不变。

  • 开机时首页插件行清单空打一轮 NOT_READY:启动顺序是拉起插件进程后立刻预热行清单,
    但插件握手是异步的——还没就绪的插件(日志里两行 ✘ …插件还没就绪)纯属启动竞态。
    现在预热先等插件就绪(轮询 running,起不来 / 崩了 / 超时就跳过)再拉行清单,
    这两行噪音日志消除,预热一次到位;拿不到的老兜底(快照过期自动重刷)不变。

  • 老内核 / 网络盘环境缓存库连环报错(GitHub issue #3,disk I/O error → no such table: line_cache):

    • 根因一:缓存库(线路结果 / 图片索引)开 WAL 需要共享内存,CentOS 7 老内核 overlayfs、
      NFS / SMB 卷上拿不到,PRAGMA journal_mode = WAL 直接抛 disk I/O error。
    • 根因二(面板 bug):cachedb.open() 先把句柄赋给模块级变量、后跑 pragma 与建表,
      pragma 一抛错就留下半初始化句柄——之后所有访问报 no such table,完全掩盖真实原因。
    • 改的是什么(ADR-0072):
      open() 原子化(全部初始化成功才登记句柄,失败关库重抛);WAL 起不来时打一条 ✘ 级日志
      并降级 DELETE journal 继续跑——缓存是可丢数据,不该为它让整个功能不可用。
    • 对用户的影响:老内核 / 网络盘环境面板照常可用(丢一点缓存读写并发收益,无感);
      卷本身坏掉(盘满 / 断连)时报的是真实原因,不再是误导性的 no such table。
  • 「日志」页的「仅错误」过滤抓不到业务失败行:面板约定失败行打 ✘ 前缀,但调用点走的
    是 console.log(级别是 log)——logbus 只按 console 方法分级,导致这些行进不了
    「仅错误」、也不标红。现在按行首符号归级(✘→error、⚠️→warn),几十处调用点不用改;
    标红样式(CSS 早已备好)随之生效。

  • HamHub 点播时反复失败(等几秒才起播):HamHub 把面板下发的根相对拉流地址
    (/videos/{id}/stream.hls?…)按 origin 解析(RFC 3986:根相对替换整个 path),把 /emby 丢掉,
    打的是 http://<主机>:<实例端口>/videos/… —— 撞上实例端口的 404 守卫,反复退避重试(抓包里
    /videos/… 404 四次、改用 /emby/videos/… 才 200)。

    • 改的是什么:实例端口的路径归一化多认一条 —— 不以 /api/ 开头的路径一律当作 Emby 根路径
      (真机 Emby 本就把端点挂在根路径,见 ADR-0065)。
    • 影响哪些端点:实例端口上的全部 Emby 端点(重点:直连拉流 videos/{ItemId}/stream、
      Items/{ItemId}/Stream、下载、字幕内容)。面板端口(面板 UI 所在)不变。
    • 对客户端的影响:更宽容、客户端无需改动 —— 按 origin 解析(HamHub)与字符串拼接(AfuseKt)
      两种行为都能命中;下发的地址一字未改;面板自用端点(accounts / instances 等)仍照旧拒绝。
    • 真机对照见 docs/emby-realdevice/12-direct-stream.md 的 12-6(未复测)。
  • Yamby 打不开带字幕轨条目的播放页:字幕流(MediaStreams[] 里 Type:'Subtitle')缺
    IsDefault / IsForced 字段,Yamby 把 IsDefault 当必填,整条 PlaybackInfo 反序列化直接抛
    SerializationException。已补 IsDefault:false / IsForced:false(外挂字幕本就不是默认/强制轨,
    与真机一致)。其余客户端不受影响(它们读不到该字段时按 false 处理)。真机对照见
    docs/emby-realdevice/23-subtitles.md 的 23-4(未复测)。

  • DirectStreamUrl 容器后缀:hls 映射为 m3u8(曾为对齐真机去掉后缀,实测回归后恢复)(契约变更记录见
    docs/emby-compat.md;决策见 ADR-0071,
    取代 ADR-0070):

    • 改的是什么:MediaSources[].DirectStreamUrl 保持带后缀形态
      /videos/{ItemId}/stream.{容器}?…,但不照抄 Container 字段:hls → stream.m3u8
      (hls 是 DTO 容器枚举值、不是播放器认得的扩展名;ExoPlayer 系按后缀推断类型只认 .m3u8,
      真机的 HLS 拉流地址本就是 *.m3u8),其余容器原样拼(stream.mkv / stream.mp4)。
    • 来龙去脉:本发布周期内曾按真机形态(予初Emby 4.9.5.0 的 DirectStreamUrl 是裸 stream)
      去掉过后缀(ADR-0070),实测打断了一批靠 URL 后缀判类型的客户端(如 CapyPlayer/1.1.6:
      面板清单中继正常回 200,客户端却把 m3u8 文本当普通文件嗅探,报
      UnrecognizedInputFormatException)—— 恢复后缀,能播优先于真机形态对齐。详见
      docs/emby-realdevice/11-items-playbackinfo.md 的 11-5(未复测)。
    • 影响哪些端点:仅 POST /api/emby/Items/{ItemId}/PlaybackInfo 的
      MediaSources[].DirectStreamUrl。MediaSources[].Id(版本 Id)、Path、Container 字段本身不变。
    • 对客户端的影响:客户端无需改动 —— 拉流路由 stream(\.[a-z0-9]+)? 对裸 stream 与
      stream.{ext} 一并认;HLS 源的 DirectStreamUrl 由裸 stream 变为 stream.m3u8,
      靠后缀判类型的客户端恢复播放。

面板「设置 → 版本与更新」里可以手动更新到这个版本;它只安装正式 Release 的资产并校验 sha256。