# 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)