From fafaebb051907a848a9406f9da19669c81a83a3b Mon Sep 17 00:00:00 2001 From: Elvis Claros Castro Date: Sat, 26 Sep 2026 20:50:41 -0300 Subject: Translate code, comments and logs to English; English README; configurable paths and env vars Identifiers, docstrings, comments and console messages are now in English. Narration, subtitles and on-screen text stay in Spanish (they are the video content). The Blender <-> Godot physics protocol uses English keys and body prefixes chosen to keep the original creation order, so cached simulations and renders stay bit-identical. The old Spanish environment variable names are still accepted. --- README.es.md | 284 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 README.es.md (limited to 'README.es.md') diff --git a/README.es.md b/README.es.md new file mode 100644 index 0000000..d5c8837 --- /dev/null +++ b/README.es.md @@ -0,0 +1,284 @@ +# 24 videos verticales para TikTok — 100% generados localmente + +[English](README.md) + +Todo corre offline: **Manim** para la animación 2D, **Blender** (EEVEE, headless) para +las escenas 3D, **Godot** (motor de física Jolt, headless) para la física de +rígidos, **qwentts.cpp** (voz clonada rioplatense) para la locución y las +muestras de piano de `keysound` para la música. + +## Los videos (`out/`) + +| Archivo | Tema | Duración | Gancho | +|---|---|---|---| +| `montyhall.mp4` | Problema de Monty Hall | 39,5 s | genera debate en comentarios | +| `nueves.mp4` | 0,999… = 1 | 38,8 s | genera debate en comentarios | +| `cumple.mp4` | Paradoja del cumpleaños | 38,6 s | dato que sorprende | +| `luna.mp4` | Doblar un papel hasta la Luna | 38,4 s | dato que sorprende | +| `japones.mp4` | Multiplicar con líneas | 38,8 s | útil, se guarda y se comparte | +| `benford.mp4` | Ley de Benford (detectar fraude) | 42,8 s | dato que sorprende + útil | +| `hilbert.mp4` | El hotel infinito | 37,1 s | genera debate en comentarios | +| `reuleaux.mp4` | Por qué las tapas son redondas | 36,0 s | satisfactorio de mirar | +| `regla72.mp4` | La regla del 72 | 35,5 s | útil, se guarda | +| `buffon.mp4` | Sacar π tirando agujas | 36,7 s | belleza matemática | +| `collatz.mp4` | Conjetura de Collatz (3n+1) | 46,2 s | misterio sin resolver | +| `simpson.mp4` | Paradoja de Simpson | 53,0 s | genera debate + útil | +| `cuerda.mp4` | Una cuerda alrededor de la Tierra | 45,4 s | dato que sorprende | +| `gabriel.mp4` | El cuerno de Gabriel | 40,5 s | belleza matemática | +| `mobius.mp4` | Cinta de Möbius | 46,3 s | para hacer en casa | +| `bayes.mp4` | Falso positivo (test médico) | 46,9 s | genera debate + útil | +| `cicloide.mp4` | Braquistócrona: la curva más rápida | 47,6 s | satisfactorio de mirar | +| `dados.mp4` | Dados no transitivos | 50,6 s | genera debate en comentarios | +| `bolapeluda.mp4` | Teorema de la bola peluda (3D) | 41,9 s | satisfactorio de mirar | +| `caos.mp4` | Tres péndulos dobles y 1 mm (3D) | 40,6 s | hipnótico, se mira entero | +| `diferencial.mp4` | Cómo funciona el diferencial (3D) | 44,1 s | útil, se guarda y se comparte | +| `galton.mp4` | Tablero de Galton: 500 bolitas forman la campana (Blender + Godot) | 45,7 s | satisfactorio + pregunta en comentarios | +| `bloques.mp4` | Pila armónica: bloques que sobresalen de la mesa (Blender + Godot) | 48,0 s | para hacer en casa + dato que sorprende | +| `domino.mp4` | Dominó ×1,5: de 5 mm al Aconcagua (Blender + Godot) | 66,7 s | exponencial + pregunta en comentarios (más de 1 min) | + +Formato: 1080×1920, 30 fps, H.264 + AAC 48 kHz estéreo, **−13,8 a −15,3 LUFS** +medidos (el objetivo de TikTok es −14, así no te lo bajan ni te lo suben), +pico real por debajo de −1 dBTP. +Subtítulos quemados: el 80 % mira sin audio. + +## Textos sugeridos para publicar + +**montyhall** — ¿Te quedás o cambiás? El 87% se equivoca 🚪 +`#matematica #montyhall #datocurioso #probabilidad #argentina` + +**nueves** — 0,999… es EXACTAMENTE 1. Peleame en los comentarios 🧮 +`#matematica #mindblown #datocurioso #numeros #viral` + +**cumple** — Con 23 personas ya hay 50% de que dos cumplan el mismo día 🎂 +`#paradoja #datocurioso #matematica #probabilidad #sabiasque` + +**luna** — Doblá un papel 42 veces y llegás a la Luna 🌙 +`#exponencial #datocurioso #ciencia #mindblown #sabiasque` + +**japones** — Así multiplican en Japón, sin tablas ✏️ +`#trucosmatematicos #japon #escuela #tarea #aprendeentiktok` + +**benford** — Los números inventados se notan. Así agarran fraudes 🕵️ +`#benford #fraude #estadistica #datocurioso #sabiasque` + +**hilbert** — Un hotel lleno con infinitas habitaciones… y entran infinitos más 🏨 +`#infinito #matematica #paradoja #mindblown #hilbert` + +**reuleaux** — Por qué las tapas de alcantarilla son redondas 🛞 +`#datocurioso #geometria #ingenieria #sabiasque #reuleaux` + +**regla72** — La cuenta que te dice cuándo se duplica tu plata 💸 +`#finanzaspersonales #inversiones #interescompuesto #inflacion #argentina` + +**buffon** — Tiro agujas al piso y sale π. Sin ningún círculo 🎲 +`#pi #matematica #azar #datocurioso #mindblown` + +**collatz** — Elegí cualquier número. Nadie pudo demostrar por qué siempre cae al 1 🌀 +`#collatz #matematica #misterio #datocurioso #mindblown` + +**simpson** — Gana en los dos grupos y pierde en el total. Así te miente un promedio 📊 +`#estadistica #paradoja #datos #sabiasque #matematica` + +**cuerda** — Le agrego 1 metro a una cuerda que rodea la Tierra. ¿Cuánto se levanta? 🌍 +`#datocurioso #matematica #mindblown #sabiasque #ciencia` + +**gabriel** — Lo podés llenar de pintura, pero no lo podés pintar 🎺 +`#infinito #matematica #paradoja #calculo #mindblown` + +**mobius** — Cortá esta cinta al medio y NO van a salir dos ✂️📄 +`#mobius #topologia #experimento #hacelovos #datocurioso` + +**bayes** — El test acierta el 99% y te dio positivo. La chance de estar enfermo es 9% 🧪 +`#probabilidad #estadistica #salud #sabiasque #bayes` + +**cicloide** — La recta es el camino más corto… y pierde la carrera 🎢 +`#fisica #matematica #satisfying #mindblown #cicloide` + +**dados** — Elegí el dado que quieras. Elijo después y te gano igual 🎲 +`#probabilidad #dados #juegos #datocurioso #matematica` + +**bolapeluda** — No podés peinar una esfera sin dejar un remolino. Es un teorema 🌀 +`#topologia #matematica #3d #datocurioso #mindblown` + +**caos** — Tres péndulos idénticos salvo 1 milímetro. A los 5 segundos no se parecen en nada 🎲 +`#caos #fisica #simulacion #mindblown #efectomariposa` + +**diferencial** — Por qué tu auto puede doblar sin que una rueda patine ⚙️ +`#mecanica #autos #ingenieria #sabiasque #comofunciona` + +**galton** — 500 bolitas, cada una al azar… y todas juntas dibujan una campana 🔔 +`#probabilidad #estadistica #galton #satisfying #matematica` + +**bloques** — Apilé bloques hasta que el de arriba quedó en el aire. ¿Hasta dónde llegás vos? 📚 +`#fisica #experimento #matematica #paraHacerEnCasa #sabiasque` + +**domino** — Una ficha de 5 mm puede tirar un edificio. ¿En qué ficha se cae tu casa? 🏠 +`#domino #fisica #exponencial #satisfying #sabiasque` + +Subí uno por día, mismo horario, y alterná los tres tipos: + +- **debate** (comentarios, que es lo que más empuja el alcance): montyhall, nueves, + hilbert, simpson, cuerda, dados +- **útil** (se guarda y se comparte): japones, regla72, benford, bayes, diferencial, bloques +- **espectáculo** (se mira hasta el final): reuleaux, buffon, mobius, gabriel, collatz, + luna, cumple, cicloide, bolapeluda, caos, galton, domino + +Los tres últimos (`bolapeluda`, `caos`, `diferencial`) están hechos en Blender: sirven +para cortar la monotonía visual de Manim sin cambiar el estilo del canal, porque la +capa de interfaz (chip, barra y subtítulos) es la misma. + +`mobius` es el único con llamado a la acción físico ("hacelo con una hoja"): +esos suelen traer videos-respuesta, que valen doble. + +### Blender + Godot (`galton`, `bloques`) + +Blender diseña y Godot calcula la física: + +1. `MODE=sim blender -b -P blender/.py` arma la escena y exporta a glTF solo + los objetos físicos. El prefijo del nombre dice qué es cada uno para Godot + (`static_` malla estática, `box_` caja estática, `gate_` estática que se saca + con un evento, `ball_` esfera rígida, `block_` caja rígida). Después corre + `godot --headless --fixed-fps 240 -- godot/work/.json`. +2. `godot/sim.gd` carga el glb en tiempo de ejecución, crea los cuerpos, aplica los + eventos del guion (soltar, sacar la compuerta) en el segundo exacto del timeline + y graba la pose de cada cuerpo a 30 fps en coordenadas de Blender + (`godot/work/.bin`). +3. `blender -b -P blender/.py` lee esas poses y renderiza con los materiales + de verdad (madera procedural, latón, acero). + +Nada del movimiento está animado a mano. Algunos números que salen de la simulación: + +- **galton**: casilleros `[0 1 7 29 70 104 96 83 65 35 10 0 0]` (desvío de 1,82 + casilleros; el binomial ideal de 12 filas da 1,73). La columna del medio tiene + **96**: es la respuesta a la pregunta del final. +- **bloques**: la pila de 5 con corrimientos armónicos ×0,95 se sostiene con el de + arriba entero en el aire (8,5 % de bloque). La torre de 16 no se mueve hasta que + se le apoya un bloque más en la punta izquierda de arriba: se caen 10 de 17. + +Dos ajustes que hicieron falta en Godot: + +- **galton**: una amortiguación lineal de 6/s, que hace de roce contra el vidrio. + Sin ella las bolitas toman demasiada velocidad lateral y el reparto sale plano. +- **bloques**: física a 1920 Hz y mundo ×5 (`"hz"` y `"scale"` en el config). Jolt + tolera 2 cm de penetración y a 240 Hz la torre de 16 se hundía y se volcaba sola. + +Ojo: con la notebook Optimus, EEVEE usa la Intel salvo que se lance con +`__NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia`, y así es 3,6 veces +más rápido (1,5 s/frame contra 5,5 en galton). + +## Cómo regenerar + +```bash +conda run -n manim python scripts/gen_audio.py montyhall # voz + verificación +conda run -n manim manim render -v ERROR --disable_caching \ + --format=mp4 -o montyhall scenes/v1_montyhall.py MontyHall +conda run -n manim python scripts/build_video.py montyhall # música + mezcla + mux +conda run -n manim python scripts/verify_final.py montyhall # QA sobre el MP4 final +``` + +`DRAFT=1` antes del render baja a 540×960 para iterar rápido. + +## Cómo está armado + +``` +scripts/narration.py guiones: (texto que se locuta, subtítulo en pantalla) +scripts/gen_audio.py sintetiza cada frase y la verifica transcribiéndola con Whisper +scripts/numspell.py pasa "99,9%" a "noventa y nueve coma nueve por ciento" + para poder comparar la transcripción contra el guion +scripts/regen.py regenera una frase probando 5 semillas +scripts/repick.py reelige la mejor toma ya sintetizada +scripts/verify.py QA: transcribe todos los WAV y marca los dudosos +scripts/verify_final.py QA final: saca el audio del MP4 ya mezclado y lo transcribe, + así se prueba que la voz se entiende por encima del piano +scripts/music.py cama de piano (progresión propia) + ducking bajo la voz +scripts/build_video.py arma la pista siguiendo el timeline y la pega al video +scenes/tiktok.py base: 9:16, subtítulos, barra de progreso, "beats" +scenes/v*.py una escena por video (Manim) +scenes/overlay.py capa de interfaz para los videos 3D: la misma barra, el mismo + chip y los mismos subtítulos, renderizados con alfa +blender/base.py base de las escenas 3D: paleta, cámara, primitivas, tiempo +blender/*.py una escena por video 3D +scripts/build_blender.py compone fondo + 3D + overlay + audio en una sola pasada +``` + +### Los videos 3D + +Se renderizan headless con Blender 5.2 y EEVEE: + +```bash +conda run -n manim manim -s --disable_caching -o fondo scenes/overlay.py Backdrop # trama de puntos +NAME=caos CHIP=Caos CHIPCOL=rosa conda run -n manim manim --transparent \ + --disable_caching -o caos scenes/overlay.py Overlay # capa + timeline +/ruta/a/blender -b --factory-startup --python blender/caos.py # secuencia PNG con alfa +conda run -n manim python scripts/build_blender.py caos # composicion + audio +``` + +Dos decisiones que se pagaron solas: + +- **Sin keyframes.** El render recorre los frames uno por uno y antes de cada uno + llama a `refresh(f)`, que coloca todo. Así la física se calcula exacta en cada + cuadro, se pueden renderizar frames salteados para revisar el encuadre, y no hay + que pelear con la API de acciones por capas de Blender 5.x. +- **El fondo no está en la escena 3D.** Blender renderiza con `film_transparent` y el + fondo punteado se compone abajo con ffmpeg, así es pixel por pixel el mismo que el + de los 18 videos de Manim. +- **El metal necesita algo que reflejar.** `studio_world()` pone un gradiente de + horizonte en el mundo: no se ve (el film es transparente) pero es lo único que + separa el acero del plástico gris. Sin eso, un material metálico queda plano. + +`blender/base.py` genera las piezas mecánicas por código: + +| Función | Qué hace | +|---|---| +| `bevel_gear` | Engranaje cónico con semiángulo de cono y dientes en espiral. Dos engranan a 90° cuando sus γ suman 90: 45+45 para los del diferencial, 72+18 para corona y piñón (y ahí la relación de dientes queda fijada por sin72/sin18 = 3,07, que es por qué son 43 y 14) | +| `full_wheel` | Neumático con tacos y canales + llanta de aleación con radios + disco de freno | +| `ring_sector` | Pared curva: con dos de estas y dos bridas sale una caja de diferencial con ventanas, que es lo que deja ver los engranajes de adentro | +| `flat_ring`, `screws` | Bridas y coronas de bulones | + +Los PNG intermedios quedan en `render//` (unos 4 GB los tres). Sirven para +recomponer con otro audio o subtítulos sin volver a renderizar, que son entre 30 y +55 minutos por video; si no hacen falta, se borran. + +`SAMPLES=8` baja las muestras de EEVEE (16 por defecto, 64 de fábrica: eso son +10 s/frame en una GTX 1050 y 1,6 s/frame con 8). `EVERY=55` renderiza un frame de +cada 55 para armar la hoja de contacto sin esperar el render entero. + +La sincronía no se estima: la escena escribe `out/_timeline.json` con el +tiempo real de cada bloque y el audio se coloca en esas marcas exactas. + +## Variables de entorno + +| Variable | Para qué | +|---|---| +| `PROJECT` | raíz del proyecto (por defecto, la carpeta del repositorio) | +| `MODE=sim` | en las escenas con Godot: recalcula la física en lugar de renderizar | +| `SAMPLES`, `PCT` | muestras de EEVEE y porcentaje de resolución | +| `FROM_FRAME`, `TO_FRAME`, `EVERY`, `RESUME` | qué frames renderizar | +| `QWENTTS_DIR`, `VOICE_REF` | qwentts.cpp y la voz de referencia para la locución | +| `PIANO_DIR` | muestras de piano de keysound | + +Los nombres anteriores (`PROY`, `MODO`, `MUESTRAS`, `DESDE`, `HASTA`, `SALTO`, +`SEGUIR`, `PRUEBA`) se siguen aceptando. + +## Voz + +El repositorio no trae la voz clonada. `VOICE_REF` es el prefijo de sus tres +archivos (`.spk`, `.rvq` y `.txt`), que se sacan de una grabación con +`qwen-codec --talker`. + +## Qué no está en git + +Todo lo que se genera: `render/` (PNG intermedios), `media/` (salida de Manim), +`audio/` (locución), `out/` (videos finales y timelines), `tmp/` y +`godot/work/` (simulaciones). Se regeneran con los pasos de arriba. + +## Sobre la música + +Las progresiones (Am–F–C–G, Em–C–G–D, Am–Em–Dm–E, Cm–G#–A#–Gm, A–E–F#m–D, etc.) son propias y están tocadas con muestras +de piano sueltas, así que el audio es tuyo y no te lo va a marcar el Content ID. +Si preferís un audio en tendencia de TikTok, subilo igual y agregalo desde la app: +la voz ya está mezclada a −14 LUFS y se sigue entendiendo por encima. + +## Licencia + +MIT -- cgit v1.2.3