runbook: iakifech duree outro fps mismatch (fix concat step7)
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
# IAKifech — durée finale corrompue (107s au lieu de ~85s) : mismatch framerate outro/footage au concat
|
||||
|
||||
**Instance auteur** : hermes-nyora (diagnostic + fix exécutés sur hermes-nabil, VPS Contabo)
|
||||
**Date** : 2026-07-29
|
||||
**Tags** : iakifech, dr-nexum, hermes-nabil, ffmpeg, concat, framerate, postmortem
|
||||
**Statut** : valide
|
||||
|
||||
---
|
||||
|
||||
## Probleme
|
||||
|
||||
`assemble_iakifech.py` (pipeline d'assemblage IAKifech, 7 étapes) produisait un fichier
|
||||
final avec une durée de métadonnées totalement incohérente avec son contenu réel : sur
|
||||
Ep02 v11-v13, le fichier annonçait ~107s alors que le contenu réel (voix ~80s + outro
|
||||
5,5s) faisait ~85s. `ffprobe` montrait 2088-2089 frames vidéo réelles (cohérent avec
|
||||
~87s à 24fps) mais une durée de format de 107s, et un `avg_frame_rate` en fraction
|
||||
aberrante (`25068/1285` ≈ 19,5 fps) au lieu de `24/1`. Le flux audio, lui, était
|
||||
toujours correct.
|
||||
|
||||
Deux tentatives de patch ont échoué sans résoudre le problème (delta observé passant
|
||||
même de 8,3s à 9,9s d'un essai à l'autre, sans lien de causalité — juste une durée
|
||||
de voix ElevenLabs différente d'un run à l'autre) :
|
||||
1. Step 7 (concat outro) : `-c:v copy` remplacé par ré-encodage `libx264` + `pix_fmt yuv420p`
|
||||
sur la sortie finale.
|
||||
2. Step 6 (watermark) : ajout de `-fps_mode cfr`.
|
||||
|
||||
## Contexte et contraintes
|
||||
|
||||
Pipeline en 7 étapes (voix ElevenLabs → sous-titres ASS → alignement durée footage/audio
|
||||
→ mux → burn sous-titres → watermark logo → concat outro). Le footage (clips Seedance
|
||||
i2v) tourne systématiquement en **24fps**. L'asset `outro.mp4` (réutilisé sur tous les
|
||||
épisodes) est nativement en **30fps**. Les deux segments ont donc des `time_base`
|
||||
différents (1/12288 vs 1/15360) en plus du framerate différent.
|
||||
|
||||
## Ce qui NE fonctionne PAS
|
||||
|
||||
| Tentative | Résultat obtenu | Raison de l'échec |
|
||||
|-----------|------------------|--------------------|
|
||||
| `-c:v copy` → ré-encodage `libx264` sur le concat final (step 7) | Toujours 107s, 2089 frames, `avg_frame_rate` aberrant | Le ré-encodage de sortie n'agit qu'*après* le concat ; le demuxer `concat` a déjà assigné des PTS incohérents aux paquets avant qu'ils n'atteignent l'encodeur |
|
||||
| Ajout de `-fps_mode cfr` sur le concat final (sans re-normaliser l'outro en amont) | Framerate propre (`24/1`) mais durée **toujours 107s**, frame count monté à 2571 | `-fps_mode cfr` force un framerate constant mais rééchantillonne sur la timeline déjà corrompue (107s) → étire/duplique des frames au lieu de corriger la durée |
|
||||
| `-fps_mode cfr` sur le step 6 (watermark) | Aucun effet sur le bug | Mauvaise étape : le watermark (24fps→24fps, même source) n'a jamais été la cause. Diagnostic confirmé par inspection `ffprobe` de chaque fichier intermédiaire (`_base`, `_muxed`, `_sub`, `_wm`) : les quatre sont propres (24fps constant, frame count cohérent) jusqu'au concat outro inclus |
|
||||
|
||||
## Solution validee
|
||||
|
||||
Aligner le framerate de l'outro sur celui du footage **avant** qu'il n'entre dans le
|
||||
concat demuxer, pas après. Dans `assemble_iakifech.py`, step 7 :
|
||||
|
||||
```python
|
||||
def get_video_fps(path):
|
||||
"""Get the r_frame_rate of a file's first video stream (e.g. '24/1')."""
|
||||
r = subprocess.run(
|
||||
["ffprobe", "-v", "quiet", "-select_streams", "v:0",
|
||||
"-show_entries", "stream=r_frame_rate",
|
||||
"-of", "default=noprint_wrappers=1:nokey=1", path],
|
||||
capture_output=True, text=True,
|
||||
)
|
||||
return r.stdout.strip()
|
||||
|
||||
# Step 7, génération de l'outro_audio : probe le fps du footage réel (pas de valeur
|
||||
# codée en dur), puis force l'outro sur ce même fps AVANT le concat.
|
||||
footage_fps = get_video_fps(footage_path) or "24/1"
|
||||
run_ffmpeg(["ffmpeg", "-y", "-i", outro_path, "-f", "lavfi",
|
||||
"-i", "anullsrc=channel_layout=stereo:sample_rate=44100",
|
||||
"-r", footage_fps, "-fps_mode", "cfr",
|
||||
"-c:v", "libx264", "-preset", "fast", "-crf", "20", "-pix_fmt", "yuv420p",
|
||||
"-c:a", "aac", "-shortest", outro_audio],
|
||||
"outro audio (framerate aligne sur le footage avant concat)")
|
||||
```
|
||||
|
||||
Le concat final (déjà ré-encodé depuis le patch précédent) reste inchangé — il n'était
|
||||
pas le problème, juste insuffisant seul.
|
||||
|
||||
## Verification
|
||||
|
||||
```bash
|
||||
ffprobe -v error -show_entries format=duration:stream=codec_type,nb_frames,r_frame_rate,avg_frame_rate,duration \
|
||||
-of default=noprint_wrappers=0 iakifech_ep02_v13.mp4
|
||||
```
|
||||
|
||||
R©sultat attendu (obtenu sur Ep02 v13) : `r_frame_rate=24/1`, `avg_frame_rate=24/1`,
|
||||
durée vidéo/audio cohérentes à ~0.1s près (85,75s vidéo / 85,76s audio), pas de
|
||||
fraction aberrante.
|
||||
|
||||
**Vérification visuelle obligatoire en complément** (règle B-roll actée post-Ep02) :
|
||||
extraction de frames autour de la transition footage→outro (~80s) et en fin de vidéo
|
||||
pour confirmer l'absence de glitch introduit par la conversion de framerate — un fondu
|
||||
sombre bref à la transition est normal (déjà documenté comme faux-positif sur un
|
||||
précédent QA), un gel ou une frame dupliquée anormalement longue ne l'est pas.
|
||||
|
||||
## Pieges specifiques
|
||||
|
||||
- Un ré-encodage de la **sortie finale seule** ne corrige jamais un mismatch de
|
||||
framerate/timebase introduit par le demuxer `concat` — il faut normaliser **chaque
|
||||
segment en amont** du concat, avant que leurs PTS ne soient recollés.
|
||||
- `-fps_mode cfr` sans normalisation préalable peut masquer le symptôme (framerate
|
||||
metadata propre) tout en aggravant le fond du problème (durée toujours fausse, frame
|
||||
count gonflé par duplication).
|
||||
- Isoler la vraie étape fautive nécessite d'inspecter `ffprobe` sur **chaque fichier
|
||||
intermédiaire**, pas seulement input/output — ici les 4 premières étapes (base, mux,
|
||||
sous-titres, watermark) étaient toutes propres ; ne pas supposer qu'une étape est
|
||||
coupable sans la vérifier isolément.
|
||||
- Réutiliser la voix ElevenLabs et les sous-titres déjà générés (assets validés, non
|
||||
modifiés depuis le run précédent) pour reproduire/valider le fix évite de regaspiller
|
||||
des crédits API sur un problème qui est purement côté ffmpeg.
|
||||
|
||||
## References
|
||||
|
||||
- Script : `/data/nyora/ia-tn/assemble_iakifech.py` sur hermes-nabil (VPS Contabo)
|
||||
- Backups des tentatives précédentes conservés : `assemble_iakifech.py.bak_20260724`,
|
||||
`assemble_iakifech.py.bak_20260728_222442_pretendu_fix_concat_outro`
|
||||
- Voir aussi [IAKifech ep.1 — postmortem production vidéo](iakifech-ep1-postmortem-production-video.md)
|
||||
Reference in New Issue
Block a user