Cane's Blog

Cane

【Nas】告别 alist,三步实现 emby 115 直链播放

Nas
13718
2024-06-25

前言

之前出过两篇在云服务器上采用 cd2/rclone + alist +nginx + emby 实现 115 直链播放的方案。

【Nas】115 + alist + cd2 实现 emby 直链播放 & 加速扫库版

【Nas】115 + alist + rclone 实现 emby 直链播放

很多读者反馈,步骤太多,跟着教程一套下来有些吃力。尤其是很多朋友没有自己的服务器,选择部署在家里的 Nas 上,但是由于不知道如何同步修改路径和对应配置,导致直链方案失败。

鉴于此,整理汇总了当前各种方案,最终选择在 T3rry 大佬的 sjtuross/emby115:latest 镜像的基础上,做二次封装,特成此篇。

再次致谢 T3rry 佬,动手能力强的朋友也可以直接选择 T3rry 佬的原版镜像,实现更加灵活的客制化配置,镜像地址: https://hub.docker.com/r/sjtuross/emby115

下面这篇博文,可能是你目前能找到的全网最简洁版本部署方案,适用于各种 Nas / 云服务器。

流程图 & 原理介绍

之前的原理介绍,讲的是各方案的原理和流程。这次我想跳脱具体方案,从更底层的部分来讲解一下,使你对「直链播放」有个更加细致全面的了解,同时也让你对「网盘&媒体库」的发展史有个粗略的了解。(对技术原理不感兴趣的,可以跳过这一部分,不影响最终搭建)

读完这个部分大概可以解答你以下几个疑问

  1. 为什么 115 / XX 网盘可以实现直链播放,为什么 XX 网盘不可以?

  2. Alist 是不是必须的,Nginx 和 CD2 呢?

  3. 搭建步骤还有哪些优化方向?极限优化的情况下,终极方案大概会是个什么样?

  4. 扫库慢的原因是什么,有哪些加速方案?

  5. Emby / Plex / Jellyfin 都可以支持直链播放吗?

  6. 为什么不推荐直链播放情况下的转码,技术层面上有可能实现完美的直链转码吗?

  7. 直链播放方案是没有瑕疵的吗,存在哪些潜在风险?

AList / CD2 / Rclone 原理

首先,从访问控制的角度而言,所有的网络资源大概分为两类,一类是公开资源: 可以被任何用户无需认证的访问,比如各种公共的图库、各种公开的下载站等。另一类属于受限资源,这类资源需要用户登录/鉴权通过后才可以访问和查看。很明显,当前流行的各种网盘上,从访问控制的角度而言属于后者。

一般来说,只有通过官方允许的渠道(比如浏览器/官方客户端),经过安全认证才可以正常访问网盘里的各种资源。同时我们也只能在官方允许的范围内,对资源进行操作,无法直接将网盘里的资源提供给其他服务使用。从程序的角度而言,浏览器/官方客户端访问资源的本质无非是各种网络请求,如果我们能用第三方客户端/代码/程序,模拟这些请求,就可以达到使用第三方客户端/代码/程序访问网盘资源的目的。

而在第三方客户端/代码/程序的基础上,我们可以很方便的扩展和开发各种接口给其他服务使用,这是所有其他服务能够把网盘当作 "本地磁盘/网络空间" 使用的基础。

AList / Rclone / CD2 本质上就是这个第三方客户端,只不过各家支持的网盘数量,对外开方的接口/协议各有不同。比如 Rclone 和 CD2 支持将挂载的网盘资源文件本地化,而 Alist 则支持将网盘资源转换为可以通过 HTTP 请求访问的各种接口。

正常情况下,你通过第三方客户端/代码/程序访问网盘资源文件,第三方客户端/代码/程序做的,是把网盘资源文件下载到本地,再传给你。如果你是外网访问,会同时吃到家庭网络的上传&下载。

Alist 302 方案,则是检测到你请求网盘资源文件后,直接重定向到你网盘资源文件的原始真实链接(这个链接不需要鉴权)。由于你直接访问的是网盘资源的真实链接,Alist 只是做了个重定向功能,本身并没有参与资源的传输过程,所以不会消耗你 alist 所在家庭网络的流量,速度只取决于你外网访问时的网络下载速度(当然也要考虑网盘厂家支持的速度上限)。

alist 302.png

媒体服务器入库&播放&转码原理

挂载在媒体服务器上的媒体库,媒体服务器会首先根据文件名去内部支持的数据库里查询该电影(如 tmdb, tvdb 等)获取基础信息,如标题、演员、简介等,然后会读取一部分媒体文件,以获得诸如媒体分辨率、码率等信息。

在播放的时候,用户访问媒体服务客户端,媒体服务根据用户不同的 HTTP 请求,返回不同的资源。对用户来说,媒体服务器返回的资源,走的是家庭网络的上传。

媒体服务器.png

如果用户选择转码,媒体服务器会对读取到的文件,使用内置的程序进行转码,然后将转码后的字节流发送给用户。

正因为此,所以「直链播放」和「转码」是天然矛盾的存在。因为「转码的数据」由媒体服务器提供,「直链播放的数据」由用户通过真实链接访问的网盘直接提供,二者是矛盾的。

不同的媒体服务器的本质区别是处理请求/响应的样式不同和与本地文件交互方式不同

本质上,各种类型的媒体服务器(Emby / Jellyfin / Plex)只有解析/响应请求的格式和媒体服务器与本地文件交互方式上的不同,不涉及转码和对文件字节流二次加工处理的情况下,各种媒体服务器理论上可以通过劫持请求、Hook响应的方式实现直链播放的。

扫库慢的主要原因在于解析媒体文件

一般而言,影响入库速度快慢的,是解析视频文件获取视频码率、分辨率等信息的部分(解析一般是使用开源的 FFmpeg 插件)。因为刮削是根据文件名进行的,无论是本地文件还是网盘挂载文件,刮削这部分花费的时间,相对来说都是比较一致的。而当媒体库文件是网盘文件挂载的时候,解析视频文件就涉及到从网盘下载数据,从而导致入库比较慢。

加速扫库优化方向

  1. 首先排除刮削网络的问题,比如所在网络无法访问 TMDB 等信息网站

  2. 支持读取本地 NFO 文件的媒体服务,如果有已刮削好的数据,也是可以小幅度提升刮取速度的

  3. 网盘挂载的,使用软链接,加速解析视频文件获取信息的部分

  4. 支持 STRM 的,使用 STRM 跳过解析视频文件获取相关信息的部分(缺点是不播放的情况下无法显示音轨/帧率/分辩率等信息,播放过一次就好了)

直链播放原理

综上所述,为了能使媒体服务器加载到网盘里面的资源,一个标准搭建方案下的网络请求链路如下。

媒体服务器_网盘.png

这样就实现了媒体服务器播放网盘资源的需求,只需要一个 CD2 / Rclone + 一个受支持的网盘就可以实现。缺点是外网用户访问需要吃到 "家庭网络" 的上传下载(这里的 "家庭网络" 是指搭建这套方案所在的网络环境)。

早期的各种 Emby 公益 / 收费服,就是采用的这种方案,使用谷歌云盘 + 大流量服务器,通过尽可能提高 "家庭网络" 的速度来规避多用户访问下的卡顿问题。

上文可知,既然

  1. CD2 / Rclone 可以实现网盘文件的本地化,从而让媒体服务器可以加载和刮削网盘文件

  2. Alist 可以实现 302 转发,使得通过 Alist 接口访问文件等于通过真实链接直接访问网盘文件

那么将二者结合起来,是不是就可以实现,即让媒体服务器可以加载和刮削网盘文件,又可以让播放的时候用户通过真实链接直连网盘,从而不消耗 "家庭网络" 的流量?

是的,这就是搭建「直链播放媒体服务器」的技术原理,需要用到的工具有 3 个

  1. 一个能让网盘文件本地化的第三方客户端,实现媒体服务器能够挂载和刮削网盘文件

  2. 一个能获取网盘真实链接地址的第三方客户端,实现用户直链播放

  3. 一个能动态检测和修改网络请求/响应的服务,使用户访问媒体服务器「网盘资源」的请求,能够重定向到 「2」获得的网盘真实链接

目前主流的方案是采用 CD2 | Rclone / Alist / Nginx 来充当以上各步骤中的工具,从而实现直链播放,之前写的 教程1教程2,也是如此。

直链播放方案.png

之前的方案,因为 CD2 | Rclone / Alist / Nginx 是三个独立的服务, 互相之间还有路径、授权、内部访问的问题,部署起来不是很友好。现在优化后的方案是将 Alist 换成 Python 版本的第三方客户端,同时 Nginx 只有当 realplay 的时候才将请求转发给媒体服务器,其他请求统一转发给 Python 版本第三方客户端进行判断处理。

这套优化方案简化了部署难度,但本质上还是需要三个组件,追求部署难度的进一步优化的话,可以考虑 Nginx 和 负责获取直链的第三方客户端(Alist 的位置)合二为一,这是方案下一步的优化方向。

优化步骤一.png

更进一步,这个第三方客户端还可以同时负责网盘的本地化挂载,不过这个实现起来就没那么简单了。工程角度而言,可以通过生成 STRM 文件代替网盘文件的本地化挂载来降低一定的工程难度。不过 STRM 目前只有 Emby 支持,而且 STRM 取代网盘文件的本地化挂载本身也会引入一些新的问题。不考虑工程难度的话,最终方案大概是下面这个样子,只需要 一个第三方客户端 + 媒体服务器就可以。

优化步骤二.png

以上优化方向,只是从降低部署难度的角度出发,本质上并没有播放体验上的升级。同时过多的耦合会降低程序的鲁棒性和适用范围,有没有必要为了降低部署难度而花费时间做这些 Mundane Work 是一个值得思考的问题。

直链播放潜在风险

  1. 不是所有网盘都支持 302 转发的。归根结底,「直链」是网盘可以比较方便的通过第三方客户端(模拟请求)获取到不需授权或鉴权比较松散的网盘文件真实链接实现的。网盘作为防守方,可以很简单的通过升级/更改策略来屏蔽和限制这一行为。

  2. 通过直链访问,网盘收到的所有请求来自访问用户的 IP地址,而不是第三方客户端所在的 "家庭网络" 的 IP 地址。当有多个用户同时访问,网盘方是可以看到同一时间来自不同 IP 地址的多路请求。限制单位时间流量总出口或者限制同一时间允许访问的 IP 数量,网盘方可以以非常低的成本来显著的影响直链播放的用户体验。

  3. 网盘方作为服务提供商,最终解释权始终在他们手里。如果判定「多用户同时间直链播放」为服务滥用,对相关网盘帐号进行封号处理,似乎消费者也没什么办法,这是悬在所有搭建「直链播放媒体服务器」用户头上的达摩克利斯之剑。不过截止 2024年6月,笔者并没有听到任何因为直链播放导致封号消息。

  4. 随着净网行动的进行,网盘是不是一个存资源的好去处,本身也是一个见仁见智的问题。

安装

以下安装步骤均在 群辉 DSM 7.2.1 版本经过验证,如果你在其他系统/版本遇到部署问题,欢迎留言。

安装 CloudDrive2

CD2 版本无所谓,套件版 / Docker 版都可以,这里我选择安装的是套件版。

安装完成后点击添加网盘,选择 115 网盘。

添加115网盘.png

双击网盘,进入网盘根目录,点击挂载,选择要挂载的盘符位置,我这里选择挂载到盘1的 CloudNas 目录,权限建议改成 777。

115挂载.png

如果一切正常的话,点击右侧的挂载按钮,可以看到已经挂载成功,同时会显示挂载路径。

挂载成功.png

这里可以看到,我们已经成功的将网盘根目录挂载到了本机的 /volume1/CloudNAS/115 目录。

不确定自己有没有操作正确的读者,可以访问 /volume1/CloudNAS/115 目录,看看是不是对应着网盘根目录

一键安装 emby, emby_nginx, emby_115

在 Nas 中,找一个空白文件夹,将下面两段代码,分别保存为 compose.yaml / 115.env 上传到该文件夹内

# 将该代码保存为 compose.yaml
version: "3.5"
services:
  emby_server:
    image: "emby/embyserver:latest"  # 这里改可以成第三方 embyServer 镜像
    container_name: "emby_server"
    restart: always
    ports:
      - "8096:8096"
    volumes:
      - "/volume1/docker/emby:/config"  # 这里是 EmbyServer 文件的保存地址,这样每次重新构建 EmbyServer 可以保证配置不丢失
      - "/volume1/CloudNAS/115:/media"  # /volume1/CloudNAS/115 用你上一步 CD2 中选择的地址替代
    environment:
      - "TZ=Asia/Shanghai"

  emby_115:
    image: "hicane/emby_115:latest"
    container_name: "emby_115"
    restart: always
    environment:
      - "TZ=Asia/Shanghai"
    depends_on:
      - emby_server
    env_file: ./115.env

  emby_nginx:
    image: "hicane/emby_nginx:latest"
    container_name: "emby_nginx"
    restart: always
    ports:
      - "8097:80"
    environment:
      - "TZ=Asia/Shanghai"
    depends_on:
      - emby_115
# 将该代码保存为 115.env
# 本机地址
PUBLIC_HOST=http://xxxx:8097

# EMBY API KEY
EMBY_API_KEY=xxx

# 115 Cookie
COOKIE=xxxx

# 挂载路径
MOUNT_PATH={"/media": ""}

上传文件.png

在 Docker 管理器里面,新增项目

新增项目.png

点击构建项目

项目初始化.png

构建完成待所有容器启动后,访问 本机地址:8096, 对 embySever 进行初始化,并新建 API KEY,我的 Nas 地址为 192.168.3.5,所以我这里访问的是:http://192.168.3.5:8096

复制key.png

修改配置重启服务

打开 115.env , 按需修改配置,需要注意的是

  1. 挂载路径,前面是挂载到 embyServer 的内部路径,我这里是 /media, 后面是 115网盘中的对应路径,我这里 cd2 中挂载的是115根目录,留空就好

  2. 115 Cookie 尽量选择保活期较长的 Cookie,优先推荐微信小程序中的 Cookie, 注意你的 Cookie 应有 UID/CID/SEID 三项,中间以 ; 分割符分开,不能有换行。

# 本机地址
PUBLIC_HOST=http://192.168.3.5:8097

# EMBY API KEY
EMBY_API_KEY=1fecxxxxxxx

# 115 Cookie
COOKIE=UID=xxxxx;CID=xxxxx;SEID=xxxxx

# 挂载路径
MOUNT_PATH={"/media": ""}

配置修改完成后,对着项目右键点击停止,然后点击构建,最后访问 192.168.3.5:8097,添加 /media 路径下的媒体库,即可实现直链播放!

注意: 一定要先点击停止,再点击构建才可以!重新启动不可以!

重构项目.png

效果展示

不要使用 网页访问 xx.xx.xx.xx:8097 的方式测试

使用官方或第三方客户端(比如 iOS fileball / windows emby Theater 等),通过连接至 192.168.3.5:8097,输入帐号密码来测试

具体是否走直链,可以通过观察Nas系统的网络流量来进行确认

播放效果展示.png

致谢

由于个人的技术水平及能力所限,文章难免存在不足或疏漏之处,还望各位读者海涵、斧正。

如果您觉得这篇文章对您有帮助,可以选择对我进行打赏,这将有助于我更快更好的产出文章,谢谢。

微信赞赏码.png