Communitygithub.com

real-sfx

Conception sonore pour vidéos animées avec de véritables sons enregistrés provenant des bibliothèques de l'utilisateur (un pack principal trié de whooshes, hits, risers, pops, carillons, frappes au clavier, bruitages, ambiances ainsi que des bibliothèques de secours) et des signaux UI de uisfx, jamais synthétisés.

Qu'est-ce que real-sfx ?

real-sfx est une compétence de conception sonore orientée vers les vidéos animées, les screencasts et les animations UI, qui garantit que tous les effets sonores proviennent de véritables enregistrements—jamais de sons synthétisés. Elle s'intègre dans un pipeline plus large (comme Video Director ou un workflow autonome) et peut lire les listes d'événements d'un projet, analyser des scripts de synthétiseur, extraire des moments à partir d'enregistrements d'écran ou même détecter les changements visuels dans une vidéo. Le système sélectionne les sons appropriés parmi les bibliothèques de l'utilisateur (y compris uisfx pour les signaux d'interface), les place précisément sur les images correspondantes, préserve la musique et la voix existantes, et remplace toute synthèse intégrée pour éviter les doublons. La sortie comprend une nouvelle vidéo MP4, une piste audio SFX WAV distincte, un rapport de repérage et un tableau de bord d'auto-critique. Cette compétence fonctionne avec Python et nécessite ffmpeg, ainsi que les bibliothèques audio et les index de l'utilisateur. Elle est utile chaque fois que l'utilisateur demande des effets sonores (SFX), des bruitages, des sons d'interface utilisateur, ou souhaite remplacer des sons synthétiques par des sons réels, ou lorsqu'il se plaint que l'audio semble générique ou désynchronisé.

Compatible avec✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/SallyRS/video-director/tree/HEAD/skills/video-director/real-sfx

Demander à votre IA préférée

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

Documentation

real-sfx : des sons réels pour une vidéo animée

L'objectif : le film sonne comme si une personne disposant d'une bonne bibliothèque l'avait monté. Donc :

  • Le son n'est jamais synthétisé. Sources : les bibliothèques de l'utilisateur (config.json) et uisfx (un pack CC0 prêt à l'emploi de signaux d'interface, lui-même synthétisé : la seule exception, uniquement pour les moments d'interface ; "aucune synthèse" le désactive : --ui library). Aucun son adapté : le moment reste silencieux et est consigné dans le rapport. Cela remplace "aucune piste : synthétiser" des standards motion-standards.
  • Vous ne pouvez pas entendre. Le son est lu sous forme de chiffres, de mots et d'images (references/listening.md). Ne présentez pas une sélection comme ayant été écoutée : dites ce qui a été vérifié visuellement et par mesure, et ce que l'utilisateur devrait écouter.
  • Conservez la musique et la voix lorsqu'elles portent le film. Le résultat est toujours une nouvelle MP4 et une piste WAV séparée.
  • Ne doublez pas. La synthèse intégrée à l'audio du rendu est remplacée par les vrais sons, et non superposée en dessous (étape 1). La critique mesure cela sous forme de nombre (l'axe doubling).
  • Ne modifiez ni le projet ni le dossier de la compétence. Placez tous les fichiers de travail dans votre propre dossier (work/, result/).

À l'intérieur de Video Director

(Ajouté dans la copie de Video Director ; absent de l'original de Clipwing. UPSTREAM.md liste chaque modification.) Cette copie réside dans la compétence Video Director et est exécutée par son étape Sound : ../references/sound-stage.md, "Sound engineering". Ces étapes décident quels moments reçoivent un son, ne transmettent à cette compétence que ceux-ci (build/audio/sfx/events.json), épinglent les enregistrements choisis par l'utilisateur (sound_handoff.py pins), l'exécutent avec --ui library, --no-loudnorm et sans couche de texture ni fond sonore, et ne récupèrent que la piste d'effets et les repères résolus (sound_handoff.py collect). Suivez-les, et lisez ce fichier uniquement pour les options qu'elles ne couvrent pas. Définissez REAL_SFX_CONFIG, REAL_SFX_INDEX, REAL_SFX_TASTE, REAL_SFX_RATINGS, REAL_SFX_STEADY et REAL_SFX_STYLES vers des chemins sous ~/.config/real-sfx/ (le plugin installe chaque version dans un nouveau dossier, donc tout ce qui est écrit ici est laissé lors de la prochaine mise à jour), et n'utilisez pas --remember, qui écrit dans ce dossier (tout comme learn_style.py : copiez un style appris dans ~/.config/real-sfx/styles/).

Chemin rapide

D'abord python scripts/setup.py check (ffmpeg, bibliothèques principale/supplémentaires, index, uisfx) et python scripts/look.py FILM.mp4 --out work/look (images avec le temps + le son original en dessous). Ensuite, selon ce que vous avez :

# 1. le projet a une liste d'événements (docs/cues.json, scripts/cues.json) OU un script qui synthétise son son (audio.cjs)
python scripts/from_cues.py PROJECT_FOLDER|docs/cues.json --video RENDER.mp4 --out work/cues.json
# 2. enregistrement d'écran sans liste : ui_events.py ... (references/screencast.md), puis from_cues.py work/ui/events.json
# 3. image uniquement :                    find_moments.py FILM.mp4 --out work/moments; suggest_cues.py work/moments/moments.json --out work/cues.json
# 3b. ANIMATION DOUCE COLORÉE sans liste (aperçu UI, illustration, graphiques animés) : l'automatisation voit 5-6 mouvements sur 40.
#     étape 2, "Animation silencieuse sans liste" : find_moments.py FILM --out work/moments --fine; look.py FILM --at T --span 2.4
#     --step 0.1 --out work/at.png; VOTRE PROPRE liste d'événements à partir des images (references/typed-cues.md) -> from_cues.py - --ui library
python scripts/mix.py work/cues.json --out result/film_sfx.mp4 --plan     # quoi va où ; puis sans --plan
python scripts/critique.py result/film_sfx_resolved_cues.json result/film_sfx_sfx_track.wav
python scripts/levels.py   result/film_sfx_resolved_cues.json result/film_sfx_sfx_track.wav --json work/edits.json
# un film dont le son est UNIQUEMENT des SFX (pas de musique ni de voix propre) : petits sons dans les trous, puis mix.py à nouveau (étape 4, "Couche de petits sons")
python scripts/texture.py work/cues.json --moments work/moments/moments.json
# le même film : un fond sonore (un long enregistrement réel sombre sous tout le film ; étape 4, "Fond sonore"), puis mix.py à nouveau
python scripts/bed.py work/cues.json [--list]
# chiffres contre neuf bobines SFX finies (étape 6, "Contre la référence") : pas de scores, n'affecte pas le verdict
python scripts/critique.py RESOLVED.json WAV --style clean-sfx-refs
# oreilles humaines à moindre coût (étape 6) : une page avec les questions de la critique et un verdict en un clic ; le modèle de masquage
python scripts/listen_page.py build work/listen --moments result/film_sfx.mp4 --critique RESOLVED.json WAV
python scripts/listen_page.py serve work/listen [--lan]        # puis : listen_page.py results work/listen --log
python scripts/mix.py work/cues.json --out result/film_sfx.mp4 --masking        # quels sons le reste cache (nécessite le venv)

Un dossier de projet trouve sa propre liste d'événements (docs/, scripts/, assets/) ; le script du synthétiseur n'est lu que lorsqu'il n'y a pas de liste. Choisissez tous les indicateurs de from_cues.py avant de modifier la feuille : l'exécuter à nouveau efface les modifications manuelles (puis sheet.py apply). Voix dans le film : mix.py ... --voice-safe (profondeur normal ; --voice-depth light lorsqu'il y a de nombreuses textures silencieuses, deep uniquement pour les sons rares dans les pauses : il retire complètement l'interface du mix). La musique porte le film : --duck. Loudness : une base reconstruite correspond à l'original par défaut ; votre propre : --target-lufs NUMBER. Pas d'index, ou les bibliothèques ont été déplacées : python scripts/build_index.py, puis python scripts/listen.py tag-index. Pas d'uisfx : setup.py init --uisfx. Un autre ordinateur : setup.py scan FOLDER, setup.py add-library NAME PATH [--tier main|extra] --index. Exécutez les scripts depuis le dossier de la compétence ; mettez entre guillemets les chemins avec des espaces ou des caractères non latins ; votre propre Python avec des chemins non latins sous Windows : PYTHONUTF8=1. Dans PowerShell, les guillemets cassent les arguments JSON : mettez-les dans un fichier.

D'où viennent les sons

Ce qui est nécessaireD'où cela vient
La base : whooshes, hits, risers, pops, carillons, touches, papier, bruitages, ambiancela bibliothèque principale (tier: main, chemin dans config.json). Un pack trié avec catalog.json / catalog.csv donne à chaque son son type et son enregistrement source, ce qui évite de deviner à partir des noms de fichiers
Ce qui manque à la bibliothèque principale : chutes graves, pièces de monnaie, petits glitchsbibliothèques de secours (tier: extra, marquées ~ dans les résultats) : uniquement lorsque la bibliothèque principale a moins de trois sons adaptés
Packs conçus avec leurs propres rôlesles rôles granular, atmosphere, power, music_transition, voice ne sont jamais demandés par la sélection automatique : prenez-les explicitement (--role, "pick": {"role": ...})
Un moment d'interface : clic, tic, fenêtre, notificationuisfx (--ui auto) lorsque la liste elle-même nomme les types d'interface (clic, carillon...) : from_cues dit pourquoi et où (routes: key -> library:click, pop -> uisfx:select)
Frappe au claviertoujours le vrai clavier de la bibliothèque, même avec --ui auto ; une séquence de 8+ événements click espacés de 35 à 170 ms est reconnue comme une frappe par from_cues lui-même (--no-typing-detect)
Contact physique : balle, pas, perle, objettoujours la bibliothèque : une balle sur le sol fait un bruit sourd, pas un select (recette ci-dessous)

Pas encore de bibliothèque : setup.py init --uisfx seul donne 78 signaux UI CC0. Sources gratuites d'enregistrements réels qui valent la peine d'être vérifiées (lisez chaque licence) : Freesound (filtre CC0), ensembles Sonniss GDC, Mixkit, Pixabay effets sonores.

"De ma bibliothèque", "aucune synthèse" ou "sons synthétiques" : --ui library. Un accent sur le logo ou un "cha-ching" dans un projet avec des sons d'interface uisfx : --from-library pop,bell (noms de types de la liste) ; pour un seul son : sheet.py set --at T --label bell id=65. Sous une musique tonale :

  • les pas de hauteur des répétitions d'uisfx et des sons tonaux de la bibliothèque (carillon, pop, verre, pièce) se désactivent automatiquement lorsque le projet a une partition (--ui-pitch off|cycle) ;
  • la hauteur d'un son réel est accordée aux notes de la musique : mix.py prend la music_ref de la feuille (le fond sans effets, la piste de musique) ou --music-ref FILE et décale un son tonal par demi-tons entiers jusqu'à 2 plus les cents qui le mettent sur une note (2,5 au total), si cela le met sur une note ; le bruit est laissé intact (--no-tonal-fit ; scripts/tonal.py SOUND --music FILE --at T montre les notes) ;
  • les intervalles des fréquences propres à l'auteur (tick(t, 1800 * 2 ** (4 * i / 12))) deviennent les pas de hauteur du remplacement (melody:).

Flux de travail

1. Qu'y a-t-il déjà dans le son

look.py montre le spectrogramme du son natif (la voix est des bandes de phrases, la musique un tapis avec un battement, le silence est noir) ; listen.py voice FILM.mp4 donne la part de parole et de musique. Trois cas :

  • La musique ou la voix de l'auteur : elles restent, les SFX vont par-dessus (--duck / --voice-safe). Exception (réponse d'une personne sur un vrai film, 2026-10-19) : le film a été envoyé "pour être sonorisé", son son natif est uniquement de la musique (listen.py voice : parole 0 %), et la personne le veut sans la musique, comme ses propres bobines SFX propres. Faites une version sans musique (from_cues.py ... --ui library --drop-original, puis bed.py --id ... --level -46 avec une ambiance favorite), et une version avec musique si utile, et dites laquelle est laquelle. Dans un choix aveugle de trois (original / effets sur musique / effets seuls) la personne a choisi la dernière sans une seule plainte. from_cues imprime BAKED: sur un tel film bien qu'il n'y ait pas de synthèse intégrée (parole 0 %, musique 84 %, les attaques ne correspondent pas aux événements : 7 % contre 9 % par hasard) : c'est une fausse alerte.
  • Synthèse intégrée dans la piste (le projet a été écrit pour une partition synthétisée) : les vrais sons par-dessus créent un doublon. from_cues.py le vérifie lui-même (BAKED:, unbake:) et supprime la synthèse de la base sans toucher à la musique et à la voix ; comment exactement, et que faire si le script échoue ou si la synthèse se trouve dans la piste musicale (--extra-synth) : references/project-audio.md (lisez-le dès que la sortie a BAKED, WARN stems, unbake: not possible, ou que le projet synthétise son son avec un script). Après la construction, critique.py imprime l'axe doubling : la corrélation de la couche avec l'original et avec le nouveau film (devrait être d'environ 0).
  • Le son des clips joués dans une fenêtre d'enregistrement d'écran : natif, reste ; les événements à l'intérieur de ces fenêtres sont ignorés.

2. Trouver les moments (de la meilleure source à la pire)

  • La liste d'événements du projet ou le script du synthétiseur → from_cues.py (ci-dessous). En détail : references/typed-cues.md.
  • Un enregistrement d'écran → references/screencast.md (ui_events.py régions, correspondance des frappes avec les caractères, son du clip).
  • HyperFrames avec data-start et sans liste : from_hyperframes.py PROJECT --out work/moments.json. "1 moments" avec 18 éléments signifie que le mouvement ne suit pas data-start : cherchez un script de synthétiseur.
  • Vidéo uniquement : find_moments.py FILM --out work/moments [--roi x,y,w,h] [--from A --to B] [--fine] ; types cut, burst, onset, settle (settle se déclenche aussi sur une image vide ou une boucle au repos : regardez l'image) ; look.py --moments ... dessine les images des moments. Squelette : suggest_cues.py (references/recipes.md) ; une ébauche est un début, pas une réponse. --fine pour l'animation douce colorée (dégradés, lueurs, formes pastel qui changent de couleur plutôt que de luminosité) : il lit aussi les changements de chrominance, les moments ont src=chroma|luma ; sur trois tels films, il trouve 33 à 69 % des événements qu'un agent a notés à partir des images (à moins de 80 ms), contre 13 à 25 % avec la seule luminosité ; 3 à 4 fois plus de candidats (15 à 25 par 10 s). Ce sont des candidats : les images décident.
  • Sous la musique : beats.py FILM --out work/beats.json --plot work/beats.png ; avec usable: true, mix.py --snap-beats (±50 ms). La grille est vérifiée par rapport à la grosse caisse (la bande basse < 125 Hz séparément) : elle imprime combien de battements ont atterri sur une grosse caisse en moins de 40 ms. Une grille à côté de la grosse caisse (le tracker s'est posé sur les charlestons, "0,22 s de décalage") est déplacée dessus ; une grille qui n'atterrit sur rien reçoit usable: false, et --snap-beats l'ignore. --plot dessine la bande, les grosses caisses (marques vertes) et la grille (lignes rouges) : les marques sont sur les lignes, ou ne faites pas confiance à la grille. Si la musique est à vous et peut être adaptée à l'image : beats.py FILM --suggest-offset work/moments.json dit de combien décaler la musique pour que les coupures et les impacts atterrissent sur les battements (conseil uniquement ; la musique n'est pas touchée).

from_cues.py : python scripts/from_cues.py LIST|PROJECT_FOLDER|SCRIPT.cjs|- --video RENDER.mp4 --out work/cues.json (- lit la liste depuis l'entrée standard ; un BOM de PowerShell est compris). Ce qu'il fait et dit par lui-même :

  • est-ce le bon rendu : la liste manque l'image (VERDICT) ; une liste en phase de conception contre un rendu chronométré par rapport à la voix : une carte temporelle à partir des ancres du projet (timing.json avec a...

[...tronqué pour la traduction]

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Skills associés