Files
StudyDiary/02-学习笔记/NAS(群晖+飞牛)MoviePilot_TMM TMDB刮削 终极稳定技术方案.md

7.9 KiB
Raw Permalink Blame History

NAS(群晖+飞牛)MoviePilot/TMM TMDB刮削 终极稳定技术方案

一、问题背景与核心故障根源

1.1 设备环境差异

  • 群晖NAS:Mihomo代理正常、Hysteria2节点正常、UDP链路通畅、全局代理生效,MoviePilot/TMM刮削全部正常。

  • 飞牛fnOS:无系统全局代理、OVS虚拟交换机拦截UDP、Hysteria2(QUIC/UDP)链路大面积失效,导致所有TMDB API请求超时/握手失败,媒体刮削完全不可用。

1.2 核心技术故障定论

本次故障不是节点、密钥、TLS版本、DNS污染问题,是环境硬限制:

  • TMDB CloudFront 强制仅支持 TLS1.3;

  • 传统TCP隧道(Vmess/Vless/AnyTLS/Mieru)存在内层TLS1.3报文损坏缺陷;

  • 唯一稳定的Hysteria2(QUIC/UDP)协议,被飞牛fnOS OVS/路由器UDP拦截;

  • 飞牛Docker容器不会自动继承宿主机代理,裸网访问TMDB必然失败。

结论:飞牛无法本地稳定运行HY2代理,放弃飞牛本地代理,采用「双方案冗余架构」解决刮削问题。

二、整体架构设计(双冗余方案)

主方案(长期日常使用):飞牛容器复用群晖Mihomo代理(全接口覆盖)

备方案(断代理兜底):Cloudflare Worker带鉴权+缓存TMDB中转(无需任何代理、纯裸网可用)

两套方案可随时切换,彻底解决飞牛TMDB刮削不稳定问题。

三、主方案:飞牛复用群晖Mihomo代理(推荐默认启用)

3.1 前置必备条件(必须配置)

群晖Mihomo config.yaml 核心配置(允许局域网访问):

mixed-port: 7890
allow-lan: true
listen-address: 0.0.0.0
ipv6: false

群晖防火墙放行 7890端口,飞牛与群晖处于同一局域网、无跨VLAN隔离。

3.2 MoviePilot 完整部署配置

飞牛docker-compose.yml,直接复用群晖SOCKS5代理,自动解决TMDB/Github/豆瓣全部外网请求。

version: "3.8"
services:
  moviepilot:
    image: jxxghp/moviepilot:latest
    container_name: moviepilot
    restart: unless-stopped
    ports:
      - "3000:3000"
    volumes:
      - /volume1/moviepilot:/app/config
    environment:
      - TZ=Asia/Shanghai
      # 核心代理配置:远端解析域名,规避DNS污染
      - PROXY_HOST=socks5h://192.168.1.100:7890
      # Github加速,解决插件/资源下载失败
      - GITHUB_PROXY=https://mirror.ghproxy.com/
    network_mode: bridge

⚠️ 替换:192.168.1.100 为你的群晖真实内网IP,目录按需修改。

3.3 MoviePilot 网页端配置

  • 无需修改TMDB接口地址,保持官方默认

  • PROXY_HOST已由环境变量注入,无需重复填写

  • 正常填写TMDB API Key即可

3.4 TinyMediaManager(TMM) 部署配置

version: "3.8"
services:
  tinymediamanager:
    image: tinymediamanager/tinymediamanager:latest
    container_name: tinymediamanager
    restart: unless-stopped
    ports:
      - "4000:4000"
    volumes:
      - /volume1/tmm:/config
    environment:
      - TZ=Asia/Shanghai
      - ALL_PROXY=socks5h://192.168.1.100:7890
      - NO_PROXY=127.0.0.1,localhost,192.168.0.0/16
    network_mode: bridge

3.5 TMM 网页端代理配置(优先推荐)

  • Proxy type: SOCKS5

  • Host: 群晖内网IP

  • Port: 7890

  • 开启:Resolve hostnames remotely(远端域名解析,等价socks5h)

3.6 连通性验证命令(飞牛SSH执行)

docker exec -it moviepilot curl -v --socks5-hostname 192.168.1.100:7890 https://api.themoviedb.org/3/movie/550?api_key=你的TMDB密钥

返回JSON即为代理通路正常。

四、备方案:CF Worker 鉴权+缓存 TMDB 中转(无代理兜底)

适用场景:群晖关机、代理节点故障、飞牛UDP彻底不通,零代理依赖完成TMDB刮削。

核心优势:TCP链路传输、不受UDP/OVS限制、带密码防盗刷、自带缓存提速、节省TMDB/CF额度。

4.1 主中转Worker代码(鉴权+缓存)

新建Worker,清空默认代码,粘贴如下完整版:

export default {
  async fetch(request, env) {
    // 自定义你的访问密钥
    const ACCESS_SECRET = "自定义随机密钥";
    // 缓存有效期1小时,可改为600(10分钟)/86400(24小时)
    const CACHE_TTL = 3600;

    const auth = request.headers.get("X-Tmdb-Secret");
    if (!auth || auth !== ACCESS_SECRET) {
      return new Response("Access Denied", { status: 403 });
    }

    const targetHost = "api.themoviedb.org";
    const url = new URL(request.url);
    url.hostname = targetHost;
    const newReq = new Request(url, request);
    newReq.headers.set("Host", targetHost);

    // GET请求缓存加速
    if (request.method === "GET") {
      const cacheKey = new Request(newReq.url, newReq);
      const cache = caches.default;
      let response = await cache.match(cacheKey);

      if (!response) {
        response = await fetch(newReq);
        response = new Response(response.body, response);
        response.headers.set("Cache-Control", `s-maxage=${CACHE_TTL}`);
        await cache.put(cacheKey, response.clone());
      }
      return response;
    }

    return await fetch(newReq);
  }
}

4.2 缓存清理方案(三种方式)

方式1:临时绕过缓存(单影片刷新,最简单)

链接后追加参数:&_nocache=随机数字

方式2:全局一键清缓存(批量重刷库)

修改任意一行Worker代码并重新部署,CF边缘节点缓存全部自动清空。

方式3:精准单条缓存删除(进阶)

单独部署purge清理Worker,支持指定路径删除缓存(文档末尾附代码)。

4.3 MoviePilot 切换Worker配置

  • 清空 PROXY_HOST(关闭代理)

  • TMDB API地址:https://你的worker域名.workers.dev/3

  • 自定义请求头新增:X-Tmdb-Secret: 你的自定义密钥

  • 保留原有TMDB Key

4.4 TMM 切换Worker配置

  • TMDB API URL 替换为Worker地址

  • Custom HTTP Headers 添加 X-Tmdb-Secret: 你的密钥

  • 关闭软件内代理设置

4.5 缓存清理Purge Worker代码(精准删除单条缓存)

export default {
  async fetch(request, env) {
    const ACCESS_SECRET = "和主Worker一致的密钥";
    const auth = request.headers.get("X-Tmdb-Secret");
    if (!auth || auth !== ACCESS_SECRET) {
      return new Response("Access Denied", { status: 403 });
    }

    const url = new URL(request.url);
    const targetPath = url.searchParams.get("path");
    if (!targetPath) {
      return new Response("Missing ?path=/3/movie/550", { status: 400 });
    }
    const cacheUrl = new URL(`https://你的主worker域名.workers.dev${targetPath}`);
    const cacheReq = new Request(cacheUrl);
    const cache = caches.default;
    await cache.delete(cacheReq);
    return new Response(`Purged: ${cacheUrl.toString()}`);
  }
}

五、两套方案取舍标准

方案 适用场景 优点 缺点
群晖代理复用(主) 日常长期使用、群晖开机 全覆盖(TMDB/Github/豆瓣)、无额度限制、速度稳定 依赖群晖在线
CF Worker中转(备) 群晖关机、代理故障、UDP拦截 零代理依赖、抗网络污染、自带缓存加速 仅覆盖TMDB、有每日免费额度

六、通用排坑清单(飞牛专属)

  1. 禁止使用127.0.0.1:容器内回环地址指向自身,必须填写群晖内网IP

  2. 必须开启allow-lan: true:群晖Mihomo禁止仅监听127.0.0.1

  3. 飞牛关闭IPv6:规避隧道TLS1.3握手异常

  4. 放弃飞牛本地HY2:fnOS OVS+路由器UDP拦截为硬故障,无法修复

  5. 优先软件内置代理:MoviePilot/TMM原生代理优于系统环境变量代理

七、最终落地规范

  • 日常默认:群晖Mihomo代理复用方案

  • 故障兜底:CF Worker鉴权缓存中转方案

  • 永久废弃:飞牛本地Hysteria2代理、TCP隧道(AnyTLS/Mieru/Vmess)

(注:部分内容可能由 AI 生成)