Communitygithub.com

block-town

Créez une vidéo verticale « Dans cette ville / Dans ce monde » façon Roblox, de l'idée à un MP4 1080×1920 terminé : règle, script, voix narrative distinctive, monde et personnages construits en code dans Blender et rendus avec Three.js, plans, couche de vie, écrans de téléphone et accessoires, sous-titres karaoké, effets sonores ElevenLabs ou libres, mix vocal stable et fichier musique.

Qu'est-ce que block-town ?

Block Town est un kit de production vidéo complet pour générer des vidéos verticales « Dans cette ville » ou « Dans ce monde » dans le style Roblox. Il guide l'utilisateur à travers sept étapes clés : définition de la règle, écriture du script, enregistrement vocal, conception des décors et accessoires, rendu des images fixes, création d'un extrait d'accroche, puis vidéo complète. Le kit utilise Blender pour construire et animer le monde en code Python (avec une couche de vie pour les mouvements subtils), puis Three.js dans Chrome headless pour le rendu final des images, avant d'assembler le tout avec sous-titres karaoké, voix stabilisée, effets sonores (ElevenLabs ou libres) et musique. Il prend en charge les looks Roblox (têtes rondes, visages anime) et Block (cubes, couleurs unies), et exige que tout soit généré en code, sans réutilisation de contenu tiers. Le kit est conçu pour des vidéos de style viral TikTok/YouTube Shorts, avec des contrôles qualité stricts : rien n'est jamais statique, les tags restent visibles, les écrans ressemblent à de vrais téléphones, et le niveau vocal ne faiblit jamais.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/chihabMe/block-town/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

Block town

Ce dossier est le kit complet : la ville, le casting, leurs déplacements, le moteur de rendu, la voix, les sons, les paramètres musicaux et les étapes allant d'une idée à une vidéo verticale finie. Le dossier de la compétence est le répertoire qui contient ce fichier ; il est appelé SKILL ci-dessous. Les épisodes vivent en dehors (l'utilisateur nomme le dossier), appelé EPISODE ci-dessous. Utilisez des chemins absolus.

À lire avant de construire : docs/ROBLOX_LOOK.md (le monde, le casting, les accessoires, comment les plans sont réalisés), docs/RENDER.md (le moteur de rendu Three.js, la couche de vie, les étiquettes, les écrans de téléphone et les accessoires imprimés), docs/SCRIPT.md (comment l'histoire est écrite), docs/VOICE.md (voix et musique), docs/SOUND.md (effets sonores, ElevenLabs, le mix vocal stable). docs/PROMPTS.md contient un prompt pour chaque étape. docs/GUIDE.md est le manuel original du look Block : la carte, pose(), les mouvements et les règles de la caméra s'appliquent toujours.

Comment une vidéo est fabriquée (depuis ep05)

Blender construit et pose tout à partir du code Python de l'épisode ; Three.js dessine les images finales. Le propre moteur de rendu de Blender est réservé aux fiches de design et aux arrêts sur image.

episode.py ──(Blender : construire la ville, poser chaque image, couche de vie)──> bake : scene.glb + anim.bin + materials.json
           ──(Three.js dans Chrome headless)──> EPISODE/frames/f_####.jpg  (~0,1-0,15 s par image)
           ──(finish.py : sous-titres, voix nivelée, effets sonores, musique)──> EPISODE/<nom>.mp4 et <nom>_music.mp4

Un épisode de 66 secondes prend environ 10-12 minutes des images aux MP4 finis (Blender EEVEE prenait environ 3 heures).

Jamais

  • Pas d'articles du catalogue Roblox, de modèles téléchargés, de séquences, d'histoires ou d'audio provenant d'autres créateurs. Tout ce qui se trouve dans l'image est construit en code ou dessiné par blockworld/pictures.py. Les vidéos virales peuvent être étudiées pour leur savoir-faire, jamais réutilisées.
  • Pas d'appels API payants sans l'accord de l'utilisateur. Fish Audio (voix) et ElevenLabs (effets sonores) coûtent de l'argent : dites d'abord combien coûtera une exécution. sfx_gen.py vérifie les crédits restants et s'arrête avant la réserve ; ne jamais augmenter la réserve ni boucler les générations pour « réessayer » sans demander. Demandez avant de télécharger quoi que ce soit.
  • Pas de musique ni d'extraits de voix de référence dans ce kit. Musique uniquement à partir d'un fichier fourni par l'utilisateur, et uniquement dans la copie _music.mp4. Si ce fichier a été extrait de la vidéo d'un autre créateur, dites clairement que le _music.mp4 ne doit pas être publié : publiez le <nom>.mp4 propre et ajoutez la chanson dans le sélecteur de son de TikTok.
  • Ne modifiez pas les huit personnages récurrents (couleurs, cheveux, vêtements) : blockworld/town.py.
  • Ne passez pas un épisode déjà en cours à un autre style.
  • Pas de graphiques abstraits non expliqués. Un faisceau, une ligne ou une lueur entre deux petites figures n'apprend rien au spectateur (le « donnant toutes les barres » d'ep05 a été lu comme « une ligne bleue »). Montrez la chose elle-même : des barres sortant d'une étiquette, un compteur qui descend, un écran de téléphone qui le dit.

Le style

Les nouveaux épisodes utilisent le style Roblox : build_town(..., style="roblox"). Têtes rondes avec visages anime, cheveux en couches, vêtements imprimés, plastique brillant, ambiances soleil/brouillard/pluie, sous-titres karaoké de 3 mots. L'ancien style Block (têtes cubiques, couleurs unies) est toujours présent pour les épisodes qui ont commencé avec : build_town(...) sans style donne le style Block, alors écrivez toujours style="roblox" dans un nouvel épisode.

Barre de qualité (ce que l'utilisateur a rejeté ou demandé)

  • Rien n'est jamais statique. Rendez avec la couche de vie (BT_LIFE=1, la valeur par défaut dans render_threejs.sh) : respiration, regards, transferts de poids, rebond à chaque coupe, tremblement de caméra et zooms avant, arbres qui se balancent, nuages qui dérivent, étiquettes flottantes, spinners de chargement qui tournent, anneaux Wi-Fi pulsants, barres de signal qui rebondissent. Un plan où seule la caméra bouge est un plan faible : donnez-lui sa propre action.
  • Les étiquettes et les bulles ne sont jamais couvertes et jamais coupées. La couche de vie les dessine par-dessus tout, les soulève au-dessus des cheveux, et les maintient dans la zone de sécurité TikTok (x 5-85 %, y au-dessus des sous-titres). Vérifiez que deux étiquettes ne se chevauchent pas (pas encore automatique).
  • Chaque écran ressemble à un vrai téléphone : big_phone(screen=...) avec une image de pictures.py (barre d'état, « Pas de service », disposition des apps, une main qui le tient), jamais une boîte blanche avec du texte 3D. Les téléphones tenus à la main affichent un écran de verrouillage.
  • Les accessoires se lisent à la taille d'un téléphone : une carte en papier est une vraie carte dessinée (paper_map()), un panneau est entièrement dans le cadre (reculez la caméra : un panneau de 10 studs nécessite ~25 studs de distance en 9:16).
  • La voix ne faiblit jamais. finish.json {"voice": "vo/voice_level.wav", "loudness": "static"} : la narration est nivelée phrase par phrase et le mix reçoit un gain fixe, donc les effets forts ne peuvent pas faire baisser la voix. Mesurez : la loudness à court terme doit rester dans ±1 dB de -14 LUFS pour toute la vidéo.
  • Pas d'effets superposés ou agressifs. Un son par moment ; rien de plus long que le moment ; pas deux sons « d'erreur » en moins d'une demi-seconde.

Fabriquer un épisode : sept portes

Arrêtez-vous après chaque porte, montrez le résultat, et attendez l'utilisateur. Là où il y a un véritable choix créatif, proposez deux ou trois options et dites laquelle vous recommandez.

PorteCe que vous faitesMontrez à l'utilisateur
1 RègleTrois règles (à partir de l'idée de l'utilisateur ou des tests de docs/SCRIPT.md), chacune avec une ambiance et une idée de point de repèreun tableau
2 ScriptEPISODE/script.txt (une phrase par ligne) et EPISODE/SCRIPT.md : option A et B, tableau des beats, scores du critiquele script
3 Voixvo.py, words.py, voice_check.py (prise Fish gratuite), level_voice.pyvo/voice.wav, ses chiffres
4 DesignsEPISODE/design/episode.py : un arrêt sur image de chaque nouveau point de repère, accessoire, costume et personnage ; EPISODE/pictures.json et pictures.py pour chaque écran de téléphone et accessoire impriméDESIGN_SHEET.jpg + les écrans
5 Arrêts sur imageEPISODE/episode.py avec chaque plan ; check ; arrêts sur image ; correction ; contact_sheet.pyCONTACT_SHEET.jpg
6 Accrocheles premières ~15 s : render_threejs.sh EPISODE 0 F1, indices sonores, finish.pyle MP4
7 Vidéo complèterender_threejs.sh EPISODE, sons, finish.py (fichier propre + fichier musique) ; sur approbation, la prise vocale payanteles deux MP4

Les détails des portes se trouvent dans docs/PROMPTS.md (le prompt 1 exécute l'ensemble). Copiez examples/ep05-wifi pour commencer : c'est un épisode terminé fabriqué de cette manière, avec sa fiche de design, 42 plans, images de téléphone, indices et paramètres.

Une prise finale payante est un nouvel enregistrement : exécutez à nouveau words.py et level_voice.py, puis check, et re-rendu (les plans suivent les temps des mots). Approuvez donc le timing de la prise gratuite à la porte 3, mais effectuez la prise payante avant la porte 6 si l'utilisateur souhaite publier.

Commandes

# voix (porte 3)
python3 SKILL/blockworld/vo.py EPISODE                 # une prise dans la voix "Roblox" de Fish (vo_config.json)
python3 SKILL/blockworld/vo.py EPISODE --post-only     # refaire le resserrement/présence/tempo sur la prise sauvegardée, sans nouvel appel
python3 SKILL/blockworld/words.py EPISODE              # temps des mots -> vo/times.json
python3 -I SKILL/blockworld/voice_check.py EPISODE     # rythme, pauses, luminosité par rapport aux plages virales
python3 -I SKILL/blockworld/level_voice.py EPISODE     # chaque phrase à un niveau -> vo/voice_level.wav

# images pour les accessoires (porte 4)
python3 -I SKILL/blockworld/pictures.py EPISODE        # EPISODE/pictures.json -> EPISODE/pictures/*.png

# plans (portes 4-5) : Blender, toujours via run.py avec --factory-startup
blender -b --factory-startup --python-exit-code 1 -P SKILL/blockworld/run.py -- EPISODE check
BT_LIFE=1 blender -b --factory-startup --python-exit-code 1 -P SKILL/blockworld/run.py -- EPISODE stills [plan ...]
blender -b --factory-startup --python-exit-code 1 -P SKILL/blockworld/run.py -- EPISODE frame 12.5
python3 -I SKILL/blockworld/contact_sheet.py EPISODE   # un arrêt sur image numéroté par plan -> CONTACT_SHEET.jpg

# images finales (portes 6-7) : Three.js
bash SKILL/blockworld/render_threejs.sh EPISODE              # chaque image -> EPISODE/frames/ (~10 min pour 66 s)
bash SKILL/blockworld/render_threejs.sh EPISODE F0 F1        # seulement F0..F1 (l'accroche, un plan refait)

# effets sonores (portes 6-7) : voir docs/SOUND.md
python3 -I SKILL/blockworld/sfx_gen.py --credits             # crédits ElevenLabs restants
python3 -I SKILL/blockworld/sfx_gen.py el-tag-pop ep07-...   # générer des sons nommés à partir de sfx/ELEVENLABS_LIST.md
python3 -I SKILL/blockworld/cues.py EPISODE cues_spec.json   # indices par mot ("dire" : "gelé") -> EPISODE/cues.json

# finition (portes 6-7)
python3 -I SKILL/blockworld/finish.py EPISODE                # sous-titres + voix + effets (+ musique) -> les MP4
  • check ne rend rien : il exécute chaque plan, affiche le tableau des plans et prévient des plans de plus de 2,5 s.
  • Vérifications automatiques des arrêts sur image (blockworld/stillcheck.py, depuis ep08) : appelez focus(personnage, étiquette, ...) dans chaque plan. check et stills signalent alors les visages bloqués (par un poteau, une personne, une étiquette ou le propre bras du personnage), les visages sous la bande de sous-titres, les étiquettes en dehors de la zone de sécurité (x 5-85 %, entre la barre supérieure de TikTok et les sous-titres), les étiquettes qui se chevauchent, et tout ce qui se trouve à moins de 1 stud de l'objectif. Les résultats vont dans EPISODE/still_check.txt. Corrigez chaque ligne avant de montrer les arrêts sur image, puis regardez-les quand même : cela ne juge pas le cadrage ni si l'image illustre la phrase.
  • 60 fps avec flou de mouvement (optionnel) : finish.json "render_fps": 240, "blur": 4 rend 240 images par seconde et moyenne chaque groupe de 4 en une image 60 fps. Environ 1,6 min de rendu par seconde de vidéo.
  • Virage couleur (optionnel) : finish.json "grade": {"word": 24, "ramp": 0.5, "saturation": 0.6, "brightness": -0.05, "cool": 0.1, "vignette": true} atténue l'image vers le froid, le sombre et le plat à partir de ce mot du script (le tournant de l'histoire). Les sous-titres ne sont pas modifiés. finish.py EPISODE --plain écrit aussi <nom>_plain.mp4 (30 fps, pas de flou, pas de virage) pour une comparaison côte à côte.
  • ep08 (episodes/ep08-price-tags-10s) est le test de 10 secondes de ces éléments, avec des plans d'environ 1 s.
  • stills écrit deux images Blender demi-taille par plan (à 30 % et 85 %) dans EPISODE/stills/. Utilisez BT_LIFE=1 pour que les étiquettes soient placées comme lors du rendu final. Regardez chaque arrêt sur image avant d'en montrer un.
  • render_threejs.sh s'exécute en arrière-plan si vos commandes expirent (environ 10 minutes pour 66 s). Il installe les deux packages npm lors de la première utilisation (blockworld/threejs/) et nécessite Chrome ou Chromium (CHROME=/path pour choisir). Il conserve son bake dans EPISODE/threejs/ ; supprimez-le ainsi que frames/ après que l'utilisateur a accepté la vidéo.
  • Après toute modification de episode.py, d'un décor ou d'une image : réexécutez render_threejs.sh (le bake lit le code ; rien n'est mis en cache entre les exécutions).
  • render_all.sh (images Blender EEVEE) est conservé uniquement pour les comparaisons : environ 3-6 s par image.
  • L'accroche : render_threejs.sh EPISODE 0 F1 où F1 est l'image juste avant la première coupe après ~15 s, puis finish.py (elle utilise les images existantes), et renommez le MP4 pour que la vidéo complète ne l'écrase pas.
  • Regardez les images sur toute la vidéo (au moins une par plan) et mesurez la loudness avant de déclarer la vidéo terminée. Si vous ne pouvez pas écouter, dites-le clairement et listez ce que vous avez vérifié à la place.

Ce qui va où

CheminQuoi
blockworld/town.pyla rue, le casting, pose(), lumière, caméra, build_town(style=...)
blockworld/roblox.pyle look Roblox : rchar, plastique, ambiances, rule_sign, giant_clock, puddles
blockworld/rprops.pyaccessoires prêts : étiquettes de barre de signal et jetons de barre volante, téléphones avec vrais écrans et une main, images éclairées et imprimées, carte en papier pliée, affiche, écharpe, haut-de-forme, bus, porte, faisceau, pigeon, tour Wi-Fi
blockworld/pictures.py, blockworld/pictures/dessine les écrans de téléphone, les écrans de verrouillage et les cartes à partir de pictures.json ; les images par défaut du kit
blockworld/anim.pyaides au timing des mots, cartes (étiquettes, bulles), stand, walk, le coureur
blockworld/life.pyla couche de vie (BT_LIFE=1) : mouvement d'inactivité, caméra, balancement de la scène, spinners, placement des étiquettes
blockworld/threejs/le moteur de rendu : bake.py (côté Blender), scene.html + capture.mjs (côté Three.js)
blockworld/render_threejs.shbake + dessin, la manière normale de faire les images finales
blockworld/vo.py, words.py, voice_check.py, level_voice.pyvoix, temps des mots, vérification vocale, nivellement
blockworld/sfx_gen.py, sfx/ELEVENLABS_LIST.mdeffets sonores ElevenLabs : le générateur et la liste des prompts
blockworld/finish.pysous-titres, voix, effets sonores (y compris les boucles de fond), musique, le mix stable, les MP4
blockworld/cues.pylistes d'indices par mot -> cues.json
sfx/effets sonores : l'ensemble Pixabay (sfx/CREDITS.md) ; les sons ElevenLabs arrivent ici sous la forme el-*.mp3 / epNN-*.mp3 une fois générés (aucun pour l'instant à partir d'ep05)
examples/ep05-wifil'épisode complet travaillé (look Roblox, moteur de rendu Three.js)
examples/ep00-roblox-look, examples/ep01-introcourtes démos du look Roblox et du look Block

Skills associés