这条 Emby 播放链路,我终于一点一点折腾通了

这几天我一直在和一条很别扭的播放链路较劲。

本来想得挺简单:把网盘里的资源通过 CMS + strm + Emby + 反代 这一套挂起来,再顺手让爆米花和 VidHub 也能一起用,事情就结束了。结果真动手之后才发现,这根本不是“修一个点”的问题,而是一边拽就会带出来一整串。

最后总算是修顺了:Web 能播,爆米花能播,VidHub 也通了,而且主入口继续保留在高位端口,不改成 443;真正的大流量也尽量还是走 302 到网盘,不让 VPS 自己苦哈哈地扛视频流。

这篇还是按博客来写,不当交接文档。公网 IP、域名、账号密码这些敏感东西我都不往里放,只记真正值得记的坑和解法。

一开始我以为只是 Emby 播不动

最初看上去特别像是 Emby 自己抽风:能刮削,能识别媒体,但一到播放就不对劲。可真往下拆之后,很快就发现事情没这么单纯。

真正的问题,至少是三层叠在一起的:

  • .strm 里有一批地址从一开始就写错了,指向的不是正确的 CMS 302 出口。
  • Emby 容器自己的代理环境也不干净,它去请求自己的链路时,反而被自己坑了。
  • 最烦的是第三方客户端根本不一定按服务端给的路径走,它们会自己改地址,最后把流量又绕回 Emby。

也就是说,这不是一个“播放器不行”的问题,而是一整条链路里,每一层都刚好有一点别扭,最后一起爆了。

第一刀,先砍 strm 和 Emby 自己

我最先下手的是 .strm。因为这个东西一旦源头写错,后面再怎么修都像在补漏水的屋顶,根本补不干净。

之前一批 .strm 写的是某个直接暴露出来的 CMS 端口,但那个口子并不是最终应该给客户端走的外部 302 出口。这样一来,Emby 虽然表面上能识别媒体,真到播放时还是会在后面翻车。

所以这一层我做得很直接:

  • 把 CMS 里和 302 相关的外部域名配置修回统一入口。
  • 批量把错误的 .strm 地址全部替换掉。
  • 在反代层把 /d//s/ 这些 CMS 302 路由都补齐。

但很快又发现,光修 .strm 还不够。Emby 容器里原本带着一套代理环境变量,它一边请求自己的反代入口,一边又会在后续跟随到网盘 CDN 时被错误带去走代理。这个坑非常阴,表面现象就是 stream.strm 500、Range 超时、日志里一堆看起来云里雾里的失败。

我后面把 Emby 的环境重新理了一遍,该放进 NO_PROXY 的域名和目标全补进去,再按新配置重建容器。到这一步之后,链路终于像样了:

  • HEAD /stream.strm 能回 200
  • Range 的请求能稳定回 206
  • Web 播放恢复正常。

这时候我心里才算有点底:至少 Emby 自己这层已经不是问题核心了。

第二刀,补一补第三方客户端那些奇奇怪怪的小脾气

Web 修好之后,爆米花和 VidHub 还是不老实。它们和浏览器访问 Emby 的方式完全不是一回事,尤其是探活和登录这一段,经常会走一些很“客户端”的路数。

比如有些接口,浏览器发 GET 没问题,某些客户端却先来个 HEAD。偏偏 Emby 某些版本在这些公共接口上,GETHEAD 的表现又不一致。结果就是:你明明服务还活着,但客户端那边看起来像服务器挂了。

这个问题说大不大,说烦是真烦。后来我干脆在 OpenResty 这一层给常见探活接口做兼容,让 GETHEAD 都能正常通过,至少别卡在“还没开始登录就先说你不在线”这种离谱环节上。

登录这里也有个坑。有些客户端去打 AuthenticateByName 的时候,自己没有带合规的 X-Emby-Authorization,于是即使用户名密码本身没错,Emby 还是会因为参数不完整直接翻脸。

这个在浏览器里你不太会碰上,但在第三方客户端里就是实打实会遇到。最后我的处理方式也很简单粗暴:客户端没带够,我就在反代层补一个兼容头再交给 Emby。至少先把登录这一步放过去,不要卡死在门口。

最难缠的,其实不是“连不上”,而是“连上以后开始中转”

真正让我头大的,不是客户端报错,而是它们有时候明明已经连上了,结果播放一拉起来,整条链路就开始往错误的方向跑。

理想状态当然是最舒服的:客户端拿到 CMS 给的 302 路径,然后自己一路跟到网盘,服务器只负责指路,不负责出力。

可现实是,第三方客户端有时候根本不按服务端给的路径来。PlaybackInfo 里明明已经有可以直接用的远程播放地址了,它们还是会自己手动拼成 /Videos/.../stream.xxx 这种地址再去找 Emby。

一旦它们这么干,事情就会变成:

  • 客户端去请求 Emby。
  • Emby 再去拉 CMS 的 /d/...
  • 最后视频流量开始走 VPS 中转。

这时候最直观的感受就是速度掉得离谱,轻量服务器的带宽和流量也会一起遭殃。最烦的是,这种坏链路有时候表面上还“不是完全不能播”,只是慢得像在受刑。

后来我干了两件很关键的事:

  • 先把 PlaybackInfo 改写掉,返回给客户端的是一条我可控的播放路径,并把原始的 orig_d 保留下来。
  • 再对 /Videos/.../stream.xxx 做一层反代侧兜底。客户端就算非要自己拼这个地址,我也在反代层把它重新引回 CMS 的原始 302 路径上。

这一刀下去之后,链路终于不再那么容易跑偏。判断它到底有没有回正,其实看日志最清楚:

  • 如果是好链路,反代层会对 /Videos/... 返回 302,CMS 再对 /d/... 返回 302,Emby 只做元数据和播放进度。
  • 如果是坏链路,Emby 日志里就会出现它自己去拉远端媒体、自己去请求 /d/... 的记录。那说明它又被迫下场当搬运工了。

VidHub 最后卡住的地方,居然是“地址得像同一个人说的话”

后面还有一个让我印象很深的坑:同一个服务,如果客户端最开始是从 IP + HTTP + 28080 这个入口进来的,服务端后面却突然返回成“域名 + HTTPS + 同端口”这一套,有些客户端真的会当场别扭起来。

爆米花对这种混用还稍微宽容一点,VidHub 就明显敏感得多。一旦入口前后说法不一致,它就会出现那种特别烦的状态:

  • 看起来像是已经连上了。
  • 登录也不一定报错。
  • 但播放就是不对,或者行为非常不稳定。

最后我才真正确认,VidHub 这边最关键的修法,根本不是继续换账号密码,也不是继续折腾 Emby 本体,而是把整个链路对外表现出来的地址形态统一掉。

说白了就是:客户端如果是从 IP + HTTP + 28080 进来的,那后面的 System/Info/PublicPlaybackInfo/Videos/...orig_d/d/...,也尽量都保持这一套说法。不要前脚让人从一个口进来,后脚又拿另一张脸跟它说话。

这一步听起来不像什么“大技术点”,但对客户端兼容来说,真的非常要命。尤其 VidHub 这种比较挑的,地址前后是不是一个逻辑,比我一开始想象的重要得多。

折腾到最后,终于像个能长期跑的样子了

这一轮全部收完之后,结果总算是顺眼了:

  • Web 正常播。
  • 爆米花正常播。
  • VidHub 也正常连、正常播。
  • 主入口继续保留高位端口,不动 443 这条主思路。
  • 大部分视频流量尽量走 302 到网盘,不让 VPS 长时间中转。

如果让我现在回头用一句话总结这次排障,那大概就是:

这条链路真正被修顺,不是因为我把某一个服务修好了,而是因为我终于把 strm、CMS、Emby、反代和客户端这些互相牵扯的地方,慢慢拽成了一条线。

顺手记几句,给以后再踩坑的自己看

  • .strm 能刮削,不代表播放链路就是对的。
  • 容器里的代理环境变量,真的很容易误伤它自己。
  • 第三方客户端不一定会按服务端给的最佳路径走,很多时候必须在反代层兜底。
  • 像 VidHub 这种客户端,地址形态前后一致,和“能不能播”几乎是同等级的重要性。
  • 如果目标是省 VPS 流量,就一定要盯日志,确认最后跑的是 302 -> 网盘,而不是 Emby 自己去拉文件。

这篇先记到这里。后面如果我把这套链路继续补成更省心的版本,比如自动巡检、播放异常提醒,或者整理出一份更适合复用的模板,我再接着写下一篇。

文末附加内容
No Comments

Send Comment Edit Comment


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
Previous