ASS/SSA-ondertitels vertalen zonder stijlen, posities of karaoke te breken
Vertaal alleen de zichtbare dialoog in een .ass-bestand en controleer daarna timing, tags, karaoke en lettertypen. Met een voorbeeldbestand, een gratis checker en een lokale LLM-test met 9 runs.

Een ASS- of SSA-ondertitelbestand is een klein programma: een header, een tabel met stijlen en een lijst met getimede events waarvan het laatste veld dialoog met opmaakcode combineert. Om het te vertalen, wijzig je alleen de leesbare woorden in dat laatste veld, laat je al het andere byte voor byte intact, en controleer je daarna drie dingen die geen enkele vertaaltool voor je oplost: de lettertypen, de spatiëringscodes en de karaokeregels.
We hebben een voorbeeld met 14 events negen keer naar Vereenvoudigd Chinees vertaald met een lokaal model, met drie verschillende prompts, en elk resultaat gecontroleerd met een script dat we zelf schreven. De timing, posities, kleuren, opmerkingen en tekeningen bleven in alle negen behouden. Wat brak, waren de delen van het bestand die uitgaan van Engels: in alle negen hadden de stijllettertypen geen Chinese tekens, dus het bestand zou erop vertrouwen dat de speler een lettertype vervangt, en een harde spatie uit de Engelse regel werd een zichtbare opening in het Chinees. De karaokeregel kwam in elke run terug met de timing op de verkeerde woorden gericht, en in vier runs lichtten sommige lettergrepen helemaal niets op.
Snel antwoord: wat je vertaalt en wat je met rust laat
| Deel van het bestand | Voorbeeld uit ons voorbeeldbestand | Vertalen? |
|---|---|---|
[Script Info]-header | PlayResX: 1920, WrapStyle: 0 | Nee. Posities worden uit deze waarden berekend. |
[V4+ Styles] | Style: Default,Trebuchet MS,64,... | Nee, behalve de lettertypenaam, die je mogelijk bewust moet wijzigen |
| Eventvelden 1–9 | 0,0:00:01.00,0:00:03.20,Default,Jun,0,0,0, | Nee. Dit zijn laag, timing, stijl, spreker, marges en effect. |
| Override-blokken | {\i1}, {\an8\pos(960,120)}, {\k25} | Nee |
| Tekeningen | {\p1}m 0 0 l 200 0 200 60 0 60{\p0} | Nee. Dit is een vectorvorm, geen tekst. |
Comment:-events | Comment: ...,Earlier draft: Try the stacks. | Optioneel. Opmerkingen verschijnen nooit op het scherm. |
| Notities tussen accolades | {TL note: "stacks" means the closed shelves} | Optioneel. Spelers negeren ze. |
| Zichtbare dialoog | Did you find the second volume? | Ja |
| Regelcodes | \N, \n, \h | Behoud \N. Beslis per geval voor \n en \h. |
De rest van deze gids legt uit waarom elke rij ertoe doet en hoe je het resultaat controleert.
Hoe een ASS-regel is opgebouwd
Elke regel in de sectie [Events] volgt het formaat dat er direct boven wordt gedeclareerd:
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:03.40,0:00:06.10,Default,Mara,0,0,0,,{\i1}I thought it was{\i0} sold out.
Alleen het tiende veld, Text, bevat iets dat een kijker leest. De handleiding voor het ASS-bestandsformaat van het libass-project merkt op dat dit laatste veld "komma's mag bevatten", en daarom breekt een achteloze splitsing op elke komma een regel als Well, if it's there, then, we go now. Een veilige tool splitst alleen op de eerste negen komma's.
Binnen Text is alles tussen accolades een override-blok. De referentiegids voor override-tags van Aegisub definieert de codes die je het vaakst zult tegenkomen:
\Nforceert een regelafbreking in elke wrap-modus.\nbreekt de regel alleen in wrap-modus 2 en is anders een spatie.\his een harde spatie.\an8stelt de uitlijning in volgens de numerieke toetsenindeling, dus 8 is midden boven.\pos(960,120)plaatst de regel op scriptcoördinaten.\k25is een karaoke-lettergreep; de duur is in centiseconden, dus 25 betekent een kwart seconde.- Na
\p1wordt de tekst "geïnterpreteerd als tekeninstructies", dus een vertaler diem 0 0 l 200 0"vertaalt", verwoest een vorm. - Niet-herkende tekst tussen accolades "wordt stilzwijgend genegeerd", daarom bevatten fansub-bestanden vaak vertalersnotities tussen accolades.
Regels die beginnen met Comment: gebruiken dezelfde velden, maar volgens de libass-gids "wordt er niets op het scherm weergegeven."
Wat we hebben getest
We schreven sample-source.ass, een scène met 14 events in een boekwinkel, met één voorbeeld van elk hierboven genoemd kenmerk: cursief, een harde regelafbreking, komma's in dialoog, een notitie tussen accolades, een commentaarregel, een gepositioneerd bord, een vectorkader, een fade, een harde spatie, een kleurverandering met \r, een zachte regelafbreking, een scrollend Banner-effect en een karaokeregel met zes lettergrepen.
Daarna vroegen we een lokaal model om het op drie manieren naar Vereenvoudigd Chinees te vertalen:
- Heel bestand. Plak het volledige
.ass-bestand en vraag om het vertaalde bestand terug. - Alleen tekst. Stuur alleen het veld
Textvan elke dialoogregel als JSON, met de tags inline, en de instructie om elk{...}-blok en elke\N,\nen\hte behouden. - Beschermd. Hetzelfde, maar vervang eerst elk accoladeblok en elke regelcode door een genummerde placeholder, en zet de originelen daarna terug.
In de tweede en derde conditie stuurt het script de vectoriële tekening of de commentaarregel nooit naar het model, dus die regels konden alleen in de heel-bestand-conditie beschadigd raken.
Het model was Qwen 3.6 27B (Q4_K_M) in LM Studio 0.4.8 op een Apple M4 Max met 64 GB geheugen, met thinking uitgeschakeld en temperatuur 0.3. We voerden elke conditie drie keer uit, negen runs in totaal. De eerste poging bij de derde run eindigde toen de lokale server de verbinding verbrak, dus we herstartten hem en voerden de derde ronde opnieuw uit. Het script is run_llm_ass_test.py, en alle negen outputs zijn ongewijzigd daarnaast gepubliceerd; de README somt elk bestand op. Als je nog nooit een lokaal model hebt opgezet, behandelt onze handleiding voor lokaal LLM-vertalen de instellingen.
Dit was een kleine test van één model, één talenpaar en één voorbeeld. Het laat zien welke problemen optreden en hoe je ze kunt opsporen. Het rangschikt geen tools of prompts.
Resultaat: De machinerie overleefde; de Engelse aannames niet
We controleerden elke output met check_ass_translation.py. De volledige output staat in check-results.txt, en results.csv heeft één rij per run, inclusief problemen die het script niet kan zien.
| Controle | Volledig bestand | Alleen tekst | Beveiligd |
|---|---|---|---|
| Timing, stijlen en velden 1–9 ongewijzigd | 3 van 3 | 3 van 3 | 3 van 3 |
| Override-tags ongewijzigd | 3 van 3 | 2 van 3 | 3 van 3 |
| Tekening- en commentaarregels onaangeroerd | 3 van 3 | 3 van 3 | 3 van 3 |
| Stijllettertypen die de vertaling kunnen weergeven | 0 van 3 | 0 van 3 | 0 van 3 |
\h en \n blijven als hiaten in Chinese tekst | 3 van 3 | 3 van 3 | 3 van 3 |
| Alle karaoke-tags behouden, elk met tekst | 3 van 3 | 0 van 3 | 1 van 3 |
Twee resultaten verrasten ons. Het plakken van het hele bestand hield de structuur in alle drie de runs intact, hoewel het in twee ervan ook de Title-regel in de header vertaalde. En de prompt met alleen tekst, die veiliger klinkt, produceerde de enige kapotte tags. In één run gaf het {\k25}翻{\k30}页,{\k45}开{\k60}灯 terug voor een regel met zes karaoke-tags. De laatste twee tags en 1,20 seconden aan highlight-timing waren verdwenen, dus de highlight zou ruim voor het einde van de regel stoppen. Dezelfde run veranderde Room\h12 is upstairs. in 12\h12号房间在楼上。, met het kamernummer twee keer.
De nuttige les is dus niet "gebruik prompt X." Het is dat de structurele schade die je vreest gemakkelijk te detecteren is, en dat de schade die er in alle negen runs daadwerkelijk doorheen glipte op drie plekken zit die de toolpagina's voor ASS-vertaling niet bespreken.
1. De lettertypen kunnen de nieuwe taal niet weergeven
De stijlen van het voorbeeld gebruiken Trebuchet MS voor dialoog en Georgia voor borden, wat normaal is voor een Engelse release. Geen van beide lettertypen bevat Chinese tekens. Toen we de glyph-test van de checker op de twee lettertypebestanden richtten, faalden alle 12 vertaalde tekstgebeurtenissen in elke run:
ERROR event 1: font 'Trebuchet MS' has no glyph for 9 characters, e.g. 了二你到卷吗找第?
ERROR event 7: font 'Georgia' has no glyph for 10 characters, e.g. 书人仅作员工库架闭限
Een speler kan een ander geïnstalleerd lettertype substitueren, dus de ondertitel verschijnt misschien nog wel, maar de release bepaalt niet langer hoe die eruitziet, en een kijker wiens systeem geen geschikt lettertype heeft, kan lege vakjes zien. De oplossing is een bewuste aanpassing van het veld Fontname van elke stijl. Toen we alle drie de stijlen in één output veranderden in Hiragino Sans GB, een Chinees lettertype dat met macOS wordt meegeleverd, en de glyph-test tegen dat lettertype uitvoerden, gingen de glyph-fouten naar nul.
Kies een lettertype dat je kijkers daadwerkelijk hebben, of lever het mee met de video. De libass-gids zegt dat releases elk lettertype dat ze gebruiken moeten bijvoegen, bij voorkeur in de MKV-container. Omdat het lettertype voor de doeltaal nieuw is, is het bijvoegen ervan nu onderdeel van de vertaaltaak.
2. Spatiëringscodes dragen Engelse gewoonten met zich mee
Room\h12 plakt "Room" aan "12" zodat ze nooit over regels splitsen. In het Chinees worden woorden niet door spaties gescheiden, maar elke run hield de \h ergens: vijf runs plaatsten hem tussen 12号房间 en 在楼上, drie zetten hem voor het nummer, en één zette hem tussen twee kopieën van het nummer. Hoe dan ook ziet de kijker een losse spatie. Wait\nhere. had hetzelfde probleem. Met WrapStyle: 0 wordt de \n als een spatie weergegeven, dus 在\n这里等 toont een gat midden in een zin van drie woorden.
De structuur is hier prima; de taal niet. Voor een doeltaal zonder spaties tussen woorden, verwijder \h en \n uit de vertaalde tekst. Behoud \N alleen waar je een geforceerde regelafbreking wilt, en plaats die op een natuurlijk punt in de doelszin. De checker rapporteert gewijzigde aantallen \h en \n daarom als waarschuwingen in plaats van fouten, en waarschuwt wanneer er één overleeft binnen Chinese, Japanse of Koreaanse tekst.
3. Karaoke-timing hoort bij de oorspronkelijke woorden
De karaoke-regel {\k25}Turn {\k30}the {\k45}page, {\k60}turn {\k40}the {\k80}light timet elke Engelse lettergreep op het lied. Een vertaling kan die timing niet zinvol behouden, omdat de Chinese woorden niet op dezelfde beats vallen. Onze runs laten de verschillende manieren zien waarop het misgaat:
- In vier runs werden alle zes tags behouden, elk op een ander woord dan voorheen. Een ervan eindigde met
{\k40}打{\k80}开, "open", en liet "light" helemaal uit de regel vallen. - In vier runs highlightte een lettergreep niets, zoals
打开{\k40}{\k80}灯(0,40 seconden highlight op een lege lettergreep). In twee daarvan highlightte een lettergreep van 0,45 seconden ook alleen een komma. - In één run verdwenen twee tags, zoals hierboven beschreven.
De checker markeert een karaoke-regel die ter plaatse is vertaald en elke lettergreep die zonder tekst achterblijft. De betere oplossing is redactioneel: vertaal karaoke niet ter plaatse. Behoud de originele getimede regel om mee te zingen, en voeg de vertaling toe als een aparte gebeurtenis: kopieer de karaoke-gebeurtenis, geef die een eigen stijl (bijvoorbeeld kleiner en onderaan geplaatst), verwijder de \k-tags en vertaal de tekst. Her-timing per lettergreep doe je alleen als je bereid bent om zelf op de audio te timen.
Een werkwijze die standhoudt
-
Maak de bron eerst leesbaar. Als het bestand onleesbare tekens toont, los dan eerst de codering op. Onze coderingsgids gebruikt SRT-voorbeelden, maar dezelfde stappen op byteniveau werken voor een
.ass-bestand en houden de originele bytes veilig. De checker leest alleen UTF-8 en UTF-16. -
Bepaal de scope. Maak een lijst van de stijlen en bepaal welke dialoog zijn, welke on-screen borden, en welke karaoke. Borden moeten meestal vertaald worden; karaoke heeft meestal een aparte regel nodig; opmerkingen en notities tussen accolades zijn aan jou om te beslissen.
-
Vertaal alleen het veld
Text. Gebruik een tool die ASS parseert in plaats van het als platte tekst te behandelen, of bescherm de tags zelf zoals in onze derde voorwaarde. Houd het bronbestand naast de output. -
Voer de structurele controle uit.
python3 check_ass_translation.py source.ass translated.assHet vergelijkt het aantal gebeurtenissen, gebeurtenistypen, velden 1–9, stijlwaarden, override-blokken, tekeningen, commentaarregels,
\N, karaoke-lettergrepen en -duren, en regels die leeg of ongewijzigd terugkwamen. Het beoordeelt de vertaalkwaliteit niet. -
Pas de lettertypen bewust aan. Wijzig
Fontnamein elke stijl die nu tekst in de doeltaal bevat en voer vervolgens de glyph-test uit met het lettertypebestand dat je gaat leveren:pip install fonttools python3 check_ass_translation.py source.ass translated.ass --font "Noto Sans SC=/path/to/NotoSansSC-Regular.otf"Een gewijzigde lettertypenaam verschijnt als waarschuwing, zodat je kunt bevestigen dat elke wijziging bedoeld was.
-
Ruim spatiëringscodes en karaoke op zoals hierboven beschreven.
-
Bekijk het met de video. Open het bestand in Aegisub of je speler. Controleer of borden nog steeds passen bij de vormen die erachter zijn getekend, want een
\p-box behoudt zijn Engelse grootte terwijl een vertaald bord veel langer of korter kan zijn. Controleer of regels niet te lang zijn voor hun schermtijd. Geen van beide problemen is zichtbaar in het bestand zelf.
Waar BookTranslator past
BookTranslator's Subtitle Translator accepteert SRT-, VTT-, ASS- en SSA-bestanden. Volgens de productpagina blijven tijdstempels en cue-volgorde behouden en blijft ondersteunde ASS- en SSA-styling aan elk ondertitelitem gekoppeld, zodat je de tekst niet zelf hoeft te extraheren en opnieuw in te voegen. Het vertaalt dialoog met de omliggende regels als context, wat helpt bij namen en running jokes in een hele aflevering.
We hebben dit voorbeeld voor dit artikel niet door BookTranslator gehaald. Welke tool je ook gebruikt, voer stappen 4 tot en met 7 uit op het resultaat. Een stijl die zijn Engelse lettertype behoudt, is nog steeds een stijl die geen Chinees kan weergeven, en karaoke die ter plaatse is vertaald, vereist nog steeds een redactionele beslissing. Voor de rest van de ondertitelworkflow, zie onze AI-ondertitelvertaalgids, onze vergelijking van ondertitelvertaalsofware, en, als je vertaling naar YouTube gaat, de YouTube-ondertitelworkflow.
Wanneer je in plaats daarvan naar SRT converteert
ASS naar SRT converteren vóór het vertalen verwijdert de stijlen, posities, tekeningen en karaoke, wat ook de meeste van de bovenstaande problemen wegneemt. Dat is een redelijke ruil als je bestemming alleen platte ondertitels toont, of als de styling nooit belangrijk was voor de release. Het is de verkeerde ruil voor anime- en muziekreleases waarbij borden en karaoke deel uitmaken van het werk. Beslis op basis van waar het bestand getoond zal worden, niet op basis van welk formaat makkelijker te vertalen is.
Download de testbestanden
Alles uit deze test is vrij te hergebruiken:
- sample-source.ass: het Engelse voorbeeld met 14 events;
- check_ass_translation.py: de checker (Python-standaardbibliotheek; de
--font-test vereist fontTools); - run_llm_ass_test.py: de drie promptcondities voor elke OpenAI-compatibele lokale server;
- results.csv en check-results.txt: resultaten per run;
- README.txt: de bestandslijst en testinstellingen, met de negen onbewerkte outputs in de map
outputs.
Gerelateerde berichten




