CommunityRédaction et éditiongithub.com

muyunxue/dance-mmd-subtitle-kit

Règles strictes, modèles, commandes ffmpeg et diagnostic des échecs pour la création de sous-titres ASS/SSA et leur incrustation avec libass sur cette machine. À charger avant d'écrire un fichier ASS, quand une incrustation « réussit » mais n'affiche aucun texte, quand le texte est mal placé/trop grand, quand les dessins \p1 sont décalés, ou quand vous avez besoin de la recette d'exportation en superposition transparente. Contient les pièges exacts rencontrés dans ce projet (format d'horodatage, esperluette finale de couleur de style, répertoire de polices, ancrage de dessin, \t enchaîné, dimensionnement de Permanent Marker).

Qu'est-ce que dance-mmd-subtitle-kit ?

Ce kit est un manuel de terrain dédié à l'écriture de fichiers ASS et à leur incrustation via libass sous Windows, avec des recettes, des pièges et un diagnostic des échecs. Il couvre les erreurs réelles rencontrées dans le projet (format d'horodatage, esperluette finale dans les couleurs de style, répertoire de polices, ancrage de dessin \p1, \t enchaîné, dimensionnement de Permanent Marker, etc.). Le kit fournit un modèle d'en-tête ASS, la sémantique des couleurs/alpha (BBGGRR vs AABBGGRR), la vérification des noms de police via PIL, un tableau de rendu des balises d'animation (\fad, \move, \t, \clip...), les commandes de rendu direct (incrustation avec ass=) et de superposition transparente (alpha=1 vers VP9), la commande d'extraction d'images de contrôle, un squelette de générateur Python, ainsi qu'un tableau de dépannage rapide. Il s'applique à tout projet vidéo sous Windows (ou WSL) où libass est utilisé via ffmpeg, et aide à éviter les erreurs silencieuses qui produisent un fichier vidéo mais sans sous-titres.

Compatible avec~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 Rédaction et édition skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

Demander à votre IA préférée

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

Documentation

Manuel pratique d'écriture ASS / incrustation libass

1. Modèle d'en-tête (à copier directement)

[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. Quatre pièges fatals de format (tous rencontrés dans ce projet)

  1. L'horodatage doit être H:MM:SS.cc
    • Correct : 0:00:01.50, 0:01:02.30
    • Erroné : 0:01.50 (libass signale Bad timestamp, la ligne entière est ignorée → pas de sous-titres sur toute la vidéo, mais ffmpeg retourne 0)
  2. La couleur de la ligne Style ne doit pas se terminer par &
    • Correct : &H00F4F1EA,&H00F4F1EA,&H00140F11,&HFF000000
    • Erroné : &H00F4F1EA&,... → L'analyse de la ligne Style échoue → pareil, « succès mais pas de texte »
    • Dans les balises inline des événements, la couleur doit avoir & : \1c&H00F4F1EA&
  3. Le répertoire de polices fontsdir doit être un chemin relatif + répertoire de travail
    • Placez fonts/ dans le répertoire de sortie, cd dans ce répertoire puis ass=x.ass:fontsdir=fonts.
    • Les chemins absolus avec lettre de lecteur et deux-points sont risqués dans le filtergraph ; les chemins relatifs avec caractères chinois fonctionnent (le cwd peut être en chinois, mais les paramètres du filtre doivent être en ASCII de préférence).
  4. Le fichier ASS doit être écrit en utf-8-sig, avec un nom de fichier ASCII
    • Les noms de fichier en chinois sont instables dans les paramètres du filtre ; utilisez _s4.ass par exemple.

Commande de diagnostic (voir ce que libass lit réellement) :

& $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. Sémantique des couleurs / alpha

  • Couleur : &HBBGGRR& (ordre Bleu-Vert-Rouge), ex : blanc &H00F4F1EA&, noir d'encre &H00140F11&, rose &H00B35CFF&, lavande &H00FFA4C4&, crème &H00D7EEF8&, or &H0054C9FF&.
  • Transparence \1a : &H00& complètement opaque ; &HFF& complètement transparent (plus le hexadécimal est élevé, plus c'est transparent). Les clignotements défaillants de la version de développement initiale étaient dus à un alpha inversé.
  • La PrimaryColour de la ligne Style est &HAABBGGRR (AA en premier, sans & final).

4. Polices

  • libass utilise fontconfig/directwrite, le nom de famille doit être exact. Vérifiez avec PIL :
from PIL import ImageFont
ImageFont.truetype(r"...\fonts\Anton-Regular.ttf", 40).getname()  # ('Anton','Regular')
  • Polices de ce projet : Anton / Archivo Black / Bebas Neue / Permanent Marker / Silkscreen / Rubik Glitch / Bungee / Monoton / Pirata One / UnifrakturCook ; les polices système Georgia, Microsoft YaHei peuvent être utilisées directement avec \fnGeorgia, \fnMicrosoft YaHei.
  • Permanent Marker dans libass fait environ 0,79× fs, donc agrandissez la taille de police / la taille des blocs de couleur selon ce facteur.
  • En cas de glyphes manquants (comme ♥ ★), le remplacement revient automatiquement à ArialMT, ce qui peut s'afficher mais avec une forme différente ; pour une précision maximale, utilisez \fnMicrosoft YaHei.

5. Référence rapide des balises d'animation

BaliseUtilisation
\fad(in,out)Fondu en millisecondes
\move(x1,y1,x2,y2,t1,t2)Déplacement (à choisir avec \pos, move est prioritaire)
\t(t1,t2,\tag...)Interpolation temporelle, ex \t(0,130,\fscx100\fscy100\blur(0))
\frz / \fscx / \fscyRotation/échelle (les valeurs négatives peuvent faire un flip)
\blur(n)Flou (efficace pour un grand mot qui devient flou puis net)
\clip(x1,y1,x2,y2)Recadrage rectangulaire (pour les effets de coupe, de balayage, d'apparition)
\org(x,y)Centre de rotation/échelle
\p1 + dessinRectangle m 0 0 l w 0 w h 0 h, etc.

Piège : Deux \t consécutifs sur la même propriété n'en prennent qu'un (ex : animation de rétrécissement d'une ligne de règle). Solution : diviser en deux événements / deux redessins. Piège : Les coordonnées du dessin \p1 sont ancrées en haut à gauche, et libass décale également l'ensemble vers le haut de h/2 ; utilisez \an7\pos(haut-gauche) + coordonnées absolues pour la stabilité, et \org pour la rotation/le balayage. Piège : Pour les surlignements qui « balayent » derrière le mot, utilisez une couche de dessin \fscx0 → \t(0,150,\fscx100) avec \org comme origine.

6. Commandes de rendu

6.1 Incrustation directe (la plus courante)

cd répertoire_de_sortie
& $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

30 s / 2560×1080 / volume de sous-titres chinois ≈ 1–3 minutes.

6.2 Calque de superposition transparent (pour logiciel de montage)

& $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
  • Le décodeur doit être -c:v libvpx-vp9 ; le décodeur natif vp9 perd l'alpha.
  • Alternative « superposition par écran » mp4 priorisant la compatibilité : fond noir + texte lumineux, le logiciel de montage utilise le mode Screen/Lighten.

6.3 Capture d'image de contrôle (ne regardez pas les logs de rendu, regardez l'image)

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

Attention : lorsque -ss est placé avant -i (recherche en entrée), dans certains cas la timeline ASS est redirigée par rapport à la sortie, ce qui donne un aperçu vide ; pour la capture de vérification, utilisez la recherche côté sortie (-i OUT.mp4 -ss 12.4) ou extrayez un segment entier puis choisissez.

7. Tableau de dépannage rapide

PhénomèneCauseCorrection
Aucun texte sur toute la vidéoFormat d'horodatage / Esperluette finale dans la couleur StylePassez à H:MM:SS.cc ; supprimez le & final dans les couleurs Style
Certaines phrases manquentHorodatage de la phrase erroné ou start>endVérifiez phrase par phrase
Texte très petit / police incorrecteNom de famille de police erronéVérifiez avec PIL getname()
Bloc \p1 décalé vers le haut/basAncrage du dessin + décalage libass de h/2Utilisez \an7 + coordonnées absolues en haut à gauche + étalonnage par image test
Centre de rotation incorrectLe centre par défaut n'est pas celui souhaitéAjoutez \org(x,y)
Fondu non effectué / clignotement inverséSémantique alpha inversée&H00 opaque, &HFF transparent
Rendu de 30 s n'affiche que les 4 premières phrasesLa boucle ne parcourt que les premières phrasesVérifiez la plage de la boucle de génération d'événements
Échec du rendu avec chemin/nom de fichier chinoisCaractères non-ASCII dans les paramètres du filtreUtilisez un nom de fichier ASCII pour ASS et les vidéos + cwd en chinois

8. Structure du générateur (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()  # ou intégré dans le code
        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")

Implémentations de référence : sous-titres/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 associés