Communitygithub.com

0xSero/video-edit

Nettoie un enregistrement brut d'écran / OBS / talk pour en faire une vidéo professionnelle et concise : coupes basées sur la transcription, suppression des blancs et des plans visuellement statiques, masquage des moments personnels et des fuites d'écran, amélioration audio, ouverture percutante, rendu vérifié, puis chapitres, titre, tags, description, sous-titres et miniature livrés dans ~/Téléchargements et ouverts. À utiliser lorsque l'utilisateur dit « édite la vidéo que j'ai enregistrée », « coupe les silences », « supprime les parties gênantes », « assure-toi qu'il n'y a pas de fuite », « rends-la prête pour YouTube ». Pas pour créer des vidéos promotionnelles ou motion graphics à partir de diapositives ; les miniatures seules vont dans youtube-pack.

Qu'est-ce que video-edit ?

Cette compétence est conçue pour les agents IA comme Claude Code, Cursor ou Codex qui doivent éditer automatiquement un enregistrement vidéo brut (écran, OBS ou talk) en une vidéo soignée et professionnelle, prête à être publiée sur YouTube ou ailleurs. L'agent orchestre un pipeline complet : transcription Whisper (mlx_whisper), amélioration audio (DeepFilterNet3), analyse de changement de plan (frame-difference), détection et floutage OCR des fuites de données (IP, clés API, e-mails), masquage des moments privés détectés par vision (main près du visage, autre personne, absence), puis montage vidéo accéléré par matériel (h264_videotoolbox), vérification automatique (comptage d'images, absence de fuite dans la sortie, piste audio intacte), et enfin génération de métadonnées (chapitres, titres, tags, description, sous-titres SRT) et d'une miniature via youtube-pack. La sortie est livrée dans ~/Téléchargements et ouverte. La compétence insiste sur la fiabilité : elle ne touche jamais à la source, vérifie chaque étape avec verify_output.py, et gère les échecs connus (fenêtre de flou, OCR côté sortie, re-transcription après coupe). Elle se compose avec d'autres compétences comme youtube-pack pour l'upload final.

Compatible avec~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/0xSero/video-edit/tree/HEAD

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

É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 OBS YYYY-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 : ffmpeg 6+, python3, mlx_whisper, DeepFilterNet3, Pillow/numpy/soundfile, Apple Vision (pyobjc-framework-Vision/-Quartz).

Étapes

  1. Reconnaissance, ne jamais toucher à la source. ffprobe <src> (résolution, fps, audio). Travaillez uniquement à partir de copies/extractions dans <workdir>.
  2. 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), et transcript.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 – lancez df_enhance.py orig48.wav df_enhanced.wav (DeepFilterNet3, ~6 min CPU) MAINTENANT, c'est indépendant.
  3. Lire l'intégralité de la transcription (3 morceaux via transcript_txt.py ... --from/--to). Écrivez les plages à conserver (secondes source) dans job.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.
  4. 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 le silencedetect brut.
  5. 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é.
  6. Analyse des fuites (s'exécute pendant que vous lisez). ocr_scan.py scan après run sur frames/ : 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 (blur window + blur_regions, en pixels source) pour la fenêtre – les boîtes par ligne manquent le texte entre les échantillons. 127.0.0.1/localhost sont corrects. Enregistrez chaque fenêtre dans job.json.
  7. Coupures de confidentialité (webcam). cam_flags.py (main près de la bouche via Vision) + cam_flags.py --sheet S:DUR agrandi à 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.
  8. Les coupes temporelles de l'utilisateur sont littérales. « coupe 0000 - 01:12 » -> mettez-le dans job.cuts (ou keep), appliquez exactement, puis revérifiez le rythme autour de la jointure.
  9. Master audio. Vérification : corrélation amélioré-vs-original > 0,95 (df_enhance.py l'imprime). La audio_chain par 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 terme equalizer ; render.py effectue la loudnorm en deux passes vers -16 LUFS / -1,5 dBTP. Le micro intact reste comme piste audio 2.
  10. 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 : encodages h264_videotoolbox parallè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).
  11. Vérifiez avant de livrer. verify_output.py se 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 --full pour un balayage complet des fuites du fichier lorsque le matériel est sensible.
  12. 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.
  13. 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échargements et ouvrez le 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.py imprime 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.
  • ffprobe du 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/cp avec le bac à sable désactivé.
  • Le filtre ffmpeg meurt (« Impossible d'allouer de la mémoire ») au-delà d'environ 100 termes between() -> réduisez render_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.py non-concordance d'images -> il refuse de concaténer ; lisez render_<n>.log (-ss avant une image non-clé, décodeur cassé).
  • Whisper encore en cours lorsque vous lisez transcript.json -> transcript_txt.py signale des segments vides ; attendez la fin de whisper.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.

Skills associés