03:00:0050% OFFClaim

Technical recipe

CJK subtitle burn-in: font coverage, UTF-8 checks and decoded-frame review

Run an original 3.6-second caption exercise with a licensed pinned Noto CJK font, a dependency-free cmap checker, real FFmpeg/libass rendering, four decoded frames and 29 executed checks. Separate missing-glyph checks from readable, regionally correct text.

Before finishing a captioned clip, distinguish four different failures: incorrect subtitle bytes, a font without the requested codepoint, a renderer using another face, and pixels that do not match the intended text. This recipe supplies a real local execution sample, not a MiniMax model test.

Download the full brief
Original geometric short clip and bilingual/CJK cues; unmodified OFL-licensed Noto font; actual FFmpeg render, four decoded PNGs, coverage/command logs and 29-check execution evidence.

01 · Environment and inputs

  • Download the original SRT, Node scripts, unmodified Noto Sans CJK SC Regular OTF and both OFL/copyright notices into one folder. Keep the font’s separate license when redistributing it.

  • Use Node.js 24 and an existing FFmpeg 6.0 build with libass/libx264; the bundle does not install or redistribute FFmpeg. The recorded run used Node v24.14.0, libass 0.17.0 and Noto font 2.004.

  • Choose a fresh local output folder. The sample is silent, 1280×720 and 3.6 seconds long; its script is not a full-length delivery exporter.

  • Read the intended four cues before rendering. An SC font’s nonzero glyph mappings do not establish preferred Japanese, Korean or Traditional Chinese regional forms.

02 · Run and inspect

  1. 01 · Preserve the exact font and verify the subtitle text

    Keep NotoSansCJKsc-Regular.otf with OFL.txt and FONT-COPYRIGHT.txt. The unmodified official Sans2.004 font is pinned by SHA-256 and font name. Open sample.srt as UTF-8 and check its four cue texts and time ranges before any renderer is involved. The parser deliberately rejects markup, overlapping cues and variation sequences; it does not guess an unknown encoding or silently rewrite the subtitle. SRT start/end boundaries must align to 10 ms because ASS stores centiseconds; finer values are refused rather than rounded.

    node --version
    node run-preflight-tests.mjs
  2. 02 · Treat codepoint coverage as one preflight result

    subtitle-check.mjs reads the font’s Unicode cmap format 4 or 12 and checks nonzero, in-range glyph IDs. This sample contains 43 unique non-whitespace codepoints and none were missing. Twenty-two executed scenarios include a known absent codepoint, missing or modified fonts, invalid UTF-8/UTF-16, overlap, unsafe paths and argument boundaries. Coverage is not a shaping or typography proof: a different regional glyph or unreadable layout can still have a valid mapping.

  3. 03 · Run the actual burn-in with safe fixed filter filenames

    Pass an absolute FFmpeg binary path and a fresh output directory. The runner creates an original geometric slate, converts supported plaintext SRT into a fixed-style ASS file and uses libass to burn it in. User paths are copied to constant staging filenames instead of being interpolated into a filter expression. Child processes use shell:false, one encoder/filter thread, bounded logs and a one-minute timeout. The recorded macOS font provider was CoreText; the log confirms loading the bundled font and selecting its PostScript face, without claiming general font isolation.

    node run-recipe.mjs --ffmpeg /absolute/path/to/ffmpeg --out ./fresh-output
    node run-recipe.mjs --ffmpeg /absolute/path/to/ffmpeg --out ./another-fresh-output --input ./sample-source.mp4 --srt ./sample.srt --font ./NotoSansCJKsc-Regular.otf
  4. 04 · Decode and read the text, then keep the execution receipt

    Compare keyframe-01 through keyframe-04 to the intended bilingual, Simplified/Traditional Chinese and Japanese/Korean cues. The script decodes each PNG and measures subtitle-band pixel changes against the uncaptioned source; those measurements do not prove character identity. Also read the actual font-selection log and coverage report. The execution receipt includes seven media assertions, twenty-two preflight scenarios, file sizes, hashes and the exact tool versions. A limited visual readback was recorded, while regional typography and other subtitle text still need their own review.

03 · Validate the output

  • sample.srt decodes strictly as UTF-8 and has valid, ordered, nonoverlapping cue times; the twenty-two preflight tests pass.
  • The bundled font remains byte-for-byte matched to its pinned SHA-256, and its OFL license plus copyright notice travel with it.
  • All 43 non-whitespace sample codepoints map to valid nonzero glyph IDs; no all-Unicode or regional-form coverage claim is inferred.
  • Actual FFmpeg rendering succeeds and its log records the bundled Noto face; missing-glyph diagnostics and unconfirmed font selection fail the run.
  • All four selected output frames are decoded at their intended cue times and have measured subtitle-band differences from the clean source.
  • The expected text is checked visually for replacement boxes, clipping and punctuation; a nonempty PNG or pixel delta alone is insufficient.
  • The receipt identifies actual versions and output hashes, states that production/provider tasks were not run, and preserves the distinction between local rendering and generation-quality evidence.

Read the actual execution receipt

04 · Boundaries and troubleshooting

The text contains replacement symbols before rendering.
Export the source subtitle explicitly as UTF-8 and rerun preflight. Do not change an encoding label while leaving unknown bytes unchanged.
Coverage finds a missing U+ codepoint.
Inspect the exact codepoint, obtain a suitably licensed font covering it, and redo the family name, checksum, renderer and visual checks. Do not accept an undocumented system fallback.
Glyphs exist but look wrong for the target language.
Separate default codepoint coverage from region-specific CJK forms. Use the appropriate language variant and have the intended language’s typography reviewed; the SC sample does not prove those regional forms.
The renderer exits successfully but the visible subtitle is absent or clipped.
Read actual cue times, font-selection diagnostics and decoded frames. Check the 1280×720/3.6-second demonstration limits and placement before adapting the script to a real clip.
A path, font or output-file check rejects the command.
Use a fresh controlled directory, the exact bundled font, ordinary local files and an absolute FFmpeg path. The script refuses overwrite, symlinks, traversal and network inputs.
The fixture works but a full delivery would lose audio or content after 3.6 seconds.
Do not use this sample runner unchanged for full delivery. Review duration, audio mapping, frame size and caption safe area in a separately verified export command.
A 201–209 ms cue is refused before conversion.
Use 10 ms-aligned start/end boundaries with a positive duration. This sample does not round millisecond boundaries, because both values would otherwise collapse to 0.20 seconds in ASS.

Keep the source subtitle, exact font/license, renderer log, four decoded sample frames and execution receipt together. The provided hashes identify this local run; platform/build differences can change output bytes. No model generation, production billing or search-traffic result is claimed.

Files and evidence

Explore production checks and handoffs