Sous-titres chinois pour vidéos — traduction et incrustation
Prend une vidéo anglaise déjà présente sur disque et produit une version incrustée en chinois simplifié (hardcoded), accompagnée d'un fichier SRT correspondant.
Le téléchargement est délibérément hors scope. Supposez que le MP4 source est déjà présent.
Le pipeline est indépendant du sujet — il a été construit sur une vidéo de mouvement Apex de 22 minutes, mais rien dans les scripts ne connaît ou ne se soucie du contenu. Ce qui change par vidéo, c'est le glossaire et la position de la bande de sous-titres.
À quoi ressemble un bon résultat
La personne qui utilise ce skill tient à un rendu spécifique, déjà établi. Ce ne sont pas des paramètres par défaut à reconsidérer à chaque fois — ils ont été obtenus en itérant sur des résultats réels, et les modifier silencieusement sera traité comme une régression :
- Chinois simplifié uniquement. Jamais mélangé avec du traditionnel. Vérifier avant de livrer.
- Une seule ligne par sous-titre, toujours. Les sous-titres sur deux lignes sont le reproche le plus fréquent. Si une ligne est trop longue, divisez-la en deux sous-titres consécutifs plutôt que de la faire passer à la ligne.
build_srt.pyapplique cette règle. - Les sous-titres sont courts. "Une ligne" n'est pas une licence pour une ligne très large. Visez au maximum ~1100px de largeur rendue (environ 57% de la largeur d'une image en 1080p).
- Pas de fond. Texte blanc, contour dur foncé, ombre douce foncée.
- Police Source Han Sans Bold (incluse dans
assets/NotoSansSC-Bold.ttf). Droite et grasse, avec des caractères latins solides — ce genre de vidéo contient beaucoup de jargon anglais inséré dans des phrases chinoises, et une police d'affichage gère mal cela. - Le jargon que la communauté utilise réellement en anglais reste en anglais. Quels termes sont concernés est une question par sujet, et c'est à cela que répondent les glossaires.
- Les cartes-chapitres incrustées reçoivent une ligne chinoise en dessous, pas au-dessus.
Workflow
1. Analyser la source et choisir un glossaire
ffprobe -v error -show_entries format=duration -show_entries stream=codec_type,codec_name,width,height,r_frame_rate -of default=nw=1 source.mp4
Noter exactement la durée et les fps — chaque étape ultérieure en dépend.
Ensuite, déterminer le sujet de la vidéo et lire references/glossaries/README.md, qui oriente vers le fichier approprié et indique quelles sections de ce fichier lire. Lire la section 字幕使用原则 du glossaire correspondant en intégralité avant de traduire — elle est courte et contient les conventions pour ce jeu.
Glossaires inclus : Apex Legends, Warframe, osu!, Minecraft (速通/MCSR), StarCraft (星际争霸), Counter-Strike (反恐精英), ARC Raiders.
S'il n'y a pas de glossaire pour cette vidéo, c'est le cas normal. Traduire en utilisant les noms officiels simplifiés vérifiables, tenir une liste des termes que vous avez dû décider, et remettre cette liste à la fin. Si un terme n'a pas de nom chinois officiel, utiliser une traduction descriptive et préciser qu'elle n'est pas officielle — ne pas présenter une supposition comme établie. N'inventez jamais un nom pour quelque chose qui en a déjà un.
2. Obtenir une transcription anglaise avec minutage
Si la vidéo provient de YouTube, ses sous-titres automatiques sont une base utilisable :
yt-dlp --write-auto-subs --sub-langs "en.*" --skip-download. Ce sont des sous-titres déroulants avec des balises temporelles au niveau des mots, alors dédupliquez-les en segments de phrases.
Les sous-titres automatiques déforment gravement le jargon et vous devez le corriger pendant la traduction. La reconnaissance vocale transcrit phonétiquement à partir d'un modèle d'anglais général, donc chaque terme de domaine qui n'est pas un mot courant revient sous la forme d'un mot plausible mais incorrect. Exemples réels tirés d'une vidéo de mouvement Apex : "forward rez/raft/raz" → RAS, "Neor strafe" → Neo strafe, "pedo strafe" → Pito strafe, "mantel boost" → mantle boost, "alerts" → lurches, "my VO was so high" → my velo (velocity), "I couldn't attach out of that" → couldn't tap-strafe out of that. Attendez-vous au même type de dégradation dans toute vidéo riche en jargon — le glossaire vous permet de le reconnaître.
Lorsque la parole est vraiment irrécupérable — effets musicaux, cris qui se chevauchent — laissez le champ zh vide pour ce segment afin qu'il soit supprimé, et informez l'utilisateur des horodatages que vous avez supprimés. Inventer une ligne plausible est pire que pas de ligne.
3. Traduire en un JSON de segments
[{"i": 1, "start": 0.24, "end": 4.90,
"en": "Seeing movement players pull off tricks like these is super cool and all, but",
"zh": "看身法玩家秀出这种操作确实很酷,但真正的问题是"}]
Conserver en — il n'est pas décoratif. build_srt.py l'utilise pour distinguer une continuation de phrase d'un énoncé séparé lorsqu'il décide si deux sous-titres peuvent être fusionnés, ce qui évite des enchaînements comme 算了好 ou 是,长官你好啊.
4. Générer le SRT
python scripts/build_srt.py segments.json sub.srt --font assets/NotoSansSC-Bold.ttf
Il affiche un rapport. Traiter les valeurs non nulles pour overlaps, multiline, latin_cjk_runons ou term_split_across_cues comme des bogues à corriger avant l'encodage. Quelques sous-titres under_0.35s sont acceptables lorsqu'il s'agit d'interjections de 1 à 3 caractères — vérifiez-les, ne supposez pas.
5. Trouver et traduire les cartes-chapitres incrustées
python scripts/find_chapters.py source.mp4
Les créateurs incrustent souvent des cartes-chapitres dans la vidéo plutôt que d'utiliser les chapitres YouTube, donc les métadonnées n'en montrent aucune. Ce script signale les fenêtres candidates ; extrayez une image de chacune et lisez le texte réel de la carte avant d'écrire la traduction. Produire chapters.json : [{"start":42,"end":46,"zh":"第 1 章:定义 lurch 组合"}].
6. Vérifier les endroits où les sous-titres entreraient en collision avec du texte à l'écran
Les cartes de fin sont le coupable habituel — les sous-titres à la position normale atterrissent sur les réseaux sociaux du créateur. Extrayez une image, trouvez l'espace libre, et déclarez-le :
[{"from": 1334.0, "to": 100000, "bottom": 820}]
La bande de sous-titres par défaut se situe au-dessus d'un HUD FPS typique. Un autre jeu, ou un contenu non ludique, peut placer ses propres éléments à cet endroit — une minimap de MOBA, une ligne de jugement de jeu rythmique, un tiers inférieur de talk. Extrayez une image et examinez avant d'accepter la position par défaut.
7. Générer le calque et encoder
python scripts/build_overlay.py sub.srt ov --font assets/NotoSansSC-Bold.ttf \
--duration 1354.351 --chapters chapters.json --avoid avoid.json
python scripts/burn_in.py source.mp4 ov/concat.txt out.mp4
Vérifiez que le décalage (drift) signalé pour le calque est de quelques millisecondes, pas de centaines.
Avant de vous lancer dans un encodage d'environ 20 minutes, composez une image PNG du calque sur une vraie image avec PIL et regardez-la. Cela coûte quelques secondes et détecte les erreurs de position et de police qui n'apparaîtraient autrement que 20 minutes plus tard.
8. Vérifier
python scripts/verify.py out.mp4 --expect-frames <frames> \
--contact-sheet sheet.jpg --at 75 300 660 945 1340
Regardez la planche. Confirmez : une seule ligne, lisible sur des images claires, lignes de chapitre sous leurs cartes, rien ne chevauche le HUD ou le texte de fin.
9. Corrections ultérieures — fusionner (splice), ne pas ré-encoder
Lorsque l'utilisateur demande de modifier quelques lignes (cela arrivera), reconstruisez le SRT, faites un diff avec le précédent pour trouver quels sous-titres ont changé, puis :
python scripts/splice.py out.mp4 source.mp4 sub.srt out_fixed.mp4 \
--font assets/NotoSansSC-Bold.ttf --change-from 310 --change-to 316 \
--duration 1354.351 --chapters chapters.json --avoid avoid.json
python scripts/verify.py out_fixed.mp4 --expect-frames <frames> --seams 310 316
15 secondes au lieu de 20 minutes. Le nombre d'images doit être identique.
Livrables
En plus de out.mp4, remettez le SRT (dialogue plus lignes de chapitre, fusionnés et renumérotés) afin que les sous-titres puissent être modifiés ultérieurement sans refaire le travail. Proposez également un titre et une description en chinois — si la vidéo est une republication, signalez que la description originale à la première personne implique la paternité, et que les blocs d'attribution musicale doivent rester dans leur anglais d'origine car la licence exige cette forme exacte.
Si vous avez dû trancher pour des termes qui n'étaient pas dans un glossaire, listez-les. Un terme décidé une fois et écrit vaut plus que la même décision prise différemment la prochaine fois ; references/glossaries/README.md explique comment transformer une telle liste en fichier de glossaire.
Documentation de référence
references/glossaries/README.md— quel glossaire lire, quelles sections de celui-ci, et quoi faire quand la vidéo n'en a pas. Commencez ici.references/glossaries/*.md— les glossaires eux-mêmes. Volumineux. Lisez la section des principes et les sections pertinentes ; utilisez grep pour les termes individuels.references/pipeline.md— notes techniques et pièges spécifiques de ce pipeline. Lisez-le avant de déboguer quoi que ce soit qui ressemble à un problème de minutage, de fusion ou de rendu ; la plupart ont déjà été diagnostiqués une fois.