teqo-backup/tests/fixtures/fake-ffmpeg.mjs
Francisco Solla dbe77f08cc
Some checks are pending
Deploy / preflight (push) Waiting to run
Deploy / verify (push) Blocked by required conditions
Deploy / deploy staging (teqo-staging) (push) Blocked by required conditions
Deploy / requeue when main advanced (push) Blocked by required conditions
Deploy / deploy production (teqo-1313) (push) Blocked by required conditions
feat(C226): frame estático nos vídeos da Central antes do play
Peça de vídeo publicada e com arquivo passa a mostrar um frame estático
leve no card público antes do play, sem nenhum request do arquivo antes
do gesto (`preload="none"` do S27 intacto).

O frame é um derivado privado em `contentMedia` (nome determinístico),
gerado por um dono só — `ensureContentPieceFrame` — chamado pelo job
C211 (que já tem o arquivo em disco: a extração sai de graça) e pela
rota `GET /conteudos/<slug>/frame` em miss, que cura o acervo anterior
sem backfill, fila, collection nova ou migration.

A porta reusa o gate de slug publicado e o proxy de mídia privada do
`/midia`: o kill switch fecha as duas de uma vez. Sem frame possível, o
slot mostra o estado neutro honesto com play e o marcador — nunca
imagem quebrada, nunca retry.

A projeção declara o frame por elegibilidade (vídeo com arquivo), não
pela existência do derivado, então a cura é invisível para o cache da
listagem e não há tag para bustar. O frame também aparece na página da
peça e no card da home (variante compacta de 124px, cena 05).

A passagem de design (tier primário) achou dois bugs que só o browser
mostra: o glyph de imagem quebrada numa requisição que falha, e — ao
esconder a imagem até decodificar — o frame sumindo para sempre no
caminho mais rápido (uma imagem que carrega antes da hidratação não
dispara `load` nem `error` de novo; o `ref` decide os dois desfechos).

Também: o guard de falha de e2e aceita `RegExp` e confere os paths
declarados antes do caso do favicon (todo 404 do browser traz a mesma
mensagem), o manifest de e2e mapeia os módulos novos, e o job C211
passa o arquivo que já tem em disco em vez de rebaixar o vídeo.

Design tier: central-conteudos-preview-frame-video
Closes #1352
2026-09-25 14:56:06 -03:00

55 lines
1.8 KiB
JavaScript
Executable file

#!/usr/bin/env node
/**
* C167/C199 test double for ffmpeg: copies the `-i` input to the output path so
* the cut/recording pipelines can run without a real encoder (the developer
* machine has none). A `%0Nd` output pattern (C199's `-f segment`) produces
* numbered copies instead of one literal file, mirroring what the segmented
* command writes. `FAKE_FFMPEG_FAIL=1` makes it exit 1; `FAKE_FFMPEG_LOG=<path>`
* records argv. The real binary is exercised by the `skipIf(!hasFfmpeg())`
* block (CI).
*
* `FAKE_FFMPEG_FAIL_STILL=1` (C226) fails only the still command — the one
* carrying `-frames:v 1` — so a spec can pin a pipeline that ingests perfectly
* and then fails to produce a frame, which `FAKE_FFMPEG_FAIL` cannot express
* (it would fail the audio extraction too).
*/
import { copyFileSync, writeFileSync } from 'node:fs'
import { argv, env, exit } from 'node:process'
const args = argv.slice(2)
if (env.FAKE_FFMPEG_LOG) {
writeFileSync(env.FAKE_FFMPEG_LOG, JSON.stringify(args))
}
if (env.FAKE_FFMPEG_FAIL === '1') {
process.stderr.write('fake-ffmpeg: forced failure\n')
exit(1)
}
if (env.FAKE_FFMPEG_FAIL_STILL === '1' && args.includes('-frames:v')) {
process.stderr.write('fake-ffmpeg: forced still failure\n')
exit(1)
}
const inputIndex = args.indexOf('-i')
const input = inputIndex >= 0 ? args[inputIndex + 1] : undefined
const output = args.at(-1)
if (!input || !output) {
process.stderr.write('fake-ffmpeg: missing -i input or output path\n')
exit(2)
}
const segmentPattern = /%0?(\d+)d/.exec(output)
if (segmentPattern) {
const width = Number(segmentPattern[1])
const count = Number(env.FAKE_FFMPEG_SEGMENTS ?? '2')
for (let index = 0; index < count; index += 1) {
const name = output.replace(segmentPattern[0], String(index).padStart(width, '0'))
copyFileSync(input, name)
}
exit(0)
}
copyFileSync(input, output)