aboutsummaryrefslogtreecommitdiffstats
path: root/README.md
diff options
context:
space:
mode:
authorElvis Claros Castro <elvis@claros.ar>2026-09-26 20:50:41 -0300
committerElvis Claros Castro <elvis@claros.ar>2026-09-26 20:50:41 -0300
commitfafaebb051907a848a9406f9da19669c81a83a3b (patch)
treec30ea26e6b549e5523af2bae5c39569e9a946b12 /README.md
parent59355909f2de9236af8168a26c70bcf6caa3b285 (diff)
download100cia-videos-main.tar.gz
100cia-videos-main.zip
Translate code, comments and logs to English; English README; configurable paths and env varsHEADmain
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.
Diffstat (limited to 'README.md')
-rw-r--r--README.md317
1 files changed, 181 insertions, 136 deletions
diff --git a/README.md b/README.md
index bcced52..31cb19d 100644
--- a/README.md
+++ b/README.md
@@ -1,45 +1,49 @@
-# 24 videos verticales para TikTok — 100% generados localmente
+# 24 vertical TikTok videos — generated 100% locally
-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.
+[Español](README.es.md)
-## Los videos (`out/`)
+Everything runs offline: **Manim** for 2D animation, **Blender** (EEVEE, headless)
+for the 3D scenes, **Godot** (Jolt physics engine, headless) for rigid-body
+physics, **qwentts.cpp** (a cloned Rioplatense voice) for the narration and the
+`keysound` piano samples for the music.
-| Archivo | Tema | Duración | Gancho |
+The videos are in Spanish: narration, subtitles and on-screen text are Spanish on
+purpose. The code is in English.
+
+## The videos (`out/`)
+
+| File | Topic | Length | Hook |
|---|---|---|---|
-| `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.mp4` | The Monty Hall problem | 39.5 s | sparks debate in the comments |
+| `nueves.mp4` | 0,999… = 1 | 38.8 s | sparks debate in the comments |
+| `cumple.mp4` | The birthday paradox | 38.6 s | surprising fact |
+| `luna.mp4` | Folding paper to the Moon | 38.4 s | surprising fact |
+| `japones.mp4` | Multiplying with lines | 38.8 s | useful, gets saved and shared |
+| `benford.mp4` | Benford's law (spotting fraud) | 42.8 s | surprising fact + useful |
+| `hilbert.mp4` | The infinite hotel | 37.1 s | sparks debate in the comments |
+| `reuleaux.mp4` | Why manhole covers are round | 36.0 s | satisfying to watch |
+| `regla72.mp4` | The rule of 72 | 35.5 s | useful, gets saved |
+| `buffon.mp4` | Getting π by dropping needles | 36.7 s | mathematical beauty |
+| `collatz.mp4` | The Collatz conjecture (3n+1) | 46.2 s | unsolved mystery |
+| `simpson.mp4` | Simpson's paradox | 53.0 s | debate + useful |
+| `cuerda.mp4` | A rope around the Earth | 45.4 s | surprising fact |
+| `gabriel.mp4` | Gabriel's horn | 40.5 s | mathematical beauty |
+| `mobius.mp4` | Möbius strip | 46.3 s | try it at home |
+| `bayes.mp4` | False positive (medical test) | 46.9 s | debate + useful |
+| `cicloide.mp4` | Brachistochrone: the fastest curve | 47.6 s | satisfying to watch |
+| `dados.mp4` | Non-transitive dice | 50.6 s | sparks debate in the comments |
+| `bolapeluda.mp4` | Hairy ball theorem (3D) | 41.9 s | satisfying to watch |
+| `caos.mp4` | Three double pendulums and 1 mm (3D) | 40.6 s | hypnotic, watched to the end |
+| `diferencial.mp4` | How a differential works (3D) | 44.1 s | useful, gets saved and shared |
+| `galton.mp4` | Galton board: 500 balls draw the bell curve (Blender + Godot) | 45.7 s | satisfying + question in the comments |
+| `bloques.mp4` | Harmonic stack: blocks overhanging the table (Blender + Godot) | 48.0 s | try it at home + surprising fact |
+| `domino.mp4` | Dominoes ×1.5: from 5 mm to the Aconcagua (Blender + Godot) | 66.7 s | exponential + question in the comments (over 1 min) |
+
+Format: 1080×1920, 30 fps, H.264 + AAC 48 kHz stereo, **−13.8 to −15.3 LUFS**
+measured (TikTok's target is −14, so it neither lowers nor raises them), true
+peak below −1 dBTP. Burned-in subtitles: 80 % watch without sound.
+
+## Suggested post texts (in Spanish, as published)
**montyhall** — ¿Te quedás o cambiás? El 87% se equivoca 🚪
`#matematica #montyhall #datocurioso #probabilidad #argentina`
@@ -113,140 +117,181 @@ Subtítulos quemados: el 80 % mira sin audio.
**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:
+Post one a day at the same time, and rotate the three kinds:
-- **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,
+- **debate** (comments, which push reach the most): montyhall, nueves, hilbert,
+ simpson, cuerda, dados
+- **useful** (saved and shared): japones, regla72, benford, bayes, diferencial, bloques
+- **spectacle** (watched to the end): 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.
+The 3D ones (`bolapeluda`, `caos`, `diferencial`, `galton`, `bloques`, `domino`)
+are made in Blender: they break the visual monotony of Manim without changing the
+channel style, because the UI layer (chip, bar and subtitles) is the same.
-`mobius` es el único con llamado a la acción físico ("hacelo con una hoja"):
-esos suelen traer videos-respuesta, que valen doble.
+`mobius` is the only one with a physical call to action ("do it with a sheet of
+paper"): those tend to bring response videos, which count double.
-### Blender + Godot (`galton`, `bloques`)
+### Blender + Godot (`galton`, `bloques`, `domino`)
-Blender diseña y Godot calcula la física:
+Blender designs and Godot computes the physics:
-1. `MODO=sim blender -b -P blender/<nombre>.py` arma la escena y exporta a glTF solo
- los objetos físicos. El prefijo del nombre dice qué es cada uno para Godot
- (`fijo_` malla estática, `caja_` caja estática, `compuerta_` estática que se saca
- con un evento, `bola_` esfera rígida, `bloque_` caja rígida). Después corre
- `godot --headless --fixed-fps 240 -- godot/trabajo/<nombre>.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/trabajo/<nombre>.bin`).
-3. `blender -b -P blender/<nombre>.py` lee esas poses y renderiza con los materiales
- de verdad (madera procedural, latón, acero).
+1. `MODE=sim blender -b -P blender/<name>.py` builds the scene and exports only
+ the physical objects to glTF. The name prefix tells Godot what each one is
+ (`static_` static mesh, `box_` static box, `gate_` static and removed by an
+ event, `ball_` rigid sphere, `block_` rigid box). Then it runs
+ `godot --headless --fixed-fps 240 -- godot/work/<name>.json`.
+2. `godot/sim.gd` loads the glb at runtime, creates the bodies, applies the
+ script events (release, remove the gate) at the exact second of the timeline
+ and records each body's pose at 30 fps in Blender coordinates
+ (`godot/work/<name>.bin`).
+3. `blender -b -P blender/<name>.py` reads those poses back and renders with the
+ real materials (procedural wood, brass, steel).
-Nada del movimiento está animado a mano. Algunos números que salen de la simulación:
+None of the motion is animated by hand. Some numbers that come out of the
+simulation:
-- **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.
+- **galton**: bins `[0 1 7 29 70 104 96 83 65 35 10 0 0]` (standard deviation of
+ 1.82 bins; the ideal binomial for 12 rows gives 1.73). The middle column holds
+ **96**: that is the answer to the closing question.
+- **bloques**: the stack of 5 with harmonic shifts ×0.95 holds with the top block
+ entirely in the air (8.5 % of a block). The tower of 16 does not move until one
+ more block is put on its top left end: 10 of 17 fall.
-Dos ajustes que hicieron falta en Godot:
+Two tweaks Godot needed:
-- **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 `"escala"` 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.
+- **galton**: linear damping of 6/s, acting as friction against the glass.
+ Without it the balls pick up too much sideways speed and the distribution
+ comes out flat.
+- **bloques**: physics at 1920 Hz and the world ×5 (`"hz"` and `"scale"` in the
+ config). Jolt tolerates 2 cm of penetration and at 240 Hz the tower of 16 sank
+ and toppled on its own.
-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).
+The prefixes also set the order Godot creates the bodies in (Blender exports
+alphabetically), and in a chaotic scene that order changes the result: keep new
+prefixes in the same alphabetical order (`ball_ < box_ < gate_ < static_`).
-## Cómo regenerar
+On an Optimus laptop EEVEE uses the Intel GPU unless started with
+`__NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia`, which is 3.6 times
+faster (1.5 s/frame versus 5.5 on galton).
+
+## Regenerating
```bash
-conda run -n manim python scripts/gen_audio.py montyhall # voz + verificación
+conda run -n manim python scripts/gen_audio.py montyhall # voice + check
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
+conda run -n manim python scripts/build_video.py montyhall # music + mix + mux
+conda run -n manim python scripts/verify_final.py montyhall # QA on the final MP4
```
-`DRAFT=1` antes del render baja a 540×960 para iterar rápido.
+`DRAFT=1` before rendering drops to 540×960 to iterate fast.
-## Cómo está armado
+## Layout
```
-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
+scripts/narration.py scripts: (text that is spoken, on-screen subtitle)
+scripts/gen_audio.py synthesizes each sentence and checks it by transcribing with Whisper
+scripts/numspell.py turns "99,9%" into "noventa y nueve coma nueve por ciento"
+ so the transcription can be compared with the script
+scripts/regen.py regenerates one sentence trying 5 seeds
+scripts/repick.py picks the best take already synthesized again
+scripts/verify.py QA: transcribes every WAV and flags doubtful ones
+scripts/verify_final.py final QA: extracts the audio of the mixed MP4 and transcribes it,
+ which proves the voice is intelligible over the piano
+scripts/music.py piano bed (original progression) + ducking under the voice
+scripts/build_video.py builds the track following the timeline and muxes it onto the video
+scenes/tiktok.py base: 9:16, subtitles, progress bar, "beats"
+scenes/v*.py one scene per video (Manim)
+scenes/overlay.py UI layer for the 3D videos: the same bar, chip and subtitles,
+ rendered with alpha
+blender/base.py base of the 3D scenes: palette, camera, primitives, timing
+blender/*.py one scene per 3D video
+godot/sim.gd generic rigid-body simulator fed by Blender
+scripts/build_blender.py composites background + 3D + overlay + audio in one pass
+brand/ channel logo and avatar (make_logo.py)
```
-### Los videos 3D
+### The 3D videos
-Se renderizan headless con Blender 5.2 y EEVEE:
+Rendered headless with Blender 5.2 and EEVEE:
```bash
-conda run -n manim manim -s --disable_caching -o fondo scenes/overlay.py Fondo # trama de puntos
+conda run -n manim manim -s --disable_caching -o fondo scenes/overlay.py Backdrop # dot pattern
NAME=caos CHIP=Caos CHIPCOL=rosa conda run -n manim manim --transparent \
- --disable_caching -o caos scenes/overlay.py Overlay # capa + timeline
-blender -b --factory-startup --python blender/caos.py # secuencia PNG con alfa
-conda run -n manim python scripts/build_blender.py caos # composicion + audio
+ --disable_caching -o caos scenes/overlay.py Overlay # UI layer + timeline
+/path/to/blender -b --factory-startup --python blender/caos.py # PNG sequence with alpha
+conda run -n manim python scripts/build_blender.py caos # compositing + audio
```
-Dos decisiones que se pagaron solas:
+Decisions that paid for themselves:
-- **Sin keyframes.** El render recorre los frames uno por uno y antes de cada uno
- llama a `actualizar(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.** `mundo_estudio()` 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.
+- **No keyframes.** The render walks the frames one by one and calls
+ `refresh(f)` before each one, which places everything. That way physics is
+ computed exactly on every frame, skipped frames can be rendered to check the
+ framing, and there is no fighting with Blender 5.x's layered actions API.
+- **The background is not in the 3D scene.** Blender renders with
+ `film_transparent` and the dotted background is composited underneath with
+ ffmpeg, so it is pixel for pixel the same as in the 18 Manim videos.
+- **Metal needs something to reflect.** `studio_world()` puts a horizon gradient
+ in the world: it is not visible (the film is transparent) but it is the only
+ thing that separates steel from grey plastic. Without it, a metallic material
+ looks flat.
-`blender/base.py` genera las piezas mecánicas por código:
+`blender/base.py` generates the mechanical parts in code:
-| Función | Qué hace |
+| Function | What it does |
|---|---|
-| `engranaje_conico` | 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) |
-| `rueda_completa` | Neumático con tacos y canales + llanta de aleación con radios + disco de freno |
-| `sector_anillo` | 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 |
-| `anillo_plano`, `tornillos` | Bridas y coronas de bulones |
+| `bevel_gear` | Bevel gear with a cone half-angle and spiral teeth. Two mesh at 90° when their γ add up to 90: 45+45 for the differential ones, 72+18 for ring gear and pinion (and there the tooth ratio is fixed by sin72/sin18 = 3.07, which is why they are 43 and 14) |
+| `full_wheel` | Tire with lugs and grooves + alloy rim with spokes + brake disc |
+| `ring_sector` | Curved wall: two of these and two flanges make a differential housing with windows, which is what lets you see the gears inside |
+| `flat_ring`, `screws` | Flanges and bolt circles |
+
+The intermediate PNGs stay in `render/<name>/` (about 4 GB for three videos). They
+allow recompositing with other audio or subtitles without rendering again, which
+takes 30 to 55 minutes per video; if they are not needed, delete them.
+
+`SAMPLES=8` lowers the EEVEE samples (16 by default, 64 stock: that is 10 s/frame
+on a GTX 1050 and 1.6 s/frame with 8). `EVERY=55` renders one frame out of every
+55 to build a contact sheet without waiting for the whole render.
+
+Sync is not estimated: the scene writes `out/<name>_timeline.json` with the real
+time of each block and the audio is placed at those exact marks.
+
+## Environment variables
+
+| Variable | What for |
+|---|---|
+| `PROJECT` | project root (defaults to the repository directory) |
+| `MODE=sim` | in the Godot scenes: recompute the physics instead of rendering |
+| `SAMPLES`, `PCT` | EEVEE samples and resolution percentage |
+| `FROM_FRAME`, `TO_FRAME`, `EVERY`, `RESUME` | which frames to render |
+| `QWENTTS_DIR`, `VOICE_REF` | qwentts.cpp and the reference voice for the narration |
+| `PIANO_DIR` | keysound piano samples |
+
+The older Spanish names (`PROY`, `MODO`, `MUESTRAS`, `DESDE`, `HASTA`, `SALTO`,
+`SEGUIR`, `PRUEBA`) are still accepted.
+
+## Voice
+
+The repository does not include the cloned voice. `VOICE_REF` is the path prefix
+of its three files (`.spk`, `.rvq` and `.txt`), extracted from a recording with
+`qwen-codec --talker`.
+
+## What is not in git
-Los PNG intermedios quedan en `render/<nombre>/` (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.
+Everything generated: `render/` (intermediate PNGs), `media/` (Manim output),
+`audio/` (narration), `out/` (final videos and timelines), `tmp/` and
+`godot/work/` (simulations). They are regenerated with the steps above.
-`MUESTRAS=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). `SALTO=55` renderiza un frame de
-cada 55 para armar la hoja de contacto sin esperar el render entero.
+## About the music
-La sincronía no se estima: la escena escribe `out/<nombre>_timeline.json` con el
-tiempo real de cada bloque y el audio se coloca en esas marcas exactas.
+The progressions (Am–F–C–G, Em–C–G–D, Am–Em–Dm–E, Cm–G#–A#–Gm, A–E–F#m–D, etc.) are
+original and played with loose piano samples, so the audio is yours and Content
+ID will not flag it. If you prefer a trending TikTok sound, upload anyway and add
+it from the app: the voice is already mixed at −14 LUFS and stays intelligible
+over it.
-## Sobre la música
+## License
-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.
+MIT