Hongguo Short Drama & Douyin/TikTok — Truques de API e Descriptografia
1. Resolução de Entrada do Hongguo Short Drama (红果免费短剧 / Fanqie)
- Links Curtos de Compartilhamento (
novelquickapp.com/s/...,changdunovel.com):- Envie uma requisição
GETcomredirect: "manual"e User-Agent mobile. - Analise a string de consulta do cabeçalho
Locationem busca devideo_series_id,series_id,book_id,album_id,group_id,item_idouvid(IDs numéricos de 19 dígitos).
- Envie uma requisição
- Links Web Oficiais (
hongguoduanju.com):- Página da série:
https://hongguoduanju.com/detail?series_id={19_digit_id} - Página do player do episódio:
https://hongguoduanju.com/player/{series_id}/{vid}
- Página da série:
2. Truque #1: Contornando X-Gorgon via Espelhos de Pré-carregamento do App Fqnovel Oficial
Endpoints móveis padrão do Fqnovel/Hongguo exigem as assinaturas X-Gorgon / X-Argus da ByteDance. No entanto, os endpoints de pré-carregamento v1 em 6 espelhos oficiais aceitam requisições POST não autenticadas quando passam os parâmetros de consulta padrão do Android e "dr_scene": "preload":
- 6 Espelhos Ativos:
https://api5-normal-sinfonlineb.fqnovel.comhttps://api5-normal-sinfonlinea.fqnovel.comhttps://api5-normal-sinfonlinec.fqnovel.comhttps://api5-normal-lf.fqnovel.comhttps://api5-normal-lq.fqnovel.comhttps://api5-normal-hl.fqnovel.com
- String de Consulta Obrigatória (
COMMON_APP_QUERY):klink_egdi=AAI29o4dI-eMiO73_SRSbZ_0By1v3fUSriNeu8-L951MoXhWT88pzj5B&iid=3788260546453235&device_id=538083340353620&ac=wifi&channel=oppo_8662_64&aid=8662&app_name=novelread&version_code=71532&version_name=7.1.5.32&device_platform=android&os=android&ssmix=a&device_type=SM-N9860&device_brand=Samsung&language=zh&os_api=28&os_version=9&manifest_version_code=71532&resolution=900*1600&dpi=320&update_version_code=71532&host_abi=arm64-v8a&dragon_device_type=pad&pv_player=71532&compliance_status=0&need_personal_recommend=1&player_so_load=1&is_android_pad_screen=0 - Cabeçalhos Obrigatórios:
User-Agent:com.phoenix.read/71532 (Linux; U; Android 9; SM-N9860; Build/PQ3A.190705.10241111;tt-ok/3.12.13.20)Referer:https://novelquickapp.com/
- Endpoint A — Metadados Completos da Série e Lista de Episódios:
- Caminho:
POST /novel/player/multi_video_detail/preload/v1?{COMMON_APP_QUERY} - Corpo JSON:
{ "biz_param": { "detail_page_version": 0, "disable_digg_stat": false, "need_all_video_definition": false, "need_mp4_align": false, "screen_width_px": "900", "source": 7, "use_os_player": false, "use_server_dns": false }, "dr_scene": "preload", "series_id": "7588802892412406808" } - Retorna:
data[series_id].video_data(series_title,series_cover,series_intro,episode_cnt,celebritiesevideo_listcontendo todos osvid,vid_index,durationdos episódios).
- Caminho:
- Endpoint B — Streams de Vídeo Multi-resolução e Chaves
spade_a:- Caminho:
POST /novel/player/multi_video_model/preload/v1?{COMMON_APP_QUERY} - Corpo JSON:
{ "biz_param": { "detail_page_version": 0, "device_level": 3, "disable_digg_stat": false, "need_all_video_definition": true, "need_mp4_align": false, "use_os_player": false, "use_server_dns": false, "video_platform": 1024 }, "dr_scene": "preload", "mixed_video_id_map": { "1004": ["7588804476701690904"] } } - Retorna:
data[vid].video_model(string JSON). Dentro devideo_list(video_1avideo_5), cada item contémdefinition(360p..1080p),main_url,backup_url,encrypt_info.spade_a, além defallback_api(https://vas-lf-x.snssdk.com/video/fplay/1/...).
- Caminho:
3. Truque #2: SSR Web Oficial do Hongguo (window._ROUTER_DATA) e Stream H.264 Direto
- Extraindo
window._ROUTER_DATA:- Busque páginas
https://hongguoduanju.com/com UA de navegador desktop padrão:- Tendências/Home:
https://hongguoduanju.com/(loaderData.page.homeSections) - Páginas de categoria:
https://hongguoduanju.com/category/{real-drama|comic-drama|ai-drama}(loaderData.category_page.recommendList) - Pesquisa por palavra-chave:
https://hongguoduanju.com/search/{encodeURIComponent(keyword)}(loaderData["search_(keyword)/page"].searchList) - Detalhes da série:
https://hongguoduanju.com/detail?series_id={seriesId}(seriesDetail.vid_list)
- Tendências/Home:
- Extraia o JSON atribuído a
_ROUTER_DATAvia análise balanceada de chaves começando no primeiro{após_ROUTER_DATA.
- Busque páginas
- Stream H.264 Não Criptografado (
360p-h264):- Cada
vidde episódio tem um endpoint MP4 H.264/AAC direto não criptografado:https://hongguoduanju.com/video/public/{vid}/360p.mp4 - Deve ser buscado com o cabeçalho
Referer: https://hongguoduanju.com/. - Use este stream para pré-visualização instantânea
<video>em navegadores (já que navegadores não podem reproduzir nativamente streamsencvcriptografados com CENC sem EME/MSE).
- Cada
4. Truque #3: Derivação da Chave spade_a e Descriptografia Rápida CENC-AES-128-CTR com WebCrypto
spade_apara Chave AES de 16 Bytes (key_hex— algoritmolibttmplayer.so):- Decodifique
spade_aem Base64 para obterbuf(L = buf.length). - Calcule
key0 = buf[0] ^ buf[1] ^ buf[2],x27 = key0 - 0x30,w22 = L - key0 + 0x2f. - Fatia
x21 = buf.slice(1, 1 + w22). Inicializew11 = 0x55,w12 = 0xfa,w10 = 0xeb. - Para cada índice
i, calcule a contagem de populaçãopc = popcount(i),w14 = (i & 1) === 0 ? w12 : w11, atualizew11/w12comx21[i]e definax21[i] = ((w10 - pc) + (w14 ^ x21[i])) & 0xff. - Decodifique o dígito base36
hvaldex21[0], calculew9 = w22 - hvale extraia a string hex ASCIIx21.slice(1, w9)(32 caracteres hex = chave AES de 16 bytes).
- Decodifique
- Descriptografando MP4 ISO-BMFF
cenc(encv->hvc1,enca->mp4a):- Localize o box
moove itere sobre cadatrak -> mdia -> minf -> stbl:- Analise
stsz(tamanhos das amostras),stsc(amostra-para-chunk),stco(offsets dos chunks) esenc(IV de 8 bytes por amostra emsenc.off + 16 + i * 8). - Preencha com zeros cada IV de 8 bytes para um bloco de contador AES-CTR de 16 bytes (
counter[0..7] = iv8,counter[8..15] = 0) e descriptografe cada amostra comcrypto.subtle.decrypt({ name: "AES-CTR", counter, length: 64 }, cryptoKey, sampleSlice).
- Analise
- Reconstrua
moov:- Renomeie
encv->hvc1,enca->mp4a, remova os boxessinf,senc,saio,saize subtraiadelta = oldMoovSize - newMoovSizede cada offset emstcoque seguemoov(ou sobrescrevasinf/senc/saio/saizno local com boxesfreepara manter o tamanho demoovconstante).
- Renomeie
- Localize o box
5. Truque #4: Bypass de CPU de 10ms no Cloudflare Free e Rotação Multi-Provedor do Douyin
- Descriptografia Híbrida Cliente + Servidor:
- No Cloudflare Free Tier (limite de CPU de 10ms), exponha
/api/download?url=...&raw=1(passagem de streaming comReferer: https://novelquickapp.com/). - Realize a descriptografia
CENC-AES-128-CTRno navegador viawindow.HongguoClientDecryptorusando WebCrypto acelerado por hardware (0ms de custo de CPU no Worker), mantendo a descriptografia no servidor em/api/downloade no Pythonapp.py(Render.com compycryptodome) como fallback.
- No Cloudflare Free Tier (limite de CPU de 10ms), exponha
- Failover Multi-Provedor Douyin / TikTok:
- Primário:
TikWM(https://www.tikwm.com/api/,POST url=...&hd=1) — sem cooldown. - Fallback: 4 rotas do
Apihz(https://cn.apihz.cn/api/fun/douyin.php+ 3 espelhos IP HTTP proxyados no servidor via Cloudflare Worker para evitar bloqueio de conteúdo misto HTTPS no navegador). - Nota:
api.cenguigui.cn/api/duanju.htmlestá obsoleto (HTTP 404); mantenha apenas como fallback de último recurso.
- Primário:
6. Truque #5: Runbook de Otimização "Max Ping" e Cota no Cloudflare Free
Para alcançar entrega em Edge com <2ms, zero estouro de CPU e evitar queimar a cota de 100.000 invocações/dia do Cloudflare Free Worker:
- Bypass de Cota de Ativos Estáticos (
public/_routes.json):- Use
"include": ["/api/*"]e"exclude": ["/", "/index.html", "/articles.js", "/ads.txt", "/robots.txt", "/sitemap.xml", "/favicon.svg"]. - Resultado: Arquivos estáticos são servidos diretamente pelo CDN Cloudflare nos PoPs de Edge (~5ms de ping) e consomem zero invocações de Worker.
- Use
- Coalescência de Requisições Singleflight (
INFLIGHT_MAP):- Coalesça requisições concorrentes recebidas para a mesma série, episódio ou categoria em uma única Promise. Requisições posteriores aguardam a busca em andamento, evitando chamadas upstream duplicadas.
- Stale-While-Revalidate (SWR) na RAM do V8 Isolate:
- Armazene em cache o JSON analisado em
MEM_CACHEno nível do módulo. Se uma requisição chegar após o soft TTL expirar, mas dentro do hard TTL (3x), retorne os dados em cache instantaneamente (0.0ms) e dispare uma atualização assíncrona em segundo plano viactx.waitUntil.
- Armazene em cache o JSON analisado em
- Placar Adaptativo de Latência de Espelhos (Rastreador EMA + Hedging):
- Meça continuamente o RTT em todos os 6 espelhos de pré-carregamento do Fqnovel (
sinfonlineb,sinfonlinea,sinfonlinec,lf,lq,hl). - Ordene dinamicamente os espelhos pela menor latência EMA e faça hedging de requisições upstream com um timeout paralelo de
650ms.
- Meça continuamente o RTT em todos os 6 espelhos de pré-carregamento do Fqnovel (
- Agrupamento de 15 Episódios em uma Única Requisição:
- O endpoint
/novel/player/multi_video_model/preload/v1do Fqnovel aceita até 15 VIDs emmixed_video_id_map: { "1004": [vid1, vid2, ... vid15] }. - Pré-busque 15 episódios na chamada inicial
/api/parsee durante downloads em lote via/api/episode?vids=...&indices=..., reduzindo 93% das viagens de ida e volta da API.
- O endpoint
- Posicionamento Inteligente (
wrangler.toml):- Especifique
[placement] mode = "smart"para que o Cloudflare execute Workers em datacenters Edge próximos aos upstreams asiáticos da ByteDance/Hongguo, reduzindo a latência de rede multi-hop em 40-70%.
- Especifique
- API de Cache de Edge (
caches.default):- Armazene em cache imagens de capa (
/api/proxy) por 30 dias (immutable) e MP4s descriptografados pequenos (<= 20MB) por 1-2 horas para que requisições repetidas e requisições de range sejam servidas diretamente da RAM do Edge.
- Armazene em cache imagens de capa (
7. Truque #6: Offloading Direto do CDN ByteDance (Largura de Banda Zero e Custo de CPU de 0ms)
- Descoberta de Cabeçalho CORS Upstream:
- Tanto
*.qznovelvod.com(CDN VOD da ByteDance para MP4 CENC 1080p) quanto*.byteimg.com(CDN de imagens de capa) retornamHTTP 200com cabeçalho:Access-Control-Allow-Origin: *quando requisitados sem o cabeçalhoReferer(referrerPolicy: "no-referrer").
- Tanto
- Busca Direta no Lado do Cliente:
- No frontend do navegador, busque bytes MP4 brutos diretamente via:
fetch(rawVideoUrl, { referrerPolicy: "no-referrer" })e só recorra a/api/download?url=...&raw=1se o CORS falhar. - Para imagens, use
<img src="direct_byteimg_url" referrerpolicy="no-referrer" onerror="this.src='/api/proxy?url=...'"/>. - Benefício: 100% da largura de banda de vídeo e 99% das requisições de imagem ignoram completamente os Workers Cloudflare, economizando milhares de invocações de Worker e limites de largura de banda no Cloudflare Free.
- No frontend do navegador, busque bytes MP4 brutos diretamente via:
8. Truque #7: Mecanismo Híbrido de Descriptografia AES-128-CTR com T-Table 4,1x + WebCrypto
- Distribuição de Amostras em MP4 CENC 1080p:
- Em streams MP4 CENC ISO-BMFF, 94,2% das amostras têm $\le 2048$ bytes (quadros de áudio e fatias de vídeo P/B). Apenas ~5,8% (grandes I-frames) excedem 2048 bytes.
- Chamar
crypto.subtle.decryptpara mais de 12.000 amostras pequenas cria mais de 12.000 alocações de Promise, causando grande overhead no loop de eventos e atingindo os limites de CPU de 10ms do Cloudflare Worker (Error 1102).
- Solução Híbrida:
- Pré-calcule tabelas T AES de 32 bits (
AES_TE0..TE3,AES_SBOX). - Descriptografe todas as amostras $<= 2048$ bytes de forma síncrona in-place (0 alocação de Promise, 0 GC).
- Despache apenas grandes I-frames ($> 2048$ bytes) para
crypto.subtle.decryptacelerado por hardware. - Resultado: O tempo de descriptografia cai de 395,6ms para 95,7ms (4,1x mais rápido), as alocações de Promise caem 94,2%.
- Pré-calcule tabelas T AES de 32 bits (
- Web Worker Inline no Navegador:
- Execute o descriptografador dentro de um Web Worker
Blobinline comArrayBufferTransferablede cópia zero (postMessage(..., [u8.buffer])). - Garante 0ms de congelamento da UI na thread principal do navegador durante download em lote de múltiplos episódios.
- Execute o descriptografador dentro de um Web Worker
9. Truque #8: Rotação Multi-Provedor Douyin / TikTok e Bypass de Cooldown
- Cooldown de 30s do Apihz:
- Contas gratuitas do Apihz impõem um limite de taxa estrito de 30s (
该接口免费用户限制30秒解析1次). - Rota Primária: Deve usar HTTPS
https://cn.apihz.cn/api/fun/douyin.php(IPs brutos como101.35.2.25falham através de firewalls). - Cache de Dois Níveis: Armazene em cache as respostas analisadas do Douyin por 30 minutos (
getOrSetCache(cacheKey, 1800, ...)) usandoaweme_idcanônico ou URL resolvida. Acessos subsequentes retornam em $<1\text{ms}$ e ignoram completamente o limite de taxa de 30s.
- Contas gratuitas do Apihz impõem um limite de taxa estrito de 30s (
- Hedged Fallback com TikWM e SSR Nativo:
- Resolva
v.douyin.comcomredirect: "manual"em ~200ms para obter oaweme_idcanônico. - Corra o Apihz (primário) contra backups TikWM e SSR Nativo usando
raceWithHedge(primary, backups, 1200).
- Resolva