BookTranslator
BookTranslator

איך לתרגם כתוביות ASS/SSA בלי לשבור סגנונות, מיקומים או קריוקי

תרגמו רק את הדיאלוג הנראה לעין בקובץ ‎.ass, ואז בדקו תזמון, תגיות, קריוקי וגופנים. עם קובץ דוגמה, בודק חינמי ובדיקה של תשע הרצות מודל שפה מקומי.

BookTranslator

BookTranslator Team

11 min read

קובץ כתוביות ASS או SSA הוא תוכנית קטנה: כותרת, טבלת סגנונות ורשימת אירועים מתוזמנים שהשדה האחרון שלהם מערבב דיאלוג עם קוד עיצוב. כדי לתרגם אותו, משנים רק את המילים הקריאות באותו שדה אחרון, משאירים את כל השאר ללא שינוי בייט אחר בייט, ואז בודקים שלושה דברים שאף כלי תרגום לא מתקן עבורכם: הגופנים, קודי הריווח ושורות הקריוקי.

תרגמנו דוגמה בת 14 אירועים לסינית מפושטת תשע פעמים עם מודל מקומי, באמצעות שלוש הנחיות שונות, ובדקנו כל תוצאה עם סקריפט שכתבנו. התזמון, המיקומים, הצבעים, ההערות והציורים שרדו בכל תשע הפעמים. מה שנשבר היו החלקים בקובץ שמניחים אנגלית: בכל תשע הפעמים לגופנים בסגנונות לא היו תווים סיניים, כך שהקובץ היה תלוי בנגן שיחליף גופן, ורווח קשיח מהשורה האנגלית הפך לפער נראה לעין בסינית. שורת הקריוקי חזרה עם תזמון שמצביע על המילים הלא נכונות בכל הרצה, ובארבע הרצות חלק מההברות לא הדגישו דבר בכלל.

תשובה מהירה: מה לתרגם ומה להשאיר ללא שינוי

חלק בקובץדוגמה מהקובץ שלנולתרגם?
כותרת [Script Info]PlayResX: 1920, WrapStyle: 0לא. המיקומים מחושבים מהערכים האלה.
[V4+ Styles]Style: Default,Trebuchet MS,64,...לא, למעט שם הגופן, שאולי תצטרכו לשנות בכוונה
שדות אירוע 1–90,0:00:01.00,0:00:03.20,Default,Jun,0,0,0,לא. אלה שכבה, תזמון, סגנון, דובר, שוליים ואפקט.
בלוקי עקיפה{\i1}, {\an8\pos(960,120)}, {\k25}לא
ציורים{\p1}m 0 0 l 200 0 200 60 0 60{\p0}לא. זו צורה וקטורית, לא טקסט.
אירועי Comment:Comment: ...,Earlier draft: Try the stacks.אופציונלי. הערות לעולם לא מופיעות על המסך.
הערות בסוגריים מסולסלים{TL note: "stacks" means the closed shelves}אופציונלי. הנגנים מתעלמים מהן.
דיאלוג נראה לעיןDid you find the second volume?כן
קודי שורה\N, \n, \hהשאירו \N. החליטו בכל מקרה לגופו לגבי \n ו-\h.

שאר המדריך הזה מסביר מדוע כל שורה חשובה וכיצד לבדוק את התוצאה.

כיצד בנויה שורת ASS

כל שורה בקטע [Events] עוקבת אחרי הפורמט שהוצהר ממש מעליה:

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.

רק השדה העשירי, Text, מכיל משהו שהצופה קורא. מדריך פורמט קובץ ASS של פרויקט libass מציין ששדה אחרון זה "רשאי להכיל פסיקים", ולכן פיצול רשלני לפי כל פסיק שובר שורה כמו Well, if it's there, then, we go now. כלי בטוח מפצל רק לפי תשעת הפסיקים הראשונים.

בתוך Text, כל מה שנמצא בסוגריים מסולסלים הוא בלוק עקיפה. מדריך תגי העקיפה של Aegisub מגדיר את הקודים הנפוצים ביותר שתפגשו:

  • \N כופה שבירת שורה בכל מצב גלישה. \n שובר את השורה רק במצב גלישה 2, ובמצבים אחרים הוא רווח. \h הוא רווח לא שביר.
  • \an8 קובע יישור לפי פריסת לוח המקשים המספרי, כך ש-8 הוא מרכז עליון. \pos(960,120) ממקם את השורה בקואורדינטות התסריט.
  • \k25 היא הברה בקריוקי; משכים נמדדים בסנטישניות, כך ש-25 פירושו רבע שנייה.
  • לאחר \p1, הטקסט "יתפרש כהוראות ציור", ולכן מתרגם ש"מתרגם" m 0 0 l 200 0 הורס צורה.
  • טקסט לא מזוהה בתוך סוגריים מסולסלים "מתעלמים ממנו בשקט", ולכן קבצי פאנסב לעתים קרובות מכילים הערות מתרגם בסוגריים מסולסלים.

שורות שמתחילות ב-Comment: משתמשות באותם שדות, אך לפי מדריך libass "שום דבר לא יוצג על המסך".

מה בדקנו

כתבנו את sample-source.ass, סצנה בת 14 אירועים המתרחשת בחנות ספרים, עם דוגמה אחת מכל תכונה שלמעלה: נטוי, שבירה קשה, פסיקים בדיאלוג, הערה בסוגריים מסולסלים, שורת הערה, שלט ממוקם, תיבת וקטור, דהייה, רווח קשיח, שינוי צבע עם \r, שבירה רכה, אפקט Banner גולל, ושורת קריוקי בת שש הברות.

לאחר מכן ביקשנו ממודל מקומי לתרגם אותו לסינית מפושטת בשלוש דרכים:

  1. קובץ שלם. הדביקו את כל קובץ ה-.ass ובקשו בחזרה את הקובץ המתורגם.
  2. טקסט בלבד. שלחו רק את שדה Text של כל שורת דיאלוג כ-JSON, עם התגים בתוך הטקסט, ואת ההוראה לשמור על כל בלוק {...} ועל כל \N, \n ו-\h.
  3. מוגן. אותו דבר, אך החליפו תחילה כל בלוק סוגריים מסולסלים וקוד שורה במציין מקום ממוספר, והחזירו את המקוריים afterwards.

בתנאים השני והשלישי התסריט לעולם אינו שולח למודל את ציור הווקטור או את שורת ההערה, כך שאותן שורות יכלו להיפגע רק בתנאי הקובץ השלם.

המודל היה Qwen 3.6 27B (Q4_K_M) ב-LM Studio 0.4.8 על Apple M4 Max עם 64 GB זיכרון, עם חשיבה כבויה וטמפרטורה 0.3. הרצנו כל תנאי שלוש פעמים, תשע הרצות בסך הכל. הניסיון הראשון בהרצה השלישית הסתיים כשהשרת המקומי ניתק את החיבור, אז הפעלנו אותו מחדש והרצנו את הסיבוב השלישי שוב. התסריט הוא run_llm_ass_test.py, וכל תשע הפלטים מפורסמים ללא עריכה לצידו; ה-README מפרט כל קובץ. אם מעולם לא הגדרתם מודל מקומי, מדריך התרגום עם LLM מקומי שלנו מכסה את ההגדרות.

זה היה מבחן קטן של מודל אחד, זוג שפות אחד ודוגמה אחת. הוא מראה אילו בעיות מתרחשות וכיצד לתפוס אותן. הוא אינו מדרג כלים או פרומפטים.

תוצאה: המכונה שרדה; ההנחות האנגליות לא

בדקנו כל פלט עם check_ass_translation.py. הפלט המלא נמצא ב-check-results.txt, ול-results.csv יש שורה לכל הרצה, כולל בעיות שהתסריט אינו יכול לראות.

בדיקהקובץ שלםטקסט בלבדמוגן
תזמון, סגנונות ושדות 1–9 ללא שינוי3 מתוך 33 מתוך 33 מתוך 3
תגי עקיפה ללא שינוי3 מתוך 32 מתוך 33 מתוך 3
שורות ציור והערה ללא נגיעה3 מתוך 33 מתוך 33 מתוך 3
גופני סגנון המסוגלים לצייר את התרגום0 מתוך 30 מתוך 30 מתוך 3
\h ו-\n נשארים כרווחים בטקסט הסיני3 מתוך 33 מתוך 33 מתוך 3
כל תגי הקריוקי נשמרו, כל אחד עם טקסט3 מתוך 30 מתוך 31 מתוך 3

שני תוצאות הפתיעו אותנו. הדבקת הקובץ כולו שמרה על המבנה בכל שלושת הניסיונות, אם כי בשניים מהם היא גם תרגמה את שורת ה-Title בכותרת. והפרומפט שמיועד לטקסט בלבד, שנשמע בטוח יותר, יצר את התגים השבורים היחידים. בניסיון אחד הוא החזיר {\k25}翻{\k30}页,{\k45}开{\k60}灯 עבור שורה עם שישה תגי קריוקי. שני התגים האחרונים ו-1.20 שניות של תזמון הדגשה נעלמו, כך שההדגשה הייתה מסתיימת הרבה לפני השורה. באותו ניסיון, Room\h12 is upstairs. הפך ל-12\h12号房间在楼上。, עם מספר החדר פעמיים.

אז הלקח השימושי אינו "השתמשו בפרומפט X". אלא שנזק מבני שאתם חוששים ממנו קל לזיהוי, והנזק שבאמת עבר בכל תשעת הניסיונות נמצא בשלושה מקומות שדפי הכלים לתרגום ASS אינם דנים בהם.

1. הגופנים אינם יכולים לצייר את השפה החדשה

הסגנונות בדוגמה משתמשים ב-Trebuchet MS לדיאלוג וב-Georgia לשלטים, וזה רגיל עבור מהדורה באנגלית. אף אחד מהגופנים אינו מכיל תווים סיניים. כשהפנינו את בדיקת הגליפים של הבודק לשני קבצי הגופנים, כל 12 אירועי הטקסט המתורגמים בכל ניסיון נכשלו:

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. 书人仅作员工库架闭限

נגן עשוי להחליף בגופן אחר המותקן במערכת, כך שהכתובית עשויה עדיין להופיע, אבל המהדורה כבר אינה שולטת במראה שלה, וצופה שמערכתו חסרה גופן מתאים עלול לראות תיבות ריקות. התיקון הוא עריכה מכוונת של שדה ה-Fontname בכל סגנון. כששינינו את כל שלושת הסגנונות בפלט אחד ל-Hiragino Sans GB, גופן סיני שמגיע עם macOS, והרצנו את בדיקת הגליפים מול הגופן הזה, שגיאות הגליפים ירדו לאפס.

בחרו גופן שצופיכם באמת יהיו להם, או צרפו אותו לסרטון. מדריך libass אומר שמהדורות צריכות לצרף כל גופן שהן משתמשות בו, רצוי למכל MKV. מכיוון שגופן שפת היעד חדש, צירופו הוא כעת חלק מעבודת התרגום.

2. קודי ריווח נושאים הרגלים של אנגלית

Room\h12 מדביק את "Room" ל-"12" כך שלעולם לא ייפרדו בין שורות. בסינית המילים אינן מופרדות ברווחים, אבל כל ניסיון השאיר את ה-\h במקום כלשהו: חמישה ניסיונות הציבו אותו בין 12号房间 ל-在楼上, שלושה שמו אותו לפני המספר, ואחד שם אותו בין שני עותקים של המספר. כך או כך, הצופה רואה רווח מיותר. ל-Wait\nhere. הייתה אותה בעיה. עם WrapStyle: 0, ה-\n מוצג כרווח, כך ש-在\n这里等 מציג פער באמצע משפט בן שלוש מילים.

המבנה כאן תקין; השפה לא. עבור שפת יעד ללא רווחים בין מילים, הסירו \h ו-\n מהטקסט המתורגם. השאירו \N רק במקום שבו אתם רוצים שבירה כפויה, והציבו אותו בנקודה טבעית במשפט היעד. הבודק מדווח על שינוי במספרי \h ו-\n כאזהרות ולא כשגיאות מהסיבה הזו, והוא מזהיר כאשר אחד מהם שורד בתוך טקסט סיני, יפני או קוריאני.

3. תזמון קריוקי שייך למילים המקוריות

שורת הקריוקי {\k25}Turn {\k30}the {\k45}page, {\k60}turn {\k40}the {\k80}light מתזמנת כל הברה אנגלית לשיר. תרגום אינו יכול לשמור על התזמון הזה באופן משמעותי, כי המילים הסיניות אינן נופלות על אותן פעימות. הניסיונות שלנו מראים את הדרכים השונות שבהן זה משתבש:

  • בארבעה ניסיונות כל ששת התגים נשמרו, כל אחד על מילה אחרת מאשר קודם. אחד מהם הסתיים ב-{\k40}打{\k80}开, "לפתוח", והשמיט את "light" מהשורה לחלוטין.
  • בארבעה ניסיונות הברה הדגישה דבר ולא כלום, כגון 打开{\k40}{\k80}灯 (0.40 שניות של הדגשה על הברה ריקה). בשניים מאלה, הברה של 0.45 שניות גם הדגישה רק פסיק.
  • בניסיון אחד שני תגים נעלמו, כמתואר לעיל.

הבודק מסמן שורת קריוקי שתורגמה במקום וכל הברה שנותרה ללא טקסט. התיקון הטוב יותר הוא עריכתי: אל תתרגמו קריוקי במקום. השאירו את השורה המתוזמנת המקורית לשירה יחד, והוסיפו את התרגום כאירוע נפרד: העתיקו את אירוע הקריוקי, תנו לו סגנון משלו (למשל, קטן יותר וממוקם בתחתית), הסירו את תגי ה-\k, ותרגמו את הטקסט. תזמנו אותו מחדש הברה אחר הברה רק אם אתם מוכנים לתזמן אותו לשמע בעצמכם.

תהליך עבודה שעומד במבחן

  1. הפכו את המקור לקריא תחילה. אם הקובץ מציג תווים משובשים, תקנו את הקידוד לפני כל דבר אחר. מדריך הקידוד שלנו משתמש בדוגמאות SRT, אבל אותם שלבים ברמת הבתים עובדים גם עבור קובץ .ass ושומרים על הבתים המקוריים. הבודק קורא רק UTF-8 ו-UTF-16.

  2. החליטו על ההיקף. רשמו את הסגנונות והחליטו אילו מהם דיאלוג, אילו שלטים על המסך ואילו קריוקי. שלטים בדרך כלל זקוקים לתרגום; קריוקי בדרך כלל זקוק לשורה נפרדת; הערות והערות בסוגריים מסולסלים הם לשיקולכם.

  3. תרגמו רק את שדה ה-Text. השתמשו בכלי שמנתח ASS ולא מתייחס אליו כטקסט רגיל, או הגנו על התגים בעצמכם כמו בתנאי השלישי שלנו. שמרו את קובץ המקור לצד הפלט.

  4. הריצו את הבדיקה המבנית.

    python3 check_ass_translation.py source.ass translated.ass
    

    היא משווה מספר אירועים, סוגי אירועים, שדות 1–9, ערכי סגנון, בלוקי עקיפה, ציורים, שורות הערה, \N, הברות קריוקי ומשכי זמן, ושורות שחזרו ריקות או ללא שינוי. היא אינה שופטת את איכות התרגום.

  5. תקנו את הגופנים בכוונה. שנו את Fontname בכל סגנון שנושא כעת טקסט בשפת היעד, ואז הריצו את בדיקת הגליפים מול קובץ הגופן שתפיצו:

    pip install fonttools
    python3 check_ass_translation.py source.ass translated.ass --font "Noto Sans SC=/path/to/NotoSansSC-Regular.otf"
    

    שם גופן ששונה מופיע כאזהרה, כך שתוכלו לוודא שכל שינוי היה מכוון.

  6. נקו קודי ריווח וקריוקי כמתואר לעיל.

  7. צפו בזה עם הווידאו. פתחו את הקובץ ב-Aegisub או בנגן שלכם. בדקו ששלטים עדיין מתאימים לצורות המצוירות מאחוריהם, כי תיבת \p שומרת על גודלה באנגלית בעוד ששלט מתורגם יכול להיות ארוך או קצר בהרבה. בדקו ששורות אינן ארוכות מדי לזמן שלהן על המסך. אף אחת מהבעיות הללו אינה נראית בקובץ עצמו.

איפה BookTranslator משתלב

מתרגם הכתוביות של BookTranslator מקבל קבצי SRT, VTT, ASS ו-SSA. לפי עמוד המוצר, הוא שומר על חותמות זמן וסדר כתוביות ועל עיצוב ASS ו-SSA נתמך צמוד לכל רשומת כתובית, כך שאין צורך לחלץ ולהכניס את הטקסט בעצמכם. הוא מתרגם דיאלוג עם השורות הסובבות כהקשר, מה שעוזר עם שמות ובדיחות חוזרות לאורך פרק שלם.

לא הרצנו את הדוגמה הזו דרך BookTranslator עבור מאמר זה. בכל כלי שתשתמשו, הריצו את שלבים 4 עד 7 על התוצאה. סגנון ששומר על הגופן האנגלי שלו הוא עדיין סגנון שאינו יכול לצייר סינית, וקריוקי שתורגם במקום עדיין דורש החלטה עריכתית. להמשך זרימת העבודה עם כתוביות, ראו את מדריך תרגום הכתוביות ב-AI, את השוואת תוכנות תרגום הכתוביות שלנו, ואם התרגום מיועד ל-YouTube, את זרימת העבודה לכתוביות ב-YouTube.

מתי להמיר ל-SRT במקום

המרת ASS ל-SRT לפני התרגום מסירה את הסגנונות, המיקומים, הציורים והקריוקי, מה שמסיר גם את רוב הבעיות לעיל. זו עסקה סבירה אם היעד שלכם מציג רק כתוביות פשוטות, או אם העיצוב מעולם לא היה חשוב ליציאה. זו העסקה הלא נכונה לאנימה ולהוצאות מוזיקה שבהן שלטים וקריוקי הם חלק מהיצירה. החליטו לפי היכן הקובץ יוצג, לא לפי איזה פורמט קל יותר לתרגום.

קבלו את קבצי הבדיקה

הכול מהבדיקה הזו חופשי לשימוש חוזר:

פוסטים קשורים