Cómo traducir subtítulos ASS/SSA sin romper estilos, posiciones ni karaoke
Traduce solo el diálogo visible de un archivo .ass y luego revisa tiempos, etiquetas, karaoke y fuentes. Con un archivo de muestra, un verificador gratuito y una prueba de 9 ejecuciones con un LLM local.

Un archivo de subtítulos ASS o SSA es un pequeño programa: una cabecera, una tabla de estilos y una lista de eventos cronometrados cuyo último campo mezcla diálogo con código de formato. Para traducirlo, cambia solo las palabras legibles de ese último campo, deja todo lo demás intacto byte a byte y después revisa tres cosas que ninguna herramienta de traducción corrige por ti: las fuentes, los códigos de espaciado y las líneas de karaoke.
Tradujimos una muestra de 14 eventos al chino simplificado nueve veces con un modelo local, usando tres prompts distintos, y revisamos cada resultado con un script que escribimos. Los tiempos, las posiciones, los colores, los comentarios y los dibujos sobrevivieron en las nueve. Lo que se rompió fueron las partes del archivo que dan por hecho el inglés: en las nueve, las fuentes de los estilos no tenían caracteres chinos, así que el archivo dependería de que el reproductor sustituyera la fuente, y un espacio duro de la línea en inglés se convirtió en un hueco visible en chino. La línea de karaoke volvió con sus tiempos apuntando a las palabras equivocadas en todas las ejecuciones, y en cuatro ejecuciones algunas sílabas no resaltaron nada en absoluto.
Respuesta rápida: qué traducir y qué dejar en paz
| Parte del archivo | Ejemplo de nuestra muestra | ¿Traducirla? |
|---|---|---|
Cabecera [Script Info] | PlayResX: 1920, WrapStyle: 0 | No. Las posiciones se calculan a partir de estos valores. |
[V4+ Styles] | Style: Default,Trebuchet MS,64,... | No, excepto el nombre de la fuente, que quizá necesites cambiar a propósito |
| Campos 1–9 de los eventos | 0,0:00:01.00,0:00:03.20,Default,Jun,0,0,0, | No. Son capa, tiempos, estilo, hablante, márgenes y efecto. |
| Bloques de anulación | {\i1}, {\an8\pos(960,120)}, {\k25} | No |
| Dibujos | {\p1}m 0 0 l 200 0 200 60 0 60{\p0} | No. Es una forma vectorial, no texto. |
Eventos Comment: | Comment: ...,Earlier draft: Try the stacks. | Opcional. Los comentarios nunca aparecen en pantalla. |
| Notas entre llaves | {TL note: "stacks" means the closed shelves} | Opcional. Los reproductores las ignoran. |
| Diálogo visible | Did you find the second volume? | Sí |
| Códigos de línea | \N, \n, \h | Mantén \N. Decide caso por caso para \n y \h. |
El resto de esta guía explica por qué importa cada fila y cómo comprobar el resultado.
Cómo se construye una línea ASS
Cada línea de la sección [Events] sigue el formato declarado justo encima:
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.
Solo el décimo campo, Text, contiene algo que lea el espectador. La guía del formato de archivo ASS del proyecto libass señala que este último campo «puede contener comas», y por eso una división descuidada por cada coma rompe una línea como Well, if it's there, then, we go now. Una herramienta segura divide solo por las primeras nueve comas.
Dentro de Text, todo lo que está entre llaves es un bloque de anulación. La referencia de etiquetas de anulación de Aegisub define los códigos que encontrarás con más frecuencia:
\Nfuerza un salto de línea en todos los modos de ajuste.\nsolo rompe la línea en el modo de ajuste 2 y, en los demás, es un espacio.\hes un espacio duro.\an8establece la alineación usando la disposición del teclado numérico, así que 8 es arriba en el centro.\pos(960,120)coloca la línea en coordenadas del guion.\k25es una sílaba de karaoke; las duraciones están en centésimas de segundo, así que 25 significa un cuarto de segundo.- Después de
\p1, el texto «se interpretará como instrucciones de dibujo», así que un traductor que «traduzca»m 0 0 l 200 0destruye una forma. - El texto no reconocido dentro de llaves «se ignora silenciosamente», y por eso los archivos de fansub suelen llevar notas del traductor entre llaves.
Las líneas que empiezan por Comment: usan los mismos campos, pero según la guía de libass «no se mostrará nada en pantalla».
Qué probamos
Escribimos sample-source.ass, una escena de 14 eventos ambientada en una librería, con un ejemplo de cada función anterior: cursiva, un salto duro, comas en el diálogo, una nota entre llaves, una línea de comentario, un cartel posicionado, una caja vectorial, un fundido, un espacio duro, un cambio de color con \r, un salto suave, un efecto Banner desplazante y una línea de karaoke de seis sílabas.
Luego pedimos a un modelo local que lo tradujera al chino simplificado de tres maneras:
- Archivo completo. Pegar todo el archivo
.assy pedir de vuelta el archivo traducido. - Solo texto. Enviar únicamente el campo
Textde cada línea de diálogo como JSON, con las etiquetas incluidas, y la instrucción de conservar cada bloque{...}y cada\N,\ny\h. - Protegido. Lo mismo, pero sustituyendo antes cada bloque entre llaves y cada código de línea por un marcador numerado, y restaurando los originales después.
En la segunda y la tercera condición, el script nunca envía al modelo el dibujo vectorial ni la línea de comentario, así que esas líneas solo podían dañarse en la condición de archivo completo.
El modelo fue Qwen 3.6 27B (Q4_K_M) en LM Studio 0.4.8 sobre un Apple M4 Max con 64 GB de memoria, con el razonamiento desactivado y temperatura 0.3. Ejecutamos cada condición tres veces, nueve ejecuciones en total. El primer intento de la tercera ejecución terminó cuando el servidor local cortó la conexión, así que lo reiniciamos y volvimos a ejecutar la tercera ronda. El script es run_llm_ass_test.py, y las nueve salidas se publican sin editar junto a él; el README enumera todos los archivos. Si nunca has configurado un modelo local, nuestra guía de traducción con LLM local cubre los ajustes.
Fue una prueba pequeña de un modelo, un par de idiomas y una muestra. Muestra qué problemas ocurren y cómo detectarlos. No clasifica herramientas ni prompts.
Resultado: la maquinaria sobrevivió; los supuestos del inglés, no
Revisamos cada salida con check_ass_translation.py. La salida completa está en check-results.txt, y results.csv tiene una fila por ejecución, incluidos los problemas que el script no puede ver.
| Comprobación | Archivo completo | Solo texto | Protegido |
|---|---|---|---|
| Tiempos, estilos y campos 1–9 sin cambios | 3 de 3 | 3 de 3 | 3 de 3 |
| Etiquetas de anulación sin cambios | 3 de 3 | 2 de 3 | 3 de 3 |
| Líneas de dibujo y comentarios intactas | 3 de 3 | 3 de 3 | 3 de 3 |
| Fuentes de estilo capaces de dibujar la traducción | 0 de 3 | 0 de 3 | 0 de 3 |
\h y \n dejados como huecos en el texto chino | 3 de 3 | 3 de 3 | 3 de 3 |
| Todas las etiquetas de karaoke conservadas, cada una con texto | 3 de 3 | 0 de 3 | 1 de 3 |
Dos resultados nos sorprendieron. Pegar el archivo completo mantuvo la estructura intacta en las tres ejecuciones, aunque en dos de ellas también tradujo la línea Title de la cabecera. Y el prompt de solo texto, que suena más seguro, produjo las únicas etiquetas rotas. En una ejecución devolvió {\k25}翻{\k30}页,{\k45}开{\k60}灯 para una línea con seis etiquetas de karaoke. Las dos últimas etiquetas y 1,20 segundos de temporización del resaltado desaparecieron, así que el resaltado terminaría mucho antes de la línea. La misma ejecución convirtió Room\h12 is upstairs. en 12\h12号房间在楼上。, con el número de habitación duplicado.
Así que la lección útil no es «usa el prompt X». Es que el daño estructural que temes es fácil de detectar, y el daño que realmente se coló en las nueve ejecuciones está en tres lugares de los que las páginas de herramientas para traducir ASS no hablan.
1. Las fuentes no pueden dibujar el nuevo idioma
Los estilos de la muestra usan Trebuchet MS para el diálogo y Georgia para los carteles, lo cual es normal para una versión en inglés. Ninguna de las dos fuentes contiene caracteres chinos. Cuando dirigimos la prueba de glifos del verificador a los dos archivos de fuentes, los 12 eventos de texto traducidos fallaron en todas las ejecuciones:
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. 书人仅作员工库架闭限
Un reproductor puede sustituir alguna otra fuente instalada, así que el subtítulo podría seguir apareciendo, pero la versión ya no controla su aspecto, y un espectador cuyo sistema carezca de una fuente adecuada podría ver cuadros vacíos. La solución es una edición deliberada del campo Fontname de cada estilo. Cuando cambiamos los tres estilos de una salida a Hiragino Sans GB, una fuente china que viene con macOS, y ejecutamos la prueba de glifos con esa fuente, los errores de glifos se redujeron a cero.
Elige una fuente que tus espectadores realmente tengan, o inclúyela con el vídeo. La guía de libass dice que las versiones deben adjuntar todas las fuentes que usan, preferiblemente en el contenedor MKV. Como la fuente del idioma de destino es nueva, adjuntarla ahora forma parte del trabajo de traducción.
2. Los códigos de espaciado llevan hábitos del inglés
Room\h12 pega «Room» a «12» para que nunca se separen entre líneas. En chino las palabras no se separan con espacios, pero todas las ejecuciones mantuvieron el \h en algún lugar: cinco ejecuciones lo colocaron entre 12号房间 y 在楼上, tres lo pusieron antes del número, y una lo puso entre dos copias del número. De cualquier forma, el espectador ve un espacio suelto. Wait\nhere. tuvo el mismo problema. Con WrapStyle: 0, el \n se muestra como un espacio, así que 在\n这里等 muestra un hueco en medio de una frase de tres palabras.
La estructura aquí está bien; el idioma no. Para un idioma de destino sin espacios entre palabras, elimina \h y \n del texto traducido. Mantén \N solo donde quieras un salto forzado, y colócalo en un punto natural de la frase de destino. El verificador informa de los cambios en los recuentos de \h y \n como advertencias en lugar de errores por esta razón, y avisa cuando uno sobrevive dentro de texto chino, japonés o coreano.
3. La temporización del karaoke pertenece a las palabras originales
La línea de karaoke {\k25}Turn {\k30}the {\k45}page, {\k60}turn {\k40}the {\k80}light sincroniza cada sílaba inglesa con la canción. Una traducción no puede mantener esa temporización de forma significativa, porque las palabras chinas no caen en los mismos tiempos. Nuestras ejecuciones muestran las diferentes formas en que sale mal:
- En cuatro ejecuciones se mantuvieron las seis etiquetas, cada una en una palabra diferente a la anterior. Una de ellas terminó con
{\k40}打{\k80}开, «abrir», y eliminó «light» de la línea por completo. - En cuatro ejecuciones una sílaba no resaltó nada, como
打开{\k40}{\k80}灯(0,40 segundos de resaltado en una sílaba vacía). En dos de esas, una sílaba de 0,45 segundos también resaltó solo una coma. - En una ejecución desaparecieron dos etiquetas, como se describió anteriormente.
El verificador marca una línea de karaoke traducida en el mismo lugar y cualquier sílaba que quede sin texto. La mejor solución es editorial: no traduzcas el karaoke en el mismo lugar. Conserva la línea original con su temporización para cantar, y añade la traducción como un evento separado: copia el evento de karaoke, dale su propio estilo (por ejemplo, más pequeño y colocado abajo), elimina las etiquetas \k y traduce el texto. Vuelve a temporizarlo sílaba por sílaba solo si estás dispuesto a sincronizarlo tú mismo con el audio.
Un flujo de trabajo que resiste
-
Primero, haz que la fuente sea legible. Si el archivo muestra caracteres corruptos, corrige la codificación antes que nada. Nuestra guía de codificación usa ejemplos de SRT, pero los mismos pasos a nivel de byte funcionan para un archivo
.assy mantienen los bytes originales a salvo. El verificador solo lee UTF-8 y UTF-16. -
Decide el alcance. Enumera los estilos y decide cuáles son diálogo, cuáles son carteles en pantalla y cuáles son karaoke. Los carteles suelen necesitar traducción; el karaoke suele necesitar una línea separada; los comentarios y las notas entre llaves son decisión tuya.
-
Traduce solo el campo
Text. Usa una herramienta que analice ASS en lugar de tratarlo como texto plano, o protege las etiquetas tú mismo como en nuestra tercera condición. Mantén el archivo de origen junto a la salida. -
Ejecuta la comprobación estructural.
python3 check_ass_translation.py source.ass translated.assCompara el número de eventos, los tipos de evento, los campos 1–9, los valores de estilo, los bloques de anulación, los dibujos, las líneas de comentario,
\N, las sílabas y duraciones de karaoke, y las líneas que volvieron vacías o sin cambios. No juzga la calidad de la traducción. -
Corrige las fuentes a propósito. Cambia
Fontnameen cada estilo que ahora contenga texto en el idioma de destino y, después, ejecuta la prueba de glifos con el archivo de fuente que vas a distribuir:pip install fonttools python3 check_ass_translation.py source.ass translated.ass --font "Noto Sans SC=/path/to/NotoSansSC-Regular.otf"Un nombre de fuente modificado aparece como una advertencia, así que puedes confirmar que cada cambio fue intencionado.
-
Limpia los códigos de espaciado y el karaoke como se describe arriba.
-
Revísalo con el vídeo. Abre el archivo en Aegisub o en tu reproductor. Comprueba que los carteles siguen encajando en las formas dibujadas detrás de ellos, porque un cuadro
\pconserva su tamaño en inglés mientras que un cartel traducido puede ser mucho más largo o más corto. Comprueba que las líneas no son demasiado largas para el tiempo que permanecen en pantalla. Ninguno de los dos problemas se ve en el propio archivo.
Dónde encaja BookTranslator
El traductor de subtítulos de BookTranslator acepta archivos SRT, VTT, ASS y SSA. Según la página del producto, conserva las marcas de tiempo y el orden de las entradas y mantiene el estilo de ASS y SSA compatible asociado a cada entrada de subtítulo, de modo que no tienes que extraer y volver a insertar el texto tú mismo. Traduce el diálogo con las líneas circundantes como contexto, lo que ayuda con los nombres y los chistes recurrentes a lo largo de un episodio.
No pasamos esta muestra por BookTranslator para este artículo. Sea cual sea la herramienta que uses, ejecuta los pasos 4 a 7 sobre el resultado. Un estilo que conserva su fuente inglesa sigue siendo un estilo que no puede dibujar caracteres chinos, y el karaoke traducido en el mismo lugar todavía requiere una decisión editorial. Para el resto del flujo de trabajo con subtítulos, consulta nuestra guía de traducción de subtítulos con IA, nuestra comparativa de software de traducción de subtítulos y, si tu traducción va a YouTube, el flujo de trabajo para subtítulos de YouTube.
Cuándo convertir a SRT en su lugar
Convertir ASS a SRT antes de traducir elimina los estilos, las posiciones, los dibujos y el karaoke, lo que también elimina la mayoría de los problemas anteriores. Es un intercambio razonable si tu destino solo muestra subtítulos simples, o si el estilo nunca fue importante para el lanzamiento. Es el intercambio equivocado para lanzamientos de anime y música en los que los carteles y el karaoke forman parte de la obra. Decide en función de dónde se mostrará el archivo, no de qué formato es más fácil de traducir.
Obtén los archivos de prueba
Todo lo de esta prueba es libre de reutilizar:
- sample-source.ass: la muestra en inglés de 14 eventos;
- check_ass_translation.py: el verificador (biblioteca estándar de Python; la prueba
--fontnecesita fontTools); - run_llm_ass_test.py: las tres condiciones de prompt para cualquier servidor local compatible con OpenAI;
- results.csv y check-results.txt: resultados por ejecución;
- README.txt: la lista de archivos y la configuración de la prueba, con las nueve salidas sin editar en la carpeta
outputs.
Publicaciones relacionadas




