流程 & 原理介绍


2024/10/11/115-alist-cd2-emby-direct-chainplay-01.png

此方案需使用到四个容器,Emby、CloudDriver2、Alist、Nginx。

  1. Emby 读取、刮削、入库 「2」 挂载好的资源
  2. 通过 CloudDriver2 挂载 webdav 协议的资源(115网盘)挂载到本地硬盘,使用起来比 Alist 的 webdav + rclone 挂载方便。
  3. 通过 Alist 将 115 网盘资源转成可以通过网络编辑和管理 webdav 协议。
  4. 安装 Nginx 实现对访问 Emby 的请求地址,并从 Alist 获取 115 直链转发给客户端。将: 静态资源转发到 Emby 服务上,视频资源的访问直接转发到 Alist,从而利用 Alist 的 302 转发实现直接访问网盘资源。

302 是什么

GPT 如是说:

HTTP 302 是 HTTP 协议中的一种状态码(Status Code),全称是 HTTP 302 Found,表示请求的资源临时移动到了一个新的 URL,即临时重定向。

当浏览器或其他客户端向服务器发送请求时,如果服务器返回一个 302 状态码,它会同时在响应头中提供一个 Location 字段,告知客户端资源现在可以在新的 URL 找到。客户端随后应该使用这个新的 URL 来重新发起请求。

这种重定向通常是临时的,意味着资源只是暂时可以在新的地址找到,未来还可能会返回到原来的地址。

在此教程中,利用 Alist 的获取 115 网盘直链的功能,也就是302跳转直链,来实现 Emby 播放时直连网盘地址,不走 Emby 所在网络上下行,减少了一次中转,达到外网高带宽看片的需求。

目前已测试以下客户端播放可以实现 302 跳转

  • Emby 客户端
  • Infuse
  • Fileball
  • Vidhub
  • Yamby

欢迎补充…

准备条件:


阅读此篇教程,默认你已经学会

  • Docker/Docker-Compose 的相关配置使用
  • 上述相关软件的基础配置使用

容器配置


Emby

version: '3'                            # 指定版本

services: # 定义服务的部分
  embyserver: # 服务的名称
    image: 'amilys/embyserver:latest'            # 使用的镜像
    container_name: embyserver        # 容器名称
    restart: unless-stopped             # 重启策略
    network_mode: bridge                # 网络配置
    user: '0:0'                         # 以 root 用户身份运行
    privileged: true                    # 特权模式
    deploy: # 部署配置
      resources: # 资源限制
        limits:
          cpus: '2'                     # CPU 限制(1 表示 100% 的一个 CPU,2 表示 200% 的一个 CPU)
          memory: 2048M                 # 内存限制
    ports:
      - '8096:8096'                     # 端口映射
    volumes:
      - ./emby:/config
      - /Movies:/movies:rslave

据群友实测,Emby 需要 4.8 及以上版本,低于 4.8 版本有可能不成功。

emby 配置两个路径,一个是 /config,映射到你喜欢的路径即可。一个是 /movies,映射到宿主机的 /Movies,这个路径可以自己自定义,所有的影视文件都会在此路径内,没有什么特殊的,记住这个 /movies,一会要考。

CD2

version: "3"                            # 指定版本

services: # 定义服务的部分
  cloudnas: # 服务的名称
    image: cloudnas/clouddrive2         # 使用的镜像
    container_name: clouddrive2         # 容器名称
    restart: unless-stopped             # 重启策略
    network_mode: bridge                # 网络配置 bridge / host / none / container / user-defined bridge
    user: 0:0                           # 以 root 用户身份运行
    privileged: true                    # 特权模式
    pid: "host"
    deploy: # 部署配置
      resources: # 资源限制
        limits:
          cpus: "1"                     # CPU 限制(1 表示 100% 的一个 CPU,2 表示 200% 的一个 CPU)
          memory: 1024M                 # 内存限制
    environment:
      - TZ=Asia/Shanghai
      - CLOUDDRIVE_HOME=/Config
    devices:
      - /dev/fuse:/dev/fuse
    ports:
      - "19797:19798"                   # 端口映射
    volumes:
      - /Movies:/CloudNAS:shared
      - ./cd2:/Config

cd2 映射两个路径,/CloudNAS 为挂载路径,用于将云盘文件挂载到本地,同样映射到宿主机的 /Movies 路径下,这个宿主机路径与 Emby 的必须一致,自行决定。

Alist

version: '3'                            # 指定版本

services: # 定义服务的部分
  alist: # 服务的名称
    image: xhofe/alist:latest           # 使用的镜像
    container_name: alist        # 容器名称
    restart: unless-stopped             # 重启策略
    network_mode: bridge                # 网络配置 bridge / host / none / container / user-defined bridge
    user: '0:0'                         # 以 root 用户身份运行
    privileged: true                    # 特权模式
    deploy: # 部署配置
      resources: # 资源限制
        limits:
          cpus: '1'                     # CPU 限制(1 表示 100% 的一个 CPU,2 表示 200% 的一个 CPU)
          memory: 1024M                 # 内存限制
    environment:
      - PUID=0
      - PGID=0
      - UMASK=022
    ports:
      - '5244:5244'                       # 端口映射
    volumes:
      - ./alist:/opt/alist/data

Alist 只需要映射配置文件的路径即可。

Nginx

version: '3'                            # 指定版本

services: # 定义服务的部分
  nginx: # 服务的名称
    image: nginx:latest                 # 使用的镜像
    container_name: nginx               # 容器名称
    restart: unless-stopped             # 重启策略
    network_mode: host                  # 网络配置
    user: '0:0'                         # 以 root 用户身份运行
    privileged: true                    # 特权模式
    deploy: # 部署配置
      resources: # 资源限制
        limits:
          cpus: '1'                     # CPU 限制(1 表示 100% 的一个 CPU,2 表示 200% 的一个 CPU)
          memory: 1024M                 # 内存限制
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d # 需要手动上传
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf # 需要手动上传
      - ./nginx/embyCache:/var/cache/nginx/emby
      - ./nginx/logs:/var/log/nginx

nginx 配置需要完全自定义,使用官方镜像即可,需要注意的是,容器的网络模式必须使用 host。相关配置文件后文提供,nginx 容器先不启动

详细配置


CD2

启动 CD2 容器后,添加自己的 115 账号。使用 CD2 的本地挂载功能,选择 115根目录(要挂载哪个目录,就进入到哪个目录的根层级就行),点击 挂载到本地名称 填写 115,挂载点选择 /CloudNAS,保存即可挂载到 /CloudNAS 路径下,也就是宿主机的 /Movies 路径。

2024/10/11/115-alist-cd2-emby-direct-chainplay-02.png

2024/10/11/115-alist-cd2-emby-direct-chainplay-03.png

2024/10/11/115-alist-cd2-emby-direct-chainplay-04.png

选择挂载路径(这里十分关键跟后面的 constant.js 中的路径直接相关,如果不一致会导致直链播放失败,建议按照我的配置来

2024/10/11/115-alist-cd2-emby-direct-chainplay-05.png

选择好 alist 文件夹,点击确定后,会显示如下路径

2024/10/11/115-alist-cd2-emby-direct-chainplay-06.png

点击挂载后,查看挂载是否成功,若「失败原因」处显示空白,则证明一切正常。

2024/10/11/115-alist-cd2-emby-direct-chainplay-07.png

此时,在宿主机查看 /Movies 目录,就可以查看到115上的文件了。

Alist

启动 Alist 容器后,设置密码

./alist admin set NEW_PASSWORD

访问 http://nasip:5244,登录管理后台,添加 115 网盘,按需配置,对配置项不太理解的朋友建议直接抄我的

2024/10/11/115-alist-cd2-emby-direct-chainplay-08.png

记录下 alist token 值,示例:alist-56aed914-dc75-4exxxxx

2024/10/11/115-alist-cd2-emby-direct-chainplay-09.png

挂载 115 云盘提示如下信息,是因为 115已经下架了 Windows、Mac、Linux 这三个客户端的应用

{
"state": 0,
"error": "登录失败,系统已下架!如果你有电脑端的使用需求,我们诚挚邀请你下载体验115产品专属客户端“115浏览器”或在线使用“115网页端(115.com)”,畅享智能高效云生活。",
"errno": 0,
"message": "登录失败,系统已下架!如果你有电脑端的使用需求,我们诚挚邀请你下载体验115产品专属客户端“115浏览器”或在线使用“115网页端(115.com)”,畅享智能高效云生活。",
"code": 0
}

请通过二维码令牌进行登录 QRCode 扫码方式登录

如果你的 CD2 是挂载的根目录的话,最下方的 根文件夹ID 为 0 不要修改,反之请自行修改,务必保持一致。

Emby

配置完以上挂载后,需要重启一次 Emby 容器,如果你的 Emby 已经提前启动了的话。

重启完成后,在 Emby 中添加你的媒体库,此时可以看到,Emby 的 /movie 目录下有你的 115 的影视文件了。如果你的文件部包含 nfo 文件的话,建议不要开启 ⬇️ ⬇️ ⬇️ 此开关,防止小文件上传过多被风控。以及关闭 将媒体图片保存到文件夹中 开关。

2024/10/11/115-alist-cd2-emby-direct-chainplay-10.png

Nginx

操作到这里,你需要明确一下 Emby 和 Alist 的对应文件路径。

两边对比一下同一个视频文件,可以看到,Emby 中的路径应为 /movies/alist/115/影视/动漫/动画电影/铃芽之旅 (2022)/铃芽之旅 (2022) - 1080p H.264.mkv,Alist中的同一个文件路径为 /115/影视/动漫/动画电影/铃芽之旅 (2022)/铃芽之旅 (2022) - 1080p H.264.mkv

具体的网盘内路径以自己为准,但如果完全照抄以上配置的话,路径的开头 /movies/alist/115 肯定是和我一致的。

此时 Alist 内的路径为 Emby 的路径的子集,即多出一个 /movie/alist 开头。

接下来,下载此压缩包,解压后得到一个 nginx 文件夹,其中有 conf.d 文件夹及 nginx.conf 文件,此为 nginx 相关配置文件。在此感谢 bpking1/embyExternalUrl 作者大大提供的配置及脚本。

需要自定义配置的有两个文件。

  • conf.d/constant.js

    • 2024/10/13/115-alist-cd2-emby-direct-chainplay-11.png
    • embyHost:Emby 的内网地址及端口
    • embyMountPath:填写上述的 /movies/alist ,即 Alist 路径为 Emby 的子集剩余的部分。注意填写到此列表变量的元素中,即 ["/movies/alist"]。如果你的 Emby 文件路径与 Alist 完全一致,即剩余部分为空,那么此处填写 []
    • embyApiKey: Emby 的 ApiKey,从 Emby 的 web 中获取。
    • alistAddr: Alist 的地址及端口。这里我使用的是 Alist 的外网地址,内网地址是否可用可自行探索。
    • alistToken: Alist 的 Token 令牌,在 Alist → 管理 → 设置 → 其他 → 令牌 获取,格式为 alist- 开头
  • conf.d/emby.conf

    • 2024/10/13/115-alist-cd2-emby-direct-chainplay-12.png
    • 第 26 行: listen 8091;
      • 此为 nginx 监听的端口,修改为你想要的端口即可,用于替代原 Emby 的 8096 端口访问。访问此端口才能实现 302 转发。

修改完配置之后,将 conf.dnginx.conf 映射到 nginx 容器,在上述的 nginx 的 docker-ccompose 配置中已添加,注意存放的宿主机路径。启动 nginx 容器。

测试


此时启动 Nginx 容器后,访问 8091 端口,或是你在 emby.conf 文件中修改的端口,可以访问到 Emby Web。即完成了第一步,nginx 代理 Emby Web 成功。

使用各类客户端,如 Emby 官方客户端、Infuse、Fileball、Vidhub 等登录 8091 端口,找一个刮削好的片子播放,或者 web 跳转第三方播放器 potplayer、iina 等,查看 CD2 的下载任务。如果没有大流量的对应文件下载,进程为 /system/EmbyServer ,即 302 转发成功。

目前 Emby Web 直接播放还无法实现302转发,也或许是我姿势不对。如果有成功使用 Emby Web 播放 302 直链的欢迎分享成果。

合并容器配置


使用 Docker Compose 可以方便地把多个有关联的容器进行合并配置,并且可以设置依赖的启动顺序,一键拉起所有容器。

version: '3'                            # 指定版本

services: # 定义服务的部分
  embyserver: # 服务的名称
    image: 'amilys/embyserver:latest'            # 使用的镜像
    container_name: embyserver        # 容器名称
    restart: unless-stopped             # 重启策略
    network_mode: bridge                # 网络配置
    user: '0:0'                         # 以 root 用户身份运行
    privileged: true                    # 特权模式
    deploy: # 部署配置
      resources: # 资源限制
        limits:
          cpus: '2'                     # CPU 限制(1 表示 100% 的一个 CPU,2 表示 200% 的一个 CPU)
          memory: 2048M                 # 内存限制
    depends_on:
      - cloudnas
      - alist
      - nginx
    ports:
      - '8096:8096'                     # 端口映射
    volumes:
      - ./emby:/config
      - /Movies:/movies:rslave

  cloudnas: # 服务的名称
    image: cloudnas/clouddrive2         # 使用的镜像
    container_name: clouddrive2         # 容器名称
    restart: unless-stopped             # 重启策略
    network_mode: bridge                # 网络配置
    user: 0:0                           # 以 root 用户身份运行
    privileged: true                    # 特权模式
    pid: "host"
    deploy: # 部署配置
      resources: # 资源限制
        limits:
          cpus: "1"                     # CPU 限制(1 表示 100% 的一个 CPU,2 表示 200% 的一个 CPU)
          memory: 1024M                 # 内存限制
    environment:
      - TZ=Asia/Shanghai
      - CLOUDDRIVE_HOME=/Config
    devices:
      - /dev/fuse:/dev/fuse
    ports:
      - "19797:19798"                   # 端口映射
    volumes:
      - /Movies:/CloudNAS:shared
      - ./cd2:/Config

  alist: # 服务的名称
    image: xhofe/alist:latest           # 使用的镜像
    container_name: alist        # 容器名称
    restart: unless-stopped             # 重启策略
    network_mode: bridge                # 网络配置
    user: '0:0'                         # 以 root 用户身份运行
    privileged: true                    # 特权模式
    deploy: # 部署配置
      resources: # 资源限制
        limits:
          cpus: '1'                     # CPU 限制(1 表示 100% 的一个 CPU,2 表示 200% 的一个 CPU)
          memory: 1024M                 # 内存限制
    environment:
      - PUID=0
      - PGID=0
      - UMASK=022
    ports:
      - '5244:5244'                       # 端口映射
    volumes:
      - ./alist:/opt/alist/data

  nginx: # 服务的名称
    image: nginx:latest                 # 使用的镜像
    container_name: nginx               # 容器名称
    restart: unless-stopped             # 重启策略
    network_mode: host                  # 网络配置
    user: '0:0'                         # 以 root 用户身份运行
    privileged: true                    # 特权模式
    deploy: # 部署配置
      resources: # 资源限制
        limits:
          cpus: '1'                     # CPU 限制(1 表示 100% 的一个 CPU,2 表示 200% 的一个 CPU)
          memory: 1024M                 # 内存限制
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d # 需要手动上传
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf # 需要手动上传
      - ./nginx/embyCache:/var/cache/nginx/emby
      - ./nginx/logs:/var/log/nginx

感谢