CommunityRedacción y edicióngithub.com

muyunxue/dance-mmd-subtitle-kit

Reglas estrictas, plantillas, comandos ffmpeg y diagnóstico de fallos para crear subtítulos ASS/SSA y quemarlos con libass en esta máquina. Cárgalo antes de escribir cualquier archivo ASS, cuando una quemadura

¿Qué es dance-mmd-subtitle-kit?

Este skill es una guía práctica y detallada para la creación y renderizado de subtítulos ASS/SSA usando libass, diseñada específicamente para el proyecto de baile MMD. Proporciona plantillas de cabecera, reglas estrictas de formato (timestamps, colores, fuentes, directorios de fuentes), comandos ffmpeg para quemado directo y superposición transparente, y una tabla de fallos rápida. Incluye además un esqueleto de generador en Python para facilitar la producción de eventos. Es esencial para cualquier desarrollador o AI agent que trabaje con subtítulos ASS, especialmente en plataformas como Claude Code, Cursor o Codex, ya que recopila los errores más comunes encontrados en el proyecto real y ofrece soluciones probadas. El skill cubre desde la sintaxis básica hasta animaciones complejas, dibujos \p1, y el uso de fuentes específicas como Anton, Permanent Marker o Microsoft YaHei, con advertencias sobre problemas de alineación y escalado.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/muyunxue/dance-mmd-subtitle-kit/tree/HEAD/skills/ass-render-playbook

Installed? Explore more Redacción y edición skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Manual práctico para escribir ASS / quemar con libass

1. Plantilla de cabecera (copia directa)

[Script Info]
ScriptType: v4.00+
PlayResX: 2560
PlayResY: 1080
WrapStyle: 2
ScaledBorderAndShadow: yes
YCbCr Matrix: TV.709

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: X,Microsoft YaHei,100,&H00F4F1EA,&H00F4F1EA,&H00140F11,&HFF000000,0,0,0,0,100,100,0,0,1,0,0,5,30,30,30,1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:00.39,0:00:03.75,X,,0,0,0,,{\an5\pos(500,300)\fnAnton\fs150\1c&H00F4F1EA&\bord3\3c&H00140F11&\frz-4\fscx118\fscy118\t(0,130,\fscx100\fscy100)\fad(100,100)}WALK

2. Cuatro errores fatales de formato (todos los hemos sufrido en este proyecto)

  1. Timestamp debe ser H:MM:SS.cc
    • Correcto: 0:00:01.50, 0:01:02.30
    • Incorrecto: 0:01.50 (libass muestra Bad timestamp, la línea entera se descarta → el video no tiene texto, pero ffmpeg devuelve 0)
  2. El color en la línea Style no debe terminar con &
    • Correcto: &H00F4F1EA,&H00F4F1EA,&H00140F11,&HFF000000
    • Incorrecto: &H00F4F1EA&,... → falla el parseo de la línea Style → el resultado es el mismo: «éxito pero sin texto»
    • Las etiquetas de color en línea sí deben llevar &: \1c&H00F4F1EA&
  3. El directorio de fuentes fontsdir debe ser una ruta relativa + directorio de trabajo
    • Coloca fonts/ en el directorio de salida, haz cd a ese directorio y luego ass=x.ass:fontsdir=fonts.
    • Las rutas absolutas con letra de unidad y dos puntos suelen fallar en el filtergraph; las rutas relativas con caracteres chinos no dan problema (el cwd puede ser en chino, pero los parámetros del filtro deben ser lo más ASCII posible).
  4. El archivo ASS debe escribirse con codificación utf-8-sig y nombre de archivo ASCII
    • Los nombres de archivo con caracteres chinos en los parámetros del filtro son inestables; usa nombres como _s4.ass.

Comando de diagnóstico (para ver qué lee realmente libass):

& $ff -hide_banner -v verbose -f lavfi -i "color=c=0x303040:s=2560x1080:r=30:d=2" `
  -vf "ass=_s4.ass:fontsdir=fonts" -c:v libx264 -crf 22 -pix_fmt yuv420p _t.mp4 2>&1 | Select-String 'Bad timestamp|Style|font file'

3. Semántica de color / alfa

  • Color: &HBBGGRR& (orden azul-verde-rojo), ej: blanco &H00F4F1EA&, negro tinta &H00140F11&, rosa &H00B35CFF&, lavanda &H00FFA4C4&, crema &H00D7EEF8&, dorado &H0054C9FF&.
  • Transparencia \1a: &H00& completamente opaco; &HFF& completamente transparente (a mayor hexadecimal, más transparencia). El fallo de parpadeo en la versión temprana fue por invertir el alfa.
  • PrimaryColour en la línea Style es &HAABBGGRR (AA al principio, sin & final).

4. Fuentes

  • libass usa fontconfig/directwrite; el nombre de la familia debe ser exacto. Compruébalo con PIL:
from PIL import ImageFont
ImageFont.truetype(r"...\fonts\Anton-Regular.ttf", 40).getname()  # ('Anton','Regular')
  • Fuentes de este proyecto: Anton / Archivo Black / Bebas Neue / Permanent Marker / Silkscreen / Rubik Glitch / Bungee / Monoton / Pirata One / UnifrakturCook; las fuentes del sistema Georgia, Microsoft YaHei se pueden usar directamente con \fnGeorgia, \fnMicrosoft YaHei.
  • Permanent Marker en libass equivale aproximadamente a 0.79×fs; hay que ampliar el tamaño de letra / bloque de color según este factor.
  • Los caracteres faltantes (como ♥ ★) se reemplazan automáticamente por ArialMT; se muestran pero con diferente glifo; para precisión usa \fnMicrosoft YaHei.

5. Referencia rápida de etiquetas de animación

EtiquetaUso
\fad(in,out)Fundido de entrada/salida en milisegundos
\move(x1,y1,x2,y2,t1,t2)Desplazamiento (elegir entre \pos y \move; \move tiene prioridad)
\t(t1,t2,\tag...)Interpolación temporizada, ej. \t(0,130,\fscx100\fscy100\blur(0))
\frz / \fscx / \fscyRotación / escala (valores negativos producen volteo)
\blur(n)Desenfoque (muy efectivo para que una palabra grande aparezca borrosa y luego nítida)
\clip(x1,y1,x2,y2)Recorte rectangular (para rebanados/barridos/apariciones)
\org(x,y)Punto central de rotación / escala
\p1 + dibujoRectángulo m 0 0 l w 0 w h 0 h etc.

Error común: dos \t consecutivos sobre la misma propiedad solo se toma uno (por ejemplo, animación de contracción de línea de regla); hay que dividirlo en dos eventos o dos redibujados. Error común: las coordenadas de dibujo \p1 usan el vértice superior izquierdo como ancla, y libass además desplaza todo el bloque hacia arriba h/2; lo más seguro es usar \an7\pos(esquina superior izquierda) + coordenadas absolutas, y para rotación/barrido usar \org para fijar el origen. Error común: para que un bloque de color resalte detrás de una palabra «barriendo», se usa una capa de dibujo con \fscx0 → \t(0,150,\fscx100) y el origen con \org.

6. Comandos de renderizado

6.1 Quemado directo (el más usado)

cd directorio_de_salida
& $ff -v error -y -i _base_30s.mp4 -vf "ass=_s4.ass:fontsdir=fonts" `
  -c:v libx264 -preset medium -crf 16 -pix_fmt yuv420p -movflags +faststart OUT.mp4

30s / 2560×1080 / cantidad de subtítulos en chino ≈ 1–3 minutos.

6.2 Superposición transparente (para usar en software de edición)

& $ff -v error -y -f lavfi -i "[email protected]:s=2560x1080:r=30,format=rgba" `
  -vf "fps=30,ass=_sub.ass:alpha=1" -t 154.6 `
  -c:v libvpx-vp9 -pix_fmt yuva420p -b:v 0 -crf 30 -row-mt 1 -auto-alt-ref 0 `
  -metadata:s:v:0 alpha_mode=1 OUT_alpha.webm
  • El códec de decodificación debe ser -c:v libvpx-vp9; la decodificación nativa vp9 pierde el canal alfa.
  • Superposición por «filtro de color» (mp4 compatible): fondo negro + texto brillante; el software de edición usa modos de fusión Screen/Lighten.

6.3 Extracción de fotograma para verificación (no mires los logs de renderizado, mira la imagen)

& $ff -v error -ss 12.4 -i OUT.mp4 -frames:v 1 -q:v 2 -y _check.jpg

Nota: Cuando -ss se coloca antes de -i (búsqueda en entrada), en algunos casos la línea de tiempo de ASS se redirige con respecto a la salida y la previsualización sale en blanco; para verificar la extracción usa búsqueda en lado de salida (-i OUT.mp4 -ss 12.4) o extrae un segmento completo y luego selecciona.

7. Tabla rápida de fallos

SíntomaCausaSolución
El video completo no tiene ni una letraFormato de timestamp / & final en colores de StyleCambiar a H:MM:SS.cc; quitar & final de colores de Style
Faltan algunas líneasTimestamp de esa línea mal escrito o start>endRevisar línea por línea
Letra muy pequeña / tipografía incorrectaEl nombre de la familia de fuente es incorrectoVerificar con getname() de PIL
Bloque \p1 desplazado hacia arriba/abajoAnclaje de dibujo + libass desplaza h/2 hacia arribaUsar \an7 + coordenadas absolutas de la esquina superior izquierda + fotograma de calibración real
Centro de rotación incorrectoEl centro predeterminado no es el deseadoAñadir \org(x,y)
Fundido no funciona / parpadeo invertidoLa semántica del alfa está invertida&H00 es opaco, &HFF es transparente
Renderizado de 30s solo muestra las primeras 4 líneasEl bucle solo recorrió las primeras líneasRevisar el rango del bucle de generación de eventos
Fallo al renderizar con rutas/nombres de archivo en chinoParámetros del filtro con caracteres no ASCIIUsar nombres de archivo ASCII para ASS y video base + cwd en chino

8. Esqueleto de generador (Python)

def ts(sec):
    h=int(sec//3600); m=int(sec%3600//60)
    return "%d:%02d:%05.2f" % (h,m,sec-h*3600-m*60)

class Ass:
    def __init__(self,path,w=2560,h=1080): self.ev=[]; self.path=path; self.w=w; self.h=h
    def add(self,layer,t0,t1,tags,text): self.ev.append((layer,t0,t1,tags,text))
    def write(self):
        head = open("template_header.ass",encoding="utf-8").read()  # o incluir el encabezado directamente en el código
        lines=[]
        for layer,t0,t1,tags,text in sorted(self.ev,key=lambda e:(e[0],e[1])):
            lines.append("Dialogue: %d,%s,%s,X,,0,0,0,,{%s}%s"%(layer,ts(t0),ts(t1),tags,text))
        open(self.path,"w",encoding="utf-8-sig",newline="\n").write(head+"\n".join(lines)+"\n")

Implementaciones de referencia: 字幕/build/styles_anim.py (S2/S4/S6), flare_wide.py, neon_wide.py, avoid_side2.py.

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

muyunxue/dance-mmd-subtitle-kit

Character-avoiding subtitle layout for the MMD dance videos — measure the dancer's per-frame bounding box, compute a per-cue union, place text in safe side/top columns, and verify zero overlap on every frame. Load this when asked 字幕不要挡住人物/完全不挡/避让, or when text overlaps wings/body and you need a verified-free layout with measured overlap counts.

muyunxue/dance-mmd-subtitle-kit

End-to-end recipe for making subtitles for the MMD dance videos in this workspace (字幕/ project) — probe the source, pick a segment, map LRC cues, choose a style, build ASS, burn, verify, and deliver. Load this when starting or resuming any subtitle task (静态稿/5s小样/30s小样/全片/透明叠加层), when a render "succeeded" but the video has no text, or when you need this project's paths, font list, cue sheet and acceptance criteria.

muyunxue/dance-mmd-subtitle-kit

Design and deliver subtitle style mockups and animated comparison samples for the MMD/K-pop dance videos — S1–S6 style catalogue (Y2K chrome, minimal kinetic, glitch, mix&match editorial, graphic emphasis, hand-marker), PIL/numpy effect recipes, font list, contact-sheet/comparison video conventions, and the parallel-subagent workflow used for S4 vs S6. Load this when asked 出几个静态帧方案/参考女团PV字幕/做个小样/对比几个风格, or when choosing a visual direction before building a full-length subtitle track.

muyunxue/dance-mmd-subtitle-kit

Subject-aware colour grading for the MMD dance videos in this workspace — make the dancer stand out (background dim/cool/desat, subject lift/warm/sharpen/bloom) using either a soft stage-light ellipse or a hard character matte, with ffmpeg recipes, measured parameter sets and known failure modes (cast-shadow matte contamination, banding, truncated sources). Load this when asked to 调色/突出人物/压背景/统一色调, or when a graded clip shows weird bright blobs around the dancer.

Skills relacionados