HLS .0 cache → MP4
Cache de download por sniffing do navegador Huawei: cada vídeo é armazenado como uma pasta UUID de HLS criptografado, com .0 anexado a cada nome de arquivo. O player do celular lê seu próprio banco de dados + esses nomes. Players de PC e FFmpeg não.
Esta skill converte esse cache fazendo hardlink de .ts.0→.ts e .key.0→.key, alimentando a playlist original para o FFmpeg (-c copy) e depois removendo apenas os nomes temporários. Verificado em caches do navegador Huawei. Outros fabricantes não foram testados.
Quando usar
Ative se alguma destas condições for verdadeira:
- Nomes de pastas parecem com
64f1723d-421b-495c-8a10-85ab7d74ddab - Arquivos nomeados
aq.m3u8.0,*.ts.0,*.key.0 - Usuário menciona 嗅探下载 / 华为浏览器 / VideoData / 手机能播电脑不能
- Linhas de log mencionam
DLEngine,DLSegMgr,download_content_
Não use para: baixar uma URL m3u8 (isso é N_m3u8DL-RE / 猫抓), DRM Widevine/PSSH, ou remuxar .mp4 já sem criptografia.
Estrutura (não confie na busca do workspace)
Cursor/ripgrep omitem arquivos binários *.0. Glob **/*.ts.0 retorna 0 mesmo quando existem 73 segmentos. Prove a existência dos arquivos com uma listagem de diretório (Get-ChildItem / dir / Path.iterdir), ou lendo um caminho nomeado como playlist (erro de leitura binária = arquivo existe).
Cada pasta de vídeo:
<uuid>/
aq.m3u8.0 # playlist; referencia foo.ts e foo.key (sem .0)
<digits>.ts.0 # AES-128 MPEG-TS, ~10s cada
<digits>.key.0 # chave HLS de 16 bytes
O opcional log/<uuid>.txt é texto do DLEngine, não mídia.
Leia references/layout.md se a árvore for diferente (chave faltando, subdiretórios aninhados, sem aq.m3u8.0).
Fluxo de trabalho
Portão rígido — faça isso antes de qualquer conversão ou download.
0. Encontre o ffmpeg, ou pare e pergunte
Busca limitada apenas (nunca recorra uma unidade inteira). scripts/convert.py usa a mesma ordem:
--ffmpeg/ envHLS_DOT0_FFMPEG<cache-root>/ffmpeg.exeou<cache-root>/ffmpegPATH(where.exe ffmpeg/command -v ffmpeg)- Alguns diretórios comuns se ainda estiver faltando:
%LOCALAPPDATA%\Microsoft\WinGet\Links\ffmpeg.exe,%USERPROFILE%\scoop\shims\ffmpeg.exe,C:\ffmpeg\bin\ffmpeg.exe,/opt/homebrew/bin/ffmpeg,/usr/local/bin/ffmpeg
Execute ffmpeg -version (ou o caminho absoluto). Sucesso → vá para o passo 1.
Se não encontrado, pare. Pergunte ao usuário exatamente estas duas opções; não instale nem converta até que ele responda:
- A. Ele mesmo instala ou coloca o
ffmpege avisa quando estiver pronto — reexecute esta busca +-version. - B. Você instala — detecte SO e arquitetura primeiro (
win32+PROCESSOR_ARCHITECTURE/uname -s+uname -m). Em seguida, siga apenas o padrão correspondente em references/ffmpeg-install.md.
Regras de instalação: um comando padrão, um fallback se falhar, depois pergunte novamente. Não instale Homebrew / Chocolatey / Scoop apenas para ter ffmpeg, a menos que o usuário concorde. Não confirme um binário baixado neste repositório da skill. Após uma instalação bem-sucedida, verifique -version em um novo shell ou pelo caminho do instalador (o PATH do Windows geralmente está desatualizado).
1. Planeje (imprima, depois converta)
Liste os diretórios UUID (hex 8-4-4-4-12). Para cada um, conte *.ts.0, *.key.0 e se aq.m3u8.0 existe. Pule pastas com 0 segmentos ou sem chave.
Ordem padrão: nome da pasta A–Z. Numere as saídas 01.mp4, 02.mp4, … em --out-dir (padrão <cache-root>/mp4) a partir de --start (padrão 1). O script pula um nome quando esse mp4 já existe (JSON skipped: true), a menos que --force seja usado. Reexecute o mesmo comando após um lote parcial — números já concluídos permanecem, o restante converte. Não invente um segundo esquema de numeração.
2. Execute o script incluído (não reinvente)
A partir da raiz desta skill:
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
Sempre execute --dry-run primeiro em uma árvore nova. A saída padrão do script é JSON; o progresso vai para stderr.
Não reescreva a playlist para *.ts.0. O FFmpeg rejeita essa extensão mesmo com -allowed_extensions ALL (not in allowed_segment_extensions). Faça hardlink/cópia para os nomes já em aq.m3u8.0.
Não teste as saídas com PowerShell $ErrorActionPreference = "Stop" mais ffmpeg -i file -f null -. O FFmpeg escreve banner no stderr; o PowerShell trata isso como um erro de terminação e um catch que deleta o mp4 apagará uma conversão bem-sucedida.
Flags exatas do FFmpeg (frágil — não remova):
ffmpeg -y -hide_banner -loglevel warning -stats -allowed_extensions ALL -protocol_whitelist file,crypto,data -i play.m3u8 -c copy out.mp4
3. Limpeza e relatório
O script remove apenas nomes temporários que criou nesta execução (mais hardlinks residuais que já apontam para os arquivos .0) e sempre remove play.m3u8. Os originais *.ts.0 / *.key.0 / aq.m3u8.0 permanecem. Ele não deleta um .ts / .key pré-existente que não seja um hardlink para o arquivo .0.
Relate uma tabela: número, tamanho, duração se conhecida, sps_warning. Veja references/troubleshooting.md para SPS e outras falhas.
Se o usuário pedir para recodificar um arquivo com aviso SPS: ffmpeg -i 04.mp4 -c:v libx264 -crf 18 -c:a copy 04_fixed.mp4 — apenas esses arquivos, não o lote inteiro.
Lista de verificação
- Listagem de diretório mostra
.ts.0e.key.0(ferramentas de busca podem mentir) - ffmpeg encontrado (busca limitada) ou usuário escolheu A/B;
-versionok; sem varredura de disco completo - Se instalando: SO/arquitetura detectados; apenas os comandos correspondentes em
references/ffmpeg-install.md - Plano
--dry-runparece correto (contagens, nomes de saída,SKIPem mp4s existentes) - Uma pasta convertida e o usuário pode reproduzi-la (a menos que ele tenha dito para converter tudo)
- Lote JSON
ok/skipped/ erros por item; links temporários removidos - Mencione números com aviso SPS para que o usuário possa verificar
Formato de saída
Convertidos N/M vídeos → <out-dir>
01.mp4 101 MB (~12:10) ok
04.mp4 251 MB (~23:59) aviso SPS — verifique início e cortes de ~10s
FALHA <uuid> key.0 ausente
Pegadinhas
.0é a mídia real. Glob/index ignorando binários não significa "arquivos faltando".- Playlist
URI="….key"e….ts— no disco são….key.0/….ts.0. - Hardlinks devem permanecer no mesmo volume; se
os.linkfalhar, copie (lento, disco extra). non-existing SPS 0 referenced in buffering periodgeralmente é cosmético em-c copy. Verifique limites de 10s; recodifique apenas se a reprodução estiver quebrada.- Ferramentas GUI (N_m3u8DL-RE, m3u8-to-mp4) esperam extensões padrão. Funcionam após renomear/hardlink, não com nomes Huawei brutos.
- Isto é HLS AES-128 padrão com chave local (
no psshnos logs do DLEngine), não circumvenção Widevine. - Sem ffmpeg → pergunte A/B primeiro. Não faça
winget/brew/aptsilenciosamente nem baixe um exe. 01.mp4… existentes são pulados, não são erros. Use--forceapenas quando o usuário quiser que esses arquivos sejam sobrescritos.