播放與外網連線 - 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** ⚠️