HLS .0 快取 → MP4
華為瀏覽器嗅探下載會將每部影片儲存為一個 UUID 資料夾,內容為加密的 HLS,然後在每個檔案名稱後附加 .0。手機播放器能透過其內部資料庫讀取這些名稱。桌上型電腦播放器和 FFmpeg 則無法。
此技能透過硬連結將 .ts.0 → .ts 以及 .key.0 → .key,將原始播放清單餵給 FFmpeg(-c copy),然後僅刪除暫時的名稱,來轉換該快取。已在華為瀏覽器快取上驗證。其他廠商未經測試。
使用時機
若以下任一情況為真,請啟用此技能:
- 資料夾名稱看似
64f1723d-421b-495c-8a10-85ab7d74ddab - 檔案命名為
aq.m3u8.0、*.ts.0、*.key.0 - 使用者提及「嗅探下載」/「華為瀏覽器」/「VideoData」/「手機能播電腦不能」
- 日誌行包含
DLEngine、DLSegMgr、download_content_
請勿用於:下載 m3u8 URL(應使用 N_m3u8DL-RE / 貓抓),Widevine/PSSH DRM,或重新封裝已是純 .mp4 的檔案。
佈局(勿信任工作區搜尋)
Cursor/ripgrep 會忽略二進位 *.0 檔案。Glob **/*.ts.0 即使有 73 個片段存在,也會回傳 0 個結果。透過目錄清單(Get-ChildItem / dir / Path.iterdir),或讀取一個播放清單命名的路徑(二進位讀取錯誤 = 檔案存在),來證明檔案存在。
每個影片資料夾:
<uuid>/
aq.m3u8.0 # 播放清單;參照 foo.ts 和 foo.key(無 .0)
<digits>.ts.0 # AES-128 MPEG-TS,每個約 10 秒
<digits>.key.0 # 16 位元組 HLS 金鑰
可選的兄弟 log/<uuid>.txt 是 DLEngine 文字,非媒體。
若目錄結構不同(缺少 key、巢狀目錄、無 aq.m3u8.0),請閱讀 references/layout.md。
工作流程
嚴格關卡 — 在任何轉換或下載之前,請先執行此步驟。
0. 尋找 ffmpeg,否則停止並詢問
僅限定範圍搜尋(絕對不要遞迴整個磁碟)。scripts/convert.py 使用相同順序:
--ffmpeg/ envHLS_DOT0_FFMPEG<cache-root>/ffmpeg.exe或<cache-root>/ffmpegPATH(where.exe ffmpeg/command -v ffmpeg)- 若仍找不到,檢查幾個常見目錄:
%LOCALAPPDATA%\Microsoft\WinGet\Links\ffmpeg.exe、%USERPROFILE%\scoop\shims\ffmpeg.exe、C:\ffmpeg\bin\ffmpeg.exe、/opt/homebrew/bin/ffmpeg、/usr/local/bin/ffmpeg
執行 ffmpeg -version(或該絕對路徑)。成功 → 前往步驟 1。
若未找到,停止。向使用者詢問以下兩個確切選項;在他們回答之前,請勿安裝或轉換:
- A. 他們自行安裝或放置
ffmpeg,然後告知您準備就緒 — 重新執行此搜尋 +-version。 - B. 您來安裝 — 先偵測作業系統和架構(
win32+PROCESSOR_ARCHITECTURE/uname -s+uname -m)。然後僅遵循 references/ffmpeg-install.md 中匹配的預設指令。
安裝規則:一個預設指令,一個失敗時的備用指令,然後再次詢問。除非使用者同意,否則請勿為了安裝 ffmpeg 而安裝 Homebrew / Chocolatey / Scoop。請勿將下載的二進位檔案提交到此技能儲存庫。成功安裝後,請在新的 shell 或透過安裝程式路徑(Windows PATH 通常已過時)驗證 -version。
1. 規劃(先列印,再轉換)
列出 UUID 目錄(8-4-4-4-12 十六進位)。對於每個目錄,計算 *.ts.0、*.key.0 的數量,以及 aq.m3u8.0 是否存在。跳過片段數為 0 或缺少金鑰的資料夾。
預設順序:資料夾名稱 A–Z。輸出編號為 01.mp4、02.mp4、…,放置於 --out-dir(預設為 <cache-root>/mp4),從 --start(預設為 1)開始。當該 mp4 已存在時,指令稿跳過該名稱(JSON skipped: true),除非使用 --force。在部分批次後重新執行相同指令 — 已完成的編號保持不變,其餘繼續轉換。請勿發明第二種編號方案。
2. 執行內建指令稿(請勿重新發明)
從此技能根目錄:
python scripts/convert.py --root <cache-root> --dry-run
python scripts/convert.py --root <cache-root> --out-dir <cache-root>/mp4 --start 1
python scripts/convert.py --root <cache-root> --folder <uuid> --name 01 --force
在新的目錄樹上,務必先傳遞 --dry-run。指令稿 stdout 為 JSON;進度資訊輸出到 stderr。
請勿將播放清單重寫為 *.ts.0。即使使用 -allowed_extensions ALL,FFmpeg 也會拒絕該副檔名(not in allowed_segment_extensions)。請硬連結/複製到 aq.m3u8.0 中已存在的名稱。
請勿使用 PowerShell 的 $ErrorActionPreference = "Stop" 搭配 ffmpeg -i file -f null - 來探查輸出。FFmpeg 會將橫幅寫入 stderr;PowerShell 會將其視為終止錯誤,而一個會刪除 mp4 的 catch 區塊將會清除成功的轉換。
確切的 FFmpeg 旗標(脆弱的 — 請勿遺漏):
ffmpeg -y -hide_banner -loglevel warning -stats -allowed_extensions ALL -protocol_whitelist file,crypto,data -i play.m3u8 -c copy out.mp4
3. 清理與回報
指令稿僅移除它於此次執行中建立的暫時名稱(以及已經指向 .0 檔案的殘留硬連結),並且一律移除 play.m3u8。原始的 *.ts.0 / *.key.0 / aq.m3u8.0 保持不變。它不會刪除預先存在的、且非連接到 .0 檔案的硬連結 .ts / .key。
回報一個表格:編號、大小、時長(若已知)、sps_warning。關於 SPS 和其他失敗,請參閱 references/troubleshooting.md。
若使用者要求重新編碼一個 SPS-warning 檔案:ffmpeg -i 04.mp4 -c:v libx264 -crf 18 -c:a copy 04_fixed.mp4 — 僅限那些檔案,而非整個批次。
檢查清單
- 目錄清單顯示
.ts.0和.key.0(搜尋工具可能說謊) - 已找到 ffmpeg(限定範圍搜尋)或使用者選擇了 A/B;
-version正常;無全磁碟掃描 - 若安裝:已偵測作業系統/架構;僅使用
references/ffmpeg-install.md中匹配的指令 -
--dry-run計劃看起來正確(計數、輸出名稱、對現有 mp4 的SKIP) - 已轉換一個資料夾且使用者可以播放(除非他們說要全部轉換)
- 批次 JSON 顯示
ok/skipped/ 每項錯誤;暫時連結已消失 - 提及 SPS-warning 的編號,以便使用者可以抽查
輸出格式
已轉換 N/M 個影片 → <out-dir>
01.mp4 101 MB (~12:10) ok
04.mp4 251 MB (~23:59) SPS 警告 — 檢查開始處和大約 10 秒處的剪切
失敗 <uuid> 缺少 key.0
注意事項
.0才是真正的媒體。 比對/索引跳過二進位檔並非「檔案遺失」。- 播放清單
URI="….key"和….ts— 在磁碟上它們是….key.0/….ts.0。 - 硬連結必須留在同一個磁碟區上;若
os.link失敗,則使用複製(較慢,額外磁碟空間)。 non-existing SPS 0 referenced in buffering period在-c copy時通常只是外觀問題。檢查 10 秒邊界;僅在播放損壞時重新編碼。- GUI 工具(N_m3u8DL-RE,m3u8-to-mp4)預期標準副檔名。它們在重新命名/硬連結之後才能運作,無法直接處理原始華為名稱。
- 這是標準的 HLS AES-128,使用本地金鑰(DLEngine 日誌中的
no pssh),而非 Widevine 規避。 - 無 ffmpeg → 先詢問 A/B。 請勿靜默地
winget/brew/apt或下載 exe。 - 已存在的
01.mp4… 會被跳過,而非視為錯誤。僅在使用者想要覆寫那些檔案時使用--force。