Communitygithub.com

zimodzh/hls-dot0-to-mp4-skill

Agent 技能:將華為瀏覽器嗅探下載的 HLS `.0` 快取(aq.m3u8.0 · *.ts.0 · *.key.0)轉換為桌上型可播放的 MP4。手機能播、電腦打不開 — 僅本地重新封裝,不抓取 URL,無 DRM。

hls-dot0-to-mp4-skill 是什麼?

此技能(HLS `.0` 快取轉 MP4)專門處理華為瀏覽器「資源嗅探 / 嗅探下載」功能所產生的特殊 HLS 快取格式。當使用者從華為瀏覽器下載影片時,系統會將每個影片儲存為一個 UUID 命名的資料夾,並在每個檔案名稱後附加「.0」後綴(例如 `aq.m3u8.0`、`*.ts.0`、`*.key.0`)。雖然手機端瀏覽器能透過其內部資料庫正確讀取這些檔案,但桌上型電腦的播放器或 FFmpeg 卻無法直接識別。此技能的核心運作方式,是透過建立硬連結(hardlink)將「.ts.0」重新命名為「.ts」、將「.key.0」重新命名為「.key」,然後將原始播放清單餵給 FFmpeg,使用「-c copy」進行無損重新封裝為 MP4,最後僅清理暫時建立的連結。此技能支援 Windows、macOS 和 Linux 平台,並內建 FFmpeg 查找與安裝引導機制。它**不**用於從 URL 下載 m3u8、處理 Widevine DRM,或重新封裝已為純 MP4 的檔案。技能包含一個 Python 指令稿 `scripts/convert.py`,可處理批次轉換,並提供 `--dry-run` 預覽、`--force` 強制覆蓋與 JSON 格式輸出。

相容平台~Claude Code~Codex CLI✓Cursor
npx skills add zimodzh/hls-dot0-to-mp4-skill

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

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 使用相同順序:

  1. --ffmpeg / env HLS_DOT0_FFMPEG
  2. <cache-root>/ffmpeg.exe 或 <cache-root>/ffmpeg
  3. PATH(where.exe ffmpeg / command -v ffmpeg)
  4. 若仍找不到,檢查幾個常見目錄:%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。

相關技能