Files
nas-runbooks/hermes-nyora/iakifech-duree-outro-fps-mismatch.md
T

6.3 KiB

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 :

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

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