AI Video Playbook

Text and fonts in any language

Pick a font that really supports your language, stop fallback fonts from mixing inside words, burn in captions correctly and keep text out of AI generated frames.

Add every word of on screen text in post, with a font file you have checked against your real copy. A font that "has the letters" is not enough: it must also shape them, your render must use that exact file, and the layout must follow the rules of the script. This page works for any language and any tool. If you make video with code, also read Fonts in code video.

Coverage is not support

A font can contain every character of a script and still draw the language wrong. Google's shaperglot project gives the classic case: a font can cover the whole Arabic block (U+0600 to U+06FF) and still fail Arabic, because Arabic letters need joining forms (initial, medial, final). Devanagari needs conjuncts and reordering. Turkish needs the dotted and dotless I to change case correctly.

So a real check has two parts:

  • Coverage: the font maps every character in your real copy.
  • Shaping: the font joins letters, attaches marks, reorders and builds conjuncts the way the language needs.

One language can need several subsets

Google Fonts and Fontsource cut each family into subsets, and a language often needs more than one. On 15 Oct 2026, Roboto at weight 400 came back as nine subsets: cyrillic-ext, cyrillic, greek-ext, greek, math, symbols, vietnamese, latin-ext and latin.

LanguageSubsets to load
Englishlatin
Vietnameselatin, latin-ext and vietnamese (ơ, ư, đ and the stacked tone letters live outside latin)
Polish, Turkish, Czechlatin and latin-ext
Russian, Ukrainiancyrillic
Greekgreek
Arabic, Hebrew, Hindi, Thaiarabic, hebrew, devanagari or thai, from a family that has them (usually a Noto family)
Chinese, Japanese, KoreanNo named subset in the Google Fonts CSS. The font comes as numbered slices: Noto Sans JP at one weight was 124 separate files

Load only latin for Vietnamese and some letters fall back to another font, so one word is drawn in two fonts. The Google Fonts text= option returns a file cut to just the characters you pass, which Google says can make it up to 90% smaller. That suits a title card whose text never changes.

How to check a font for your language

Filter the catalog by language

On fonts.google.com, use the Language filter to see only families that support your writing system. Do this before you fall for a display font.

Check your real copy against the font file

Drop the font into Wakamai Fondue to see its characters, OpenType features and languages in the browser. Or run the script below on the exact file you will use and your final text.

Check shaping

Hyperglot (Rosetta) checks coverage per language plus default shaping such as mark attachment, joining and Devanagari conjuncts. shaperglot (Google Fonts) checks the shaping features each language needs. Both run in the terminal. Hyperglot calls itself a work in progress and does not judge the design.

Look at a rendered frame

A tool pass proves the letters and features exist. Only a rendered frame, read by someone who reads the language, proves the text looks right.

coverage.py
# coverage.py FONT COPY.txt : list characters in the copy that the font cannot map
import sys, unicodedata
from fontTools.ttLib import TTFont
font = TTFont(sys.argv[1], fontNumber=0)
text = unicodedata.normalize("NFC", open(sys.argv[2], encoding="utf-8").read())
cmap = font.getBestCmap()
missing = sorted({c for c in text if not c.isspace() and ord(c) not in cmap})
print("missing:", " ".join(f"{c} U+{ord(c):04X}" for c in missing) or "none")
sys.exit(1 if missing else 0)
Terminal
pip install fonttools brotli hyperglot
python coverage.py BrandDisplay.ttf copy_vi.txt
hyperglot BrandDisplay.ttf
cargo install --git https://github.com/googlefonts/shaperglot
shaperglot check BrandDisplay.ttf vi ar hi

A real example from the research for this page: macOS Futura has đ and ê but not ầ or ư. In the word "đầu", the first letter would come from Futura and the second from a fallback font. That is the ransom note look inside a single word.

Noto as the safe fallback

Google's Noto covers more than 150 writing systems and over 1,000 languages, with one family per script: Noto Sans Thai, Noto Sans Arabic, Noto Naskh Arabic, Noto Sans Devanagari, Noto Sans Hebrew and so on. When your brand font lacks a script, the matching Noto family is the default partner.

For Chinese, Japanese and Korean, pick the region variant: JP (Japanese), KR (Korean), SC (Simplified Chinese), TC (Traditional Chinese) or HK (Hong Kong). The three languages share Han characters, but readers expect small differences in the shapes. A Japanese video set in Noto Sans SC is correct Unicode and still looks wrong to Japanese readers. Set the language tag too (for example lang="ja"), because some browsers pick glyph shapes by language.

Fallback without the ransom note look

When a font in your list lacks a character, the renderer tries the next font, one character at a time. If no font you supplied has it, it uses whatever is installed on the machine. That gives two failures:

  • Tofu: empty boxes. No font in the list or on the machine has the glyph.
  • Ransom note: the glyphs exist, but come from different fonts letter by letter or word by word, with different sizes, weights and baselines.

The usual causes of the ransom note are loading only the latin subset, a display font with partial coverage, and decomposed text: a base letter followed by a separate combining mark, which some fonts cannot draw as one letter. Normalize your copy to NFC (precomposed letters) before you render, especially for Vietnamese, unless you know the font handles decomposed marks.

Pick a pattern per language

SituationDo thisExample
Your brand font covers the language fullyUse it aloneEnglish, or Vietnamese in Be Vietnam Pro
Scripts never mix inside a word (a Latin brand name plus a Thai, Arabic or Hindi sentence)Keep the brand font for Latin and add a partner font for the other script, matched in sizeBrand font plus Noto Sans Thai
Latin with extra marks (Vietnamese, Polish, Turkish) and the brand font lacks some lettersSwitch the whole line, or the whole language, to a font that covers it. Never mix fonts inside a wordVietnamese headlines in Be Vietnam Pro
Chinese, Japanese or KoreanUse the region font and set the language tagNoto Sans JP for ja, Noto Sans TC for zh-Hant
Scripts whose fonts rarely have bold or italic (Chinese, Japanese, Korean, Arabic)Use real weights only and turn off fake bold and italicfont-synthesis: none in CSS

To match a partner font, pick one with similar proportions, then adjust its size until both sit at the same visual height on one line. In CSS this is size-adjust; in an editor, nudge the size by eye. When the brand font cannot cover a script at all, set that language's headlines entirely in the partner font and accept that some brand cues are lost. HyperFrames' own style presets do this for Chinese and note that the uppercase look of the Latin design disappears.

Starting fonts per language

Language (tag)Start with
Vietnamese (vi)Be Vietnam Pro, or any family with the vietnamese subset
Russian (ru), Greek (el)A family with cyrillic or greek subsets, such as Roboto
Arabic (ar)Noto Kufi Arabic or Noto Sans Arabic
Hebrew (he)Noto Sans Hebrew
Hindi (hi)Noto Sans Devanagari
Thai (th)Noto Sans Thai
Japanese (ja)Noto Sans JP
Chinese, Simplified (zh-Hans)Noto Sans SC
Chinese, Traditional (zh-Hant)Noto Sans TC
Korean (ko)Noto Sans KR
EmojiNot a font you pick for text. Emoji come from the color emoji font of the machine that renders, so they can look different on your Mac and on a cloud renderer

Script rules

Each script has a few rules that break motion design habits. Check the rows for every language in your video.

RuleScriptsWhat goes wrongWhat to do
ShapingArabic, Persian, Urdu, Hebrew with vowel points, Devanagari and other Indic scripts, Thai, Lao, Khmer, MyanmarLetters must change form, join, reorder or stack. A tool that draws one character at a time skips thisUse a tool with a real shaping engine (a browser, libass with HarfBuzz). Animate by word or line, never letter by letter
Right to left and bidiArabic, Hebrew, Persian, UrduLines read backwards, punctuation and numbers jump to the wrong end, motion runs the wrong waySet the base direction, mirror directional motion, keep logos, photos and the digits inside a number unmirrored
Line breaks without spacesChinese, Japanese, Thai, Lao, Khmer, MyanmarLines break in the middle of a word, or a tool that splits on spaces treats a whole sentence as one wordLet a browser or libass wrap (they use dictionaries), use phrase wrapping for Japanese headings (word-break: auto-phrase in Chrome), break titles by hand
Stacked marks and line heightVietnamese, Thai, Devanagari, Arabic, MyanmarTight line height clips tone marks or makes lines collide. Reveal masks cut off the topsLine height 1.2 to 1.3 for Vietnamese, 1.4 or more for Thai, Devanagari, Arabic and Myanmar. Test the tallest string
Letter spacingArabic and other cursive scripts (Syriac, Mongolian, N'Ko), Devanagari and other Indic scriptsGaps break Arabic joins. In Devanagari the top bar breaks between syllables. Any spacing also turns off optional ligaturesKeep tracking at 0. For a spaced look in Indic scripts, add space between syllables yourself
Text expansionTranslations from English, most of all short labelsShort labels can grow 2 to 3 times. Long German compounds may not wrapDesign for the longest language or fit text per language with a minimum size. Allow hyphenation with the right language tag
UppercaseTurkish, Azerbaijani, Greek, German, Dutch. No case at all in Arabic, Hebrew, Chinese, Japanese, Korean, Thai, DevanagariWrong capitals, such as ISTANBUL instead of İSTANBUL in Turkish. All caps does nothing in caseless scriptsUppercase with the language set. In caseless scripts, show hierarchy with size and weight
Fake bold and italicChinese, Japanese, Korean, ArabicSynthesized styles hurt legibility or change meaningUse real weights only. No italics in Arabic captions (Netflix Arabic guide)
EmojiAllThe design depends on the emoji font of the rendering machineRender finals where you tested, and check emoji in the final frames

Right to left

  • Set the base direction at the top of the layout, not letter by letter. In HTML that is dir="rtl" on the root element. W3C advises against setting the base direction with CSS.
  • Align with start and end instead of left and right, so one template works in both directions.
  • Mirror anything that shows order or progress: progress bars, wipes, slide ins, typewriter reveals. Do not mirror logos, universal signs, photos, clocks or the digits inside a number (Apple Human Interface Guidelines). Reverse a sequence of numbers only when it shows progress.
  • Hebrew uses Western digits. Arabic uses Western or Eastern Arabic digits depending on the region.
  • Apple suggests setting Arabic and Hebrew slightly larger to balance uppercase Latin on the same screen.
  • Mixed lines (Arabic or Hebrew with Latin words and numbers) are where bidi bugs show up. WebVTT takes each line's direction from its first strong character. Add U+200F (right to left mark) or U+200E (left to right mark) at the start when that guess is wrong.

Stacked marks and line height

W3C notes that non Latin text is often much taller than Latin: its Thai example needs about 150% of the vertical space of the English one. Vietnamese stacks a tone mark over a vowel mark (ấ, ở, ữ) and Thai stacks vowel and tone marks above consonants. Display line heights of 0.9 to 1.0 clip those marks or make lines touch.

The starting values in the table above are our synthesis of W3C and type design sources, not a standard. Test with the tallest string in your copy, for Vietnamese an uppercase line with stacked marks such as "ẤN TƯỢNG". Masks and wipes that reveal text clip marks too, so give them extra room at the top.

Text expansion when translating

W3C quotes IBM's guidance for translating from English into European languages:

English text lengthLength after translation
Up to 10 characters200 to 300%
11 to 20 characters180 to 200%
21 to 30 characters160 to 180%
31 to 50 characters140 to 160%
Over 70 characters130%

The same article measured the Flickr label "views" at 0.8 times the English width in Korean, 1.2 in Chinese, 2.8 in German and 3 in Italian. One word titles and buttons grow the most, so size boxes for the longest language, not for English.

Uppercase

All caps follows language rules only when the language is set, and support varies between browsers.

InputPlain uppercaseWith the language set
istanbul (Turkish)ISTANBULİSTANBUL
άι (Greek)ΆΙ, accent wrongly keptΑΪ
straße (German)STRASSESTRASSE

Dutch ij becomes IJ. If your tool has an all caps switch but no language setting, type the capitals yourself and check them.

Captions and burn in

Pick a format

FormatStylingLanguage featuresUse it for
SRTNone standardNoneMoving captions between tools. Style them when you burn in
WebVTTBasicLanguage spans, vertical cues for Chinese and Japanese, direction per lineWeb players and soft subtitles
ASSFull: font, size, outline, positionLanguage header, automatic base directionStyled burn in with FFmpeg (libass), also played by mpv and many players

Burn in with FFmpeg and libass

FFmpeg's subtitles and ass filters use libass, which handles shaping, right to left text and line breaking when it is built with the right libraries.

Homebrew ffmpeg cannot burn subtitles

On 15 Oct 2026, Homebrew's ffmpeg formula (9.0.2) came without libass, FreeType, HarfBuzz and fontconfig, and the 8.0.1 build on our test Mac answered "Unknown filter 'subtitles'". On macOS, run brew install ffmpeg-full or use a static build. On Linux, check that ffmpeg -buildconf lists --enable-libass.

OptionWhat it does
fontsdirA folder of font files to use in addition to installed fonts. Put your caption fonts here
shaping=complexFull shaping. Required for Arabic, Hebrew, Devanagari and Thai. Needs libass built with HarfBuzz
wrap_unicode=1Breaks lines with the Unicode line breaking algorithm. Needs libass 0.17.0 built with libunibreak. On by default except for native ASS files
force_styleOverrides ASS style fields for any subtitle file, such as Fontname and Fontsize
charencInput encoding, only needed when the file is not UTF-8
original_sizeNeeded for correct font size if the aspect ratio changed
Terminal
# Check that this ffmpeg has the subtitle filters
ffmpeg -hide_banner -filters | grep -E ' (subtitles|ass|drawtext) '

# Burn an SRT in any language with shipped fonts, complex shaping and Unicode wrapping
ffmpeg -i in.mp4 -vf "subtitles=subs.th.srt:fontsdir=./fonts:shaping=complex:wrap_unicode=1:force_style='Fontname=Noto Sans Thai,Fontsize=22,Outline=2,MarginV=60'" -c:a copy out.th.mp4

# Burn a styled ASS file
ffmpeg -i in.mp4 -vf "ass=subs.ar.ass:fontsdir=./fonts:shaping=complex" -c:a copy out.ar.mp4

Right to left captions in ASS

libass uses left to right as the base direction by default, for compatibility with the old VSFilter renderer. For Arabic, Hebrew, Persian and Urdu, set the style's Encoding field to -1, which tells libass to detect the direction. Add a Language: line under [Script Info]; libass reads the first two letters as a hint for language specific glyph forms, such as Serbian Cyrillic. Keep Spacing at 0 for Arabic, and Italic at 0 because Netflix's Arabic guide says not to use italics in Arabic.

subs.ar.ass
[Script Info]
ScriptType: v4.00+
PlayResX: 1920
PlayResY: 1080
Language: ar

[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: Default,Noto Sans Arabic,58,&H00FFFFFF,&H00FFFFFF,&H00000000,&H64000000,0,0,0,0,100,100,0,0,1,3,0,2,80,80,70,-1

Line length per script

Netflix's timed text rules are a good reference, even though social captions are usually larger (see Finishing for sizes and safe zones). General rules: 2 lines at most, each caption on screen from 5/6 of a second to 7 seconds, and lines broken after punctuation and before conjunctions or prepositions.

LanguageCharacters per line
Most languagesAbout 42 advised, no hard limit
Arabic42 in the Arabic guide; lines over 50 are rejected automatically
Chinese (Simplified and Traditional), Korean16 for Netflix Originals; lines over 23 are rejected automatically
Japanese13 full width characters horizontal, 11 vertical, half width counts as 0.5 (from a search summary of the guide, not confirmed on the page)

Captions in editors

  • Premiere Pro: until late 2021, Hebrew and Arabic SRT files imported reversed unless you switched the caption text engine to "South Asian and Middle Eastern". Since version 22.1 (December 2021) a Universal Text Engine handles this, according to an Adobe community thread. Edge cases remain: a 2024 report says Hebrew punctuation does not turn right to left in MOGRTs.
  • CapCut: we found no official documentation on Arabic, Indic or Thai shaping, right to left text or custom fonts for non Latin scripts. Treat it as unverified for those scripts and check every export.
  • Safe fallback for any editor: render the text in a browser engine, which shapes, wraps and handles direction correctly, as a transparent overlay, then drop it on your timeline.
Terminal
# HyperFrames: transparent WebM, or ProRes 4444 MOV for editing (page background must be transparent)
npx hyperframes render --format webm
npx hyperframes render --format mov

# Remotion: ProRes 4444 with alpha
npx remotion render --image-format=png --pixel-format=yuva444p10le --codec=prores --prores-profile=4444

Text inside AI generated video and images

No video or image model publishes how accurate its text is per script. Research on text rendering explains why: many models do not see individual letters, and even systems built for text still struggle with many languages. Latin gets the most attention, then Chinese, Japanese and Korean. Arabic, Indic and Thai have the fewest vendor claims and the most creator complaints.

What the vendors say (checked 15 Oct 2026):

ModelWhat the official source says about text
Seedance 2.5Prompts and audio in 11 languages: Chinese, English, Spanish, Indonesian, Malay, Thai, Arabic, Portuguese, Vietnamese, Japanese, Korean. Its FAQ admits text in video may be misspelled (English letters swapped or dropped, Chinese characters replaced) and that unwanted subtitles are reduced but cannot be removed completely
Veo and Gemini Omni FlashGoogle's Vertex AI video prompt guide says nothing about on screen text, subtitles or signs
Kling 3.0 and 4.0No official statement. A reseller page claims better text rendering; unverified marketing
WanThe Wan2.1 README says it can generate Chinese and English text. No other scripts are claimed
GPT Image 2.5OpenAI's docs say it can still struggle with precise text placement and clarity. No list per script. For the earlier ChatGPT Images 2.0, press reported OpenAI's claim of better Japanese, Korean, Chinese, Hindi and Bengali text, with no public benchmark
Nano BananaGoogle says the models can generate legible, stylized text and that 2.1 improved text rendering. No language list. Google Japan said 2.1 greatly improved Japanese text (8 Oct 2026)

Seedance subtitle syntax

Seedance 2.5 has a sound and text syntax: () for music, <> for sound effects, {} for dialogue and 【】 for subtitles. For dialogue that is not in Chinese, ByteDance recommends naming the language before the line. To avoid unwanted subtitles, its guide suggests:

  • Write "No subtitles." in the prompt. One official example uses "No subtitles, no text overlays".
  • Do not repeat dialogue words elsewhere in the prompt, and do not attach tone instructions to single words.
  • Write lines as "Character's line (emotion): content".
  • Use reference videos that contain no subtitles, since they can override your instruction.
  • Keep text off storyboards you upload.

Subtitles made with 【】 are fine for drafts, in languages on Seedance's list. They are burned into the pixels in a font you do not control, so you cannot fix a typo, restyle them or translate them later. See Seedance for the rest of the model.

The rule: add text in post

Generate clean plates

Add the model's negative for text, keep text out of reference images and storyboards, and avoid the prompt patterns above that trigger subtitles.

Add every word in post

Captions, titles, lower thirds, prices, legal lines and logos all go in during editing, with a font you checked for the script.

If text must be part of the scene, keep it to one string

For a shop sign or a blackboard: one short string in one language, written exactly in quotes, with all other text forbidden. Give the model the correctly set text as a reference image (Seedance's documented fix). Or make the key frame with an image model that handles the script, then animate it as the first frame.

Have every visible word checked

A native reader, or OCR, checks every frame where generated text is visible. If it fails, mask it and put the correct text on top in post.

Prompt
Night street, light rain, a small noodle shop with warm light inside.
Above the door, one shop sign that reads exactly "Phở Hà Nội" in white letters,
matching the attached reference image. No other text anywhere in the frame.
No subtitles, no text overlays, no captions.

Licensing

Font sourceUse in videosRender on a server or in the cloudCommit the files to a project or template
Google Fonts and other OFL fontsYes, including commercial work and logos. The video is not bound by the OFLYesYes, with the license file (OFL.txt) next to the fonts. You may not sell the fonts on their own
Adobe Fonts (subscription)Yes: in house, commercial and broadcast, including YouTube and VimeoNo. Server installation is not coveredNo. Self hosting needs a license bought from the foundry
Apple system fonts (San Francisco)No. The license only allows mock ups of Apple platform interfacesNoNo
Other installed fontsCheck each font's own licenseCheckCheck
  • Subsetting a font or converting its format counts as a change under the OFL. That is allowed, but if the font declares a Reserved Font Name, rename the family in your subset before you share it. Wrapping the font in WOFF without changing its data is the exception.
  • Videos you rendered with Adobe Fonts keep working after you cancel the subscription.
  • Some tools copy installed fonts into the project automatically. HyperFrames local renders do this, which can put a commercial system font into a file you share. Check the license before that happens.

Checklist

  • Write down each language's tag, script, direction, whether it uses spaces, has case, is cursive and stacks marks.
  • Collect the final copy for every language, normalized to NFC, including the longest strings.
  • Run a coverage check on the real copy and a shaping check; pick a partner font per script and a region font for Han.
  • Use real weights only, and a license that allows your video, your render machine and sharing the files.
  • Set the language on all text, set the direction for right to left, and mirror directional motion only.
  • Tracking at 0 for Arabic and Indic scripts, no forced uppercase on caseless scripts, uppercase with the language set.
  • Raise line height for stacked marks and pad reveal masks.
  • Let the renderer wrap lines; never split Thai, Chinese or Japanese on spaces.
  • Animate complex scripts by word or line.
  • Burn captions with a libass build of FFmpeg: fontsdir, shaping=complex, wrap_unicode=1, and Encoding -1 for right to left.
  • Generate AI footage without text and add all text in post.
  • Have a native reader check every frame that shows text.

What creators report on X

Searches run on 15 Oct 2026. Labels: organic means a creator sharing their own result; self promo means a creator promoting their own free tool; vendor means the maker; sponsored means a paid post.

  • Seedance 2.5 writing Japanese on a blackboard still makes character mistakes, and long sentences and small text break easily. Organic, @tanabe_fragm, 12 Aug 2026.
  • A creator had Seedance 2.5 generate Japanese dialogue with English subtitles and says it even sized the text on its own. Organic, @CuriousOne_01, 21 Aug 2026.
  • Chinese prompt writers routinely end Seedance prompts with negatives for subtitles (字幕) and garbled text (乱码), for example @liyue_ai and @xianshi666123. Organic.
  • When a sign must be in the scene, one prompt asks for exactly one green Chinese exit sign (安全出口) and forbids English or garbled text. Organic, @johnAGI168, 26 Aug 2026.
  • A Seedance concept ad describes the brand end card, then says the brand text is overlaid in post to keep it clear and accurate. Organic, @hxhxhx0916, 4 Oct 2026.
  • A commentator says Alibaba's docs for a new document to video model tell users to composite legal copy and subtitles afterwards. Secondhand, we did not verify that doc. @lordofblocks, 2 Sep 2026.
  • Veo 3 made errors in Japanese text. Organic, @okloorcl, 25 May 2025.
  • Nano Banana Pro drew Arabic with diacritics well, but the final image still took a few more attempts and half an hour in Photoshop. Organic, @Ibraheem_Abbas, 21 Nov 2025.
  • With the same prompts in GPT Image 2.5 and Nano Banana 2.1, Nano Banana added text to a poster that was not in the prompt. Organic, @olezhavich, 9 Oct 2026.
  • A post praising GPT Image 2.0 on Higgsfield for accurate Japanese text ends with "PR". Sponsored, @KanaWorks_AI, 22 Apr 2026. Many resellers repeat "clearer text" claims for Nano Banana; treat them as marketing.
  • Captions in Arabic and Moroccan Darija: letters do not always display well, right to left text causes problems, and mixing Arabic with French and numbers is hard. Organic, @ElmaAbdeljalil, 13 Oct 2026.
  • Vietnamese viewers notice broken fonts: one mocked a promo video for its "lỗi font" (font errors). Organic, @NcTn_1611, 5 Sep 2024.
  • CaptionSpec checks SRT files against Netflix rules (reading speed, line length, timing) in the browser. Self promo, @CreateLex, 12 Oct 2026.

The pattern: creators trust code and editors for text and treat model text as decoration. Complaints cluster on Japanese and Arabic in generated frames, and on right to left text mixed with other scripts in captions.

Sources