播放与外网访问 - MiCat-S/Mi302 GitHub Wiki

繁體中文 | 简体中文 | English

这一页说明播放器点播放后发生了什么、Mi302 识别哪些 strm、播放地址的登录和下载开关,以及怎样从外网访问。

播放一集或一部片时发生了什么

  1. 播放器先调用 PlaybackInfo。Mi302 返回一个媒体源:
    • 115 的 strm(并且已登录 115):Path 是 {播放器连进来的地址}/videos/{id}/stream.{格式}?Static=true,DirectStreamUrl 是 /videos/{id}/stream.{格式}?Static=true&MediaSourceId=…&api_key={token}。
    • 只允许直接播放(SupportsTranscoding 为 false)。Mi302 不转码,播放器要能自己播放这个格式。
    • 有媒体信息时附上分辨率、音轨、字幕轨;还没有并且“打开影片时自动探测”开着(默认开)时,在后台排队探测,见 媒体信息与探测。
  2. 播放器请求 /Videos/{id}/stream…。Mi302 读取 strm 的内容,应用路径替换,取出 pickcode(115 上每个文件的代码,17 位字母和数字),用播放器自己的 User-Agent 向 115 获取下载直链,然后返回 302 Location: <115 直链>。
  3. 播放器直接从 115 读取视频,视频流量不经过 Mi302。

Path 指回 Mi302 而不是 115,是因为有些播放器遇到 http 来源会直接播放 Path。指回 Mi302 才能保证请求经过 Mi302、带着播放器自己的 User-Agent。

媒体库里也可以放普通视频文件(不是 strm)。这种视频由 Mi302 直接发送文件,支持 Range(可以拖动进度),流量经过 Mi302。

115 直链和 User-Agent

115 的直链通常绑定获取时的 User-Agent,换一个 UA 去打开可能被 115 的 CDN 拒绝(403)。115 官方没有文档说明,这是多个 115 工具的共同做法和用户的反馈,见本节最后的参考。所以 Mi302 用播放器自己的 User-Agent 去获取,再把播放器 302 过去,自己不代为下载。就算某些直链其实没有绑定,这样做也一样能播。

  • 直链按(pickcode,User-Agent)缓存,直到直链里的过期时间前 5 分钟;看不出过期时间时缓存 10 分钟。
  • 同一个文件、同一个 User-Agent 同时来多个请求,只向 115 获取一次。
  • 授权了 115 开放平台时先用开放平台获取,失败再用扫码登录,见 115 网盘与同步。
  • 115 获取直链失败时:strm 指回 Mi302 自己(地址的主机和播放器连进来的地址相同,或 strm 里不是网址)就直接返回 502 和原因;指向别的主机时,改为 302 到 strm 里原本的地址。

参考:115-helper(为了避免 403 自动修正 Aria2 的 UA)、nodekit #761(UA 不同时播放失败)、OpenList 的 115 驱动(用客户端的 UA 获取直链)。也有相反的说法:115driver #98 说用 115 客户端 UA 获取的分享文件链接不绑定 UA。

Mi302 识别的 strm

Mi302 读取 strm 里第一行不是空白、也不是 # 开头的内容。

strm 内容 通常来自 Mi302 怎么处理
http://主机:8096/d/{pickcode}.mkv(后面可以带 ?/原文件名) Mi302 同步生成 向 115 获取直链
…/d/{pickcode} 其他工具,例如 115-station 向 115 获取直链
…?pickcode={pickcode} 或 …?pick_code={pickcode} P115StrmHelper 等 向 115 获取直链
115://{pickcode} 向 115 获取直链
其他 http://、https:// 地址 alist 等 302 到这个地址
本地路径,例如 /mnt/media/a.mkv Mi302 直接发送文件
  • 识别出 pickcode、又已登录 115 时,地址的主机是谁都没关系。其他工具生成的 strm 不必重新生成。
  • Mi302 也响应其他工具的 strm 会指向的地址:/d/{pickcode}、/p115/redirect?pickcode=…、/api/v1/plugin/p115strmhelper/redirect_url?pickcode=…。把那些 strm 的主机换成 Mi302 也能播放。这几个地址不检查登录。
  • 视频格式看地址的扩展名,没有就看 file_name= 参数,都没有就用“看不出格式时预设的影片格式”(默认 mkv)。

播放地址要求登录

“设定”标签页的“播放”卡片里有“播放网址要求登入”(redirect.require_auth,默认开)。

开着时,/Videos/{id}/… 要带有效的 token 才会返回 302,和官方 Emby 一样(Emby 4.7 起不分内外网都拦截未登录的串流请求)。token 可以放在:

  • 查询参数 api_key(也识别 ApiKey、X-Emby-Token)。PlaybackInfo 返回的 DirectStreamUrl 已经带上了。
  • 请求头 X-Emby-Token、X-MediaBrowser-Token,或 X-Emby-Authorization 里的 Token="…"。

Emby 系列和 Kodi 把 token 放在查询参数,Infuse 放在 X-Emby-Authorization 请求头,两种都支持。

关掉时,知道项目编号的人不用登录就能拿到 115 直链。只有某个播放器因此播放不了时才关:先在“日志”标签页打开“详细模式”,看播放时 /Videos/… 是不是返回 401,见 日志与常见问题。

PlaybackInfo 和下载不受这个开关影响,一律需要登录。

下载

“设定”标签页的“播放”卡片里有“允许播放器下载影片”(server.allow_download,默认开)。

  • 下载地址 /Items/{id}/Download、/Items/{id}/File 一律需要登录。strm 项目的下载同样是 302 到 115,播放器直接从 115 下载。
  • 关掉后,项目的 CanDownload 和用户的 EnableContentDownloading 都返回 false,播放器不显示下载;直接访问下载地址返回 403“下载功能已关闭”。
  • 这个开关只管下载地址,播放用的地址照常可用。

其他工具生成的 strm

strm 内容不是 Mi302 生成的(例如 alist 地址或本地路径)时,才需要“设定”标签页“其他 strm”里“其他工具产生的 strm”卡片的设置。改完点页面最下方的“储存设定”。

路径替换(redirect.path_rules):一行一条,格式是 原本开头 => 替换成,在做任何处理之前先改写 strm 的内容。

  • 本地路径:比对路径开头,以整段路径为单位,/mnt/115 能匹配 /mnt/115/…,不能匹配 /mnt/1150。
  • 原本开头 是 / 时,所有路径都会套用:/ => /mnt/nas 把 /a/b.mkv 改成 /mnt/nas/a/b.mkv。
  • 原本开头 是完整地址(带 http://)时,拿整个地址比对开头,可以用来换主机。
  • 原本开头 是路径时,也会拿来比对地址的路径部分;匹配上时整个地址换成“替换成”加上剩下的路径(查询参数保留),所以这时“替换成”要写完整地址。
  • 地址先比对完整地址的规则,再比对路径的规则;同一种规则从上往下,第一条匹配上的就用。
/mnt/115 => http://alist:5244/d/115
http://192.168.1.5:3000 => http://192.168.1.8:3000

第一条把 /mnt/115/电影/a.mkv 改成 http://alist:5244/d/115/电影/a.mkv,再 302 过去。

由服务器先跟随上游重定向(“由伺服器先跟着上游的重导向走到底”,redirect.resolve_redirects,默认关):Mi302 先用播放器的 User-Agent 对地址发 HEAD 请求、跟随所有重定向,再把最终地址交给播放器。

  • 结果按(项目,User-Agent)缓存 redirect.cache_ttl 秒(默认 90),每次最多等 redirect.resolve_timeout 秒(默认 10)。这两项只能在配置文件里改,resolve_timeout 要重启才生效。
  • 失败时用原本的地址。
  • 带 pickcode 的 strm 直接向 115 获取直链,不走这一步。

默认视频格式(“看不出格式时预设的影片格式”,redirect.default_container,默认 mkv):strm 地址看不出扩展名时,告诉播放器用什么格式。

播放进度和已看

播放器用 /Sessions/Playing、/Sessions/Playing/Progress、/Sessions/Playing/Stopped(和旧版的 /Users/{id}/PlayingItems/{id})上报进度。

  • 每个用户各自记录续播位置。
  • 停止时位置到了片长的 90% 以上,标记为已看、播放次数加 1、清除续播位置。片长来自 nfo、媒体信息,或播放器上报的片长。
  • 上报里没有位置时,只更新“最后播放时间”,不动续播位置。
  • 同样的进度也用来学习片头片尾,见 片头片尾跳过。

从外网访问

视频从 115 直接到播放器,Mi302 和反向代理只处理 API 请求和很小的 302 响应,所以家里的上行带宽几乎不影响播放。例外是媒体库里的普通视频文件和 strm 写本地路径的视频,这些要经过 Mi302。

Mi302 本身只提供 HTTP。要从外网用 HTTPS 访问,在前面加一层反向代理(例如 Caddy、Nginx):

  • 用独立的域名或子域名,整个站点都转给 Mi302。放在子路径(例如 /mi302/)下时,Mi302 返回给播放器的播放地址不会带这个子路径。
  • 要把原本的 Host 请求头和 X-Forwarded-Proto 传过去。Mi302 会采用 X-Forwarded-Proto、X-Forwarded-For,并用播放器连进来的地址拼出 PlaybackInfo 里的播放地址;Host 不对,播放器就会拿到错误的地址。
  • /embywebsocket 的 WebSocket 只用来响应 KeepAlive,转不转发都可以,下面的例子有转发。
  • MoviePilot 的封面插件如果经过反向代理上传,要允许 30 MB 的请求。

Caddy(默认就会传 Host、X-Forwarded-Proto,也会自动申请证书):

emby.example.com {
    reverse_proxy 127.0.0.1:8096
}

Nginx:

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 443 ssl;
    server_name emby.example.com;
    ssl_certificate     /etc/ssl/emby.example.com.crt;
    ssl_certificate_key /etc/ssl/emby.example.com.key;
    client_max_body_size 30m;

    location / {
        proxy_pass http://127.0.0.1:8096;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

播放器的服务器地址填 https://emby.example.com。

strm 里的服务器地址

“115 网盘”标签页的“同步选项”卡片里有“strm 里的伺服器网址”(p115.strm.base_url)。留空时自动使用管理员最近一次打开管理页面时的地址。

Mi302 自己播放时只从 strm 里取出 pickcode,不管地址的主机,所以从外网播放不必改这一项。只有其他程序直接读取这些 strm 文件(例如另一台 Emby、用 SMB 打开 strm 的播放器),并且要从外网连到 Mi302 时,才需要填对外地址。

填成反向代理的对外地址(可以带子路径,例如 https://example.com/mi302)并保存后,现有的 strm 会在后台改成新地址,只动本地文件、不连 115,不用重新同步,见115 网盘与同步。反向代理要把 /d/ 开头的请求原样转给 Mi302,并保留播放器的 User-Agent(115 的直链通常绑定获取时的 UA,见上文;Nginx、Caddy 默认就会保留)。播放时 Mi302 照常向 115 获取直链再 302 给播放器,视频不经过反向代理。

安全

  • “播放网址要求登入”保持开启,账号用足够强的密码。
  • 猜密码有限制:同一个来源对同一个账号连续输错 5 次之后,要等一会儿才能再试(30 秒起,每错一次加倍,最多 15 分钟),这时密码对了也要等;播放器登录和 WebDAV 都一样。登录成功或 15 分钟没再错就清零。
  • 可以考虑关掉“伺服器”卡片的“播放器登入画面列出使用者名称”(server.public_users),播放器登录界面就不会列出账号。
  • 管理页面 /web 只有管理员账号能用;API 密钥不能调用管理页面的 API。
  • strm 的短链接 /d/{pickcode} 不检查登录,但要知道 17 位的 pickcode 才能用。取不到直链的请求太多时(同一个来源一分钟 10 次,或全部来源加起来 60 次)先返回 429,不再替它请求 115;刚取过的照给。
  • WebDAV 要用账号密码登录;开放整个 115 时打开“只让管理员登入”。

WebDAV

不想生成 strm、或播放器不支持 Emby 时,可以用 WebDAV 直接浏览 115。在“设定”分页的“WebDAV”打开,保存后立即生效。

  • 只读:浏览文件夹、播放。删除、重命名、上传、新建文件夹一律拒绝。
  • 播放和 strm 一样:Mi302 用播放器自己的 User-Agent 向 115 获取直链,302 过去,不转发视频。
  • 登录:Mi302 的用户名和密码(HTTP Basic)。改了密码或删除用户,马上就登录不了。可以设成只让管理员登录。
  • 开放范围:默认只有同步任务的 115 目录(上层文件夹只看得到通往它们的那一层);也可以填一个 115 文件夹,例如 /影视,或 / 开放整个 115(建议同时打开“只让管理员登入”)。范围外的路径,包括用 .. 往上走的,都返回“找不到”。
  • 路径就是 115 上的路径:/dav/影视/电影/xxx.mkv 是 115 的 /影视/电影/xxx.mkv,大小写要一致。

在播放器里添加 WebDAV 来源,服务器填 http://<主机>:8096/dav/(或分开填主机、端口,路径填 /dav/),账号密码用 Mi302 的:

  • Infuse:添加文件来源(共享)→ WebDAV。
  • VidHub:添加网盘 → WebDAV。
  • Kodi:添加视频源 → 浏览 → 添加网络位置 → 协议选 WebDAV server (HTTP)。

列文件夹是实时问 115 的,同一个文件夹 2 分钟内不重复问。播放器第一次整理整个文件夹(例如 Infuse 的媒体库)时会问很多次,开放的范围越小越不容易被 115 限流;被限流时 Mi302 会熔断,列文件夹暂时失败,播放不受影响。WebDAV 没有 Mi302 的观看记录、片头片尾、媒体信息,这些要走 Emby 登录。在 115 上把文件夹移出开放的范围后,旧路径(和它底下的文件)最多 2 分钟就找不到。

从外网使用时请经过 HTTPS 反向代理:HTTP Basic 的账号密码只是编码,没有加密。

测试:WebDAV 分页下方填一个 Mi302 账号密码,点“测试 WebDAV”。它从你打开管理页面的网址实际连一次 /dav/(经过反向代理的话也一起测到),再看每个开放的 115 文件夹能不能读到,分别说明:还没开启、账号或密码不对、不是管理员但只让管理员登录、响应不是 Mi302 给的(反向代理没转发 /dav/ 或不允许 PROPFIND)、115 上没有这个文件夹。测的是已经保存的设置。

把开放的文件夹改成 /(整个 115)又没打开“只让管理员登入”时,点“储存设定”会先确认一次:所有 Mi302 用户都能看到、播放网盘里的全部文件。

播放器

Infuse、VidHub、SenPlayer、Emby 官方 App 等支持 Emby 的播放器可以直接登录观看。在播放器里添加 Emby 服务器,地址填 http://<主机>:8096(或反向代理的 HTTPS 地址),用 Mi302 的账号登录。

连不上或播放不了时,见 日志与常见问题。

⚠️ **GitHub.com Fallback** ⚠️