Édition vidéo (enregistrement d'écran / OBS / talk)
Kit de scripts : scripts/ dans cette compétence (prep.sh, transcript_txt.py, ocr_scan.py,
cam_flags.py, df_enhance.py, build_edl.py, render.py, verify_output.py,
chapters.py, overview.py, job.example.json, selftest.sh). Exécutez-les depuis une copie dans
<workdir>/scripts/ pour qu'un travail ne dépende jamais du répertoire de la compétence. scripts/selftest.sh prouve
une installation de bout en bout en quelques minutes.
Entrées
<src>: l'enregistrement, généralement le plus récent de~/Desktop/*.mov(nom OBSYYYY-MM-DD HH-MM-SS.mov). S'il existe plusieurs enregistrements récents, confirmez lequel AVANT de démarrer le long pipeline – éditer la mauvaise vidéo fait perdre une heure.<target_minutes>: demandez si non fourni ; typiquement 20-30 à partir d'une source de 45-90 min.<workdir>: répertoire de travail temporaire, par ex./tmp/<session>/edit.- Chaîne d'outils :
ffmpeg6+,python3,mlx_whisper, DeepFilterNet3, Pillow/numpy/soundfile, Apple Vision (pyobjc-framework-Vision/-Quartz).
Étapes
- Reconnaissance, ne jamais toucher à la source.
ffprobe <src>(résolution, fps, audio). Travaillez uniquement à partir de copies/extractions dans<workdir>. - Préparation.
prep.sh "<src>" $W:orig48.wav,mono16.wav,frames/(1 toutes les 2 s),camall/(recadrage webcam à 1 fps, géométrie dérivée automatiquement de la résolution),sheet_overview.jpg,silences_raw.txt(diagnostic uniquement), ettranscript.json(mlx_whisper large-v3-turbo, timestamps par mot, ~4 min). Whisper continue de s'exécuter en arrière-plan après le retour de prep – lancezdf_enhance.py orig48.wav df_enhanced.wav(DeepFilterNet3, ~6 min CPU) MAINTENANT, c'est indépendant. - Lire l'intégralité de la transcription (3 morceaux via
transcript_txt.py ... --from/--to). Écrivez les plages à conserver (secondes source) dansjob.json -> keep. Le rognage du silence est mineur (~2 sur 47 min) ; les vraies minutes proviennent des décisions de contenu. Whisper s'auto-informe : une phrase répétée 10 fois ou plus, ou des segments vides = de l'air mort, coupez. - Passe visuelle statique. « Rien ne se passe » est souvent visuellement statique, PAS silencieux. Différence d'image sur les images à 0,5 fps : <1 % de pixels changés sur une fenêtre d'environ 10 s = inactif ; fusionnez les segments séparés par des à-coups <=1 s ; nécessite >=4 s pour couper ; poignées de 0,5 s. Les curseurs clignotants / spinners simulent une activité – masquez ou augmentez le seuil ; vérifiez les images intermédiaires pour les rafales de changement-et-retour. La frappe est du bruit, pas du silence : les portes utilisent RMS sur la piste améliorée (
pause.loud_db), jamais lesilencedetectbrut. - Ouverture. Coupez tout ce qui précède le premier contenu réel. Si le début est lent/ennuyeux, commencez par la démo la plus intéressante ; optionnellement, une ouverture à froid avec 1-2 clips excitants puis un accéléré de l'intro. Ne commencez jamais sur un fond d'écran/noir – un début saccadé de 30 s donne l'impression d'une vidéo de mauvaise qualité.
- Analyse des fuites (s'exécute pendant que vous lisez).
ocr_scan.py scanaprèsrunsurframes/: IPv4/v6,*.ts.net, e-mails, clés API, matériel SSH. Passe dense à 2 fps sur chaque plage terminale/config chargée (ocr_scan.py dense src.mov dense 600:60 ...). Texte statique ->boxes(remplissage uni) ; sortie de terminal défilante -> floutez tout le volet (blurwindow +blur_regions, en pixels source) pour la fenêtre – les boîtes par ligne manquent le texte entre les échantillons.127.0.0.1/localhostsont corrects. Enregistrez chaque fenêtre dansjob.json. - Coupures de confidentialité (webcam).
cam_flags.py(main près de la bouche via Vision) +cam_flags.py --sheet S:DURagrandi à 2 fps des feuilles de chaque groupe signalé. Coupez les moments que l'utilisateur ne publierait pas : main au visage pendant une pause, quitter le bureau, une autre personne dans le cadre, segments de visage plein écran. Les poses de réflexion ordinaires et les petits gestes sont corrects. Ne coupez JAMAIS au milieu d'une phrase pour un geste – accrochez-vous à la limite de phrase la plus proche et notez ce qui a été perdu. - Les coupes temporelles de l'utilisateur sont littérales. « coupe 0000 - 01:12 » -> mettez-le dans
job.cuts(oukeep), appliquez exactement, puis revérifiez le rythme autour de la jointure. - Master audio. Vérification : corrélation amélioré-vs-original > 0,95 (
df_enhance.pyl'imprime). Laaudio_chainpar défaut est highpass 75, coupures/boosts autour de 220 Hz / 3,2 kHz / 9 kHz, dé-esseur, compresseur 3:1 ; atténuez tout bourdonnement de ventilateur persistant en ajoutant un termeequalizer;render.pyeffectue la loudnorm en deux passes vers -16 LUFS / -1,5 dBTP. Le micro intact reste comme piste audio 2. - EDL + rendu.
build_edl.py->segments.json(pauses >0,7 s dans les conservées réduites à 0,4 s ; alignées sur la fréquence d'images sondée ; <0,3 s supprimées).render.py: encodagesh264_videotoolboxparallèles groupés, concaténation-c copy, multiplexage des deux pistes. Il est redémarrable par groupe – si un groupe échoue, corrigez et relancez, les groupes inchangés sont ignorés. Livrez en 1080p sauf demande contraire (la 4K double le temps de rendu pour rien). - Vérifiez avant de livrer.
verify_output.pyse termine par un code non nul sauf si le nombre d'images correspond à l'EDL, les deux pistes audio correspondent à la durée vidéo, et l'OCR de la sortie à 4 fps sur chaque fenêtre de masquage ne trouve aucune fuite. Extrayez également les images de sortie à chaque coupure de confidentialité et à 0:00-1:00 et REGARDEZ-les. Utilisez--fullpour un balayage complet des fuites du fichier lorsque le matériel est sensible. - Re-transcrivez le nouveau montage. La transcription, les sous-titres et les chapitres doivent correspondre à la chronologie de la SORTIE, pas à celle de la source – ré-utilisez Whisper sur le montage (ou
chapters.py, qui remappe via l'EDL) avant d'écrire SRT/chapitres. Ne livrez jamais d'horodatages SRT provenant de la transcription source. - Métadonnées + livraison. Sans qu'on vous le demande deux fois : horodatages des chapitres (
chapters.py, >=3, premier à 0:00), 2-3 options de titre, ~30 balises sous 500 caractères (+2 variantes de balises/description si demandé), description, SRT par langue (~42 caractères/ligne ; multilingue sur demande), le tout en texte brut. Miniature via youtube-pack : lisez les 10 dernières miniatures de l'utilisateur pour le style ; fond blanc/crème par défaut + texte noir, pas de visage sauf demande, logos/texte grands et dégagés. Déplacez ensuite<output>.mp4(et les SRT/métadonnées) vers~/Téléchargementsetouvrezle fichier / ouvrez le dossier dans l'application par défaut.
Sorties
<Sujet> - AAAA-MM-JJ - edit.mp4(1080p, 2 pistes audio) dans~/Téléchargements, ouvert dans l'application par défaut.<workdir>:job.json,segments.json,group_bounds.json,vf_<n>.txt, journaux de masquage/confidentialité.~/Téléchargements: SRT,metadata.txt(titres, description, balises, chapitres).- Optionnel sur demande : sous-vidéos thématiques extraites de la même source, chacune avec ses propres chapitres.
Se compose avec
whisper/DFN3 (dans le kit) -> video-edit (mp4 vérifié dans ~/Téléchargements) -> youtube-pack (thumbnail.png) -> téléchargement dans le navigateur vers YouTube Studio configuré comme les autres vidéos de l'utilisateur.
Règles
- Ne modifiez jamais l'enregistrement source.
- La durée cible est un objectif ; si le contenu ne peut pas être réduit sans vider le talk, livrez légèrement au-dessus et nommez les deux prochaines coupes.
- Coupez les digressions entières avant de rogner plus de pauses ; conservez les discussions techniques, les démos en direct, les avertissements honnêtes, le récapitulatif.
- Terminez toujours par : déplacer vers ~/Téléchargements + ouvrir.
- Rapportez fidèlement : vous ne pouvez pas entendre le résultat – dites-le et pointez la piste 2.
- L'audio enregistré séparément (Discord/Craig) n'existe généralement pas ; vérifiez Bureau/Téléchargements/iCloud/Mémos vocaux, s'il est absent, utilisez le micro OBS et dites-le.
- Lorsqu'on vous demande de libérer de l'espace : supprimez les anciens brouillons/variantes non acceptés, conservez la source et la version finale.
- Podcasts multi-personnes : trouvez les BONNES pistes audio (généralement 2 sur plusieurs), associez l'audio au bon orateur, alternez la vidéo avec la personne qui parle, transitions propres.
- Ne prétendez jamais que l'édition est terminée parce que le rendu est fini ; seul
verify_output.py+ inspection visuelle des images le confirment.
Vérification
verify_output.pyimprime PASS (nombre d'images, deux pistes audio, aucune fuite dans les fenêtres) et se termine avec 0.- Images inspectées visuellement à 0:00-1:00 et à chaque coupure de confidentialité (
verify_output.py --sheet 0:60). - Vérification ponctuelle de la re-transcription SRT par rapport au montage.
ffprobedu fichier livré : durée, résolution, fps, 2 flux audio.
Échecs connus
- Mauvaise vidéo éditée -> confirmez la correspondance sujet/plus récent avant le pipeline.
- Sous-titres/chapitres sur la chronologie source -> re-transcrivez après la coupe (étape 12).
- Nom d'hôte visible dans la sortie -> texte défilant entre les échantillons OCR ; floutez tout le volet, élargissez la fenêtre, puis OCR côté sortie.
- Silencedetect coupe la frappe/la lecture vidéo -> utilisez la porte sur le RMS audio amélioré (
pause.loud_db), pas le silence seul. - Ouverture noire saccadée -> vérifiez les images de la sortie 0:00-1:00, ouvrez à froid sur du contenu réel.
- Invite de
cp -i/ blocage TCC du bac à sable sur~/Téléchargements-> utilisez/bin/cpavec le bac à sable désactivé. - Le filtre ffmpeg meurt (« Impossible d'allouer de la mémoire ») au-delà d'environ 100 termes
between()-> réduisezrender_groups. - Le curseur clignotant compte comme une activité dans la différence d'image -> masquez/ajustez le seuil, vérifiez les images intermédiaires.
render.pynon-concordance d'images -> il refuse de concaténer ; lisezrender_<n>.log(-ssavant une image non-clé, décodeur cassé).- Whisper encore en cours lorsque vous lisez
transcript.json->transcript_txt.pysignale des segments vides ; attendez la fin dewhisper.log.
Exemples
- Talk du 2026-09-02, 47 min -> 26 min : 32 plages conservées, 2 coupures de confidentialité (9:52-9:58, 26:08-26:14), 2 fenêtres de flou + 1 boîte pour un nom d'hôte
*.ts.net, rendu ~2 h temps réel, fuite détectée uniquement par l'OCR côté sortie. - Session d'enseignement OBS du 2026-09-24 : l'utilisateur a rejeté le premier montage (« bruit de fond, frappe, début très ennuyeux ») -> a supprimé le bruit de frappe, choisi une meilleure ouverture, refait les transcriptions, puis coupure littérale de tête
0:00-1:12, analyse des fuites, miniature blanc/crème avec logos plus grands, 2 variantes de métadonnées, déplacé vers Téléchargements. - Podcast (2026-09-18) : vidéo de 1h40 + 5 fichiers audio candidats -> a identifié les 2 bonnes pistes par orateur, mappé la voix à la vidéo, 1080p, rognage de tête, SRT + traductions ES/AR/HI, horodatages de chapitres, miniature avec les deux orateurs, texte en haut, pas de fond noir.