{
  "schemaVersion": 1,
  "batchId": "pseo-batch2-20261014",
  "blueprintId": "blueprint-28",
  "kind": "recipe",
  "slug": "cjk-subtitle-font-and-burnin-check",
  "locale": "en",
  "evidenceClass": "local-media-run",
  "sourcePath": "content/pseo/batch2-20261014/recipes/cjk-subtitle-font-and-burnin-check.json",
  "sourceHash": "0608da8625c4c6e159d200f6f4a672ba380857c30f5a8e0d26f1e64951ba3272",
  "contentHash": "da77f55e3c9dc3cde1a4bf04e0ee1803c2008c37256873c0013baf07f16c46a4",
  "contentVersion": "authored-da77f55e3c9dc3cde1a4bf04",
  "rendererHash": "727572c29f88632162b30bf97d95dc1be416eb61ca002023ad1c1b1410d29fbd",
  "copy": {
    "title": "CJK subtitle burn-in: font coverage, UTF-8 checks and decoded-frame review",
    "description": "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.",
    "goal": "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.",
    "preparation": [
      "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."
    ],
    "steps": [
      {
        "title": "01. Preserve the exact font and verify the subtitle text",
        "body": "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.",
        "commands": [
          "node --version",
          "node run-preflight-tests.mjs"
        ]
      },
      {
        "title": "02. Treat codepoint coverage as one preflight result",
        "body": "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."
      },
      {
        "title": "03. Run the actual burn-in with safe fixed filter filenames",
        "body": "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.",
        "commands": [
          "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"
        ]
      },
      {
        "title": "04. Decode and read the text, then keep the execution receipt",
        "body": "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."
      }
    ],
    "acceptance": [
      "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."
    ],
    "troubleshooting": [
      {
        "symptom": "The text contains replacement symbols before rendering.",
        "change": "Export the source subtitle explicitly as UTF-8 and rerun preflight. Do not change an encoding label while leaving unknown bytes unchanged."
      },
      {
        "symptom": "Coverage finds a missing U+ codepoint.",
        "change": "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."
      },
      {
        "symptom": "Glyphs exist but look wrong for the target language.",
        "change": "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."
      },
      {
        "symptom": "The renderer exits successfully but the visible subtitle is absent or clipped.",
        "change": "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."
      },
      {
        "symptom": "A path, font or output-file check rejects the command.",
        "change": "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."
      },
      {
        "symptom": "The fixture works but a full delivery would lose audio or content after 3.6 seconds.",
        "change": "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."
      },
      {
        "symptom": "A 201–209 ms cue is refused before conversion.",
        "change": "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."
      }
    ],
    "ending": "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.",
    "assetCaption": "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.",
    "prompt": ""
  },
  "assets": [],
  "artifacts": [
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/run-recipe.mjs",
      "label": {
        "en": "Run the bounded FFmpeg burn-in",
        "zh": "运行有上限的 FFmpeg 字幕烧录"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/subtitle-check.mjs",
      "label": {
        "en": "UTF-8/SRT and cmap preflight module",
        "zh": "UTF-8/SRT 与 cmap 预检模块"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/run-preflight-tests.mjs",
      "label": {
        "en": "22 executed preflight scenarios",
        "zh": "22 项已执行预检场景"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/NotoSansCJKsc-Regular.otf",
      "label": {
        "en": "Pinned unmodified Noto CJK SC font (16.44 MB)",
        "zh": "固定未修改 Noto CJK SC 字体（16.44 MB）"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/OFL.txt",
      "label": {
        "en": "Original SIL OFL 1.1 font license",
        "zh": "原始 SIL OFL 1.1 字体许可"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/FONT-COPYRIGHT.txt",
      "label": {
        "en": "Font copyright notice",
        "zh": "字体版权声明"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/LICENSE-original-assets.txt",
      "label": {
        "en": "Original asset and sample-script reuse terms",
        "zh": "原创素材与示例脚本使用条款"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/sample.srt",
      "label": {
        "en": "Original four-cue UTF-8 subtitle file",
        "zh": "原创四条 UTF-8 字幕"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/sample.ass",
      "label": {
        "en": "Actual fixed-style ASS used in this run",
        "zh": "本次实跑使用的固定样式 ASS"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/sample-source.mp4",
      "label": {
        "en": "Original 3.6-second geometric source slate",
        "zh": "原创 3.6 秒几何源测试片"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/subtitle-burned.mp4",
      "label": {
        "en": "Actual subtitle burn-in sample",
        "zh": "实际烧录字幕的样例"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/keyframe-01.png",
      "label": {
        "en": "Decoded bilingual keyframe at 0.6s",
        "zh": "0.6 秒中英混排解码帧"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/keyframe-02.png",
      "label": {
        "en": "Decoded Simplified Chinese keyframe at 1.4s",
        "zh": "1.4 秒简体中文解码帧"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/keyframe-03.png",
      "label": {
        "en": "Decoded Traditional Chinese keyframe at 2.2s",
        "zh": "2.2 秒繁体中文解码帧"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/keyframe-04.png",
      "label": {
        "en": "Decoded Japanese/Korean keyframe at 3.0s",
        "zh": "3.0 秒日语/韩语解码帧"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/coverage-report.json",
      "label": {
        "en": "Actual per-codepoint glyph mapping report",
        "zh": "实际逐码点字形映射报告"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/command-log.json",
      "label": {
        "en": "Executed FFmpeg argument log",
        "zh": "已执行 FFmpeg 参数日志"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/ffmpeg-log.txt",
      "label": {
        "en": "Actual renderer and font-selection log",
        "zh": "实际渲染与字体选择日志"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/execution-receipt.json",
      "label": {
        "en": "Actual media execution and SHA-256 receipt",
        "zh": "实际媒体执行与 SHA-256 回执"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/preflight-test-receipt.json",
      "label": {
        "en": "Actual negative/positive preflight receipt",
        "zh": "实际正负向预检回执"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/visual-review.json",
      "label": {
        "en": "Limited four-frame visual readback",
        "zh": "四帧有限目视读回记录"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/sources.json",
      "label": {
        "en": "Pinned official font/license source evidence",
        "zh": "固定官方字体/许可来源证据"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/README.en.md",
      "label": {
        "en": "English runnable command and review guide",
        "zh": "英文运行命令与检查说明"
      }
    },
    {
      "path": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/README.zh.md",
      "label": {
        "en": "Chinese runnable command and review guide",
        "zh": "中文运行命令与检查说明"
      }
    }
  ],
  "execution": {
    "nodeVersion": "v24.14.0",
    "ffmpegVersion": "ffmpeg version 6.0 Copyright (c) 2000-2023 the FFmpeg developers",
    "fontVersion": "Version 2.004;hotconv 1.0.118;makeotfexe 2.5.65603",
    "command": "node run-recipe.mjs --ffmpeg /absolute/path/to/ffmpeg --out ./fresh-output",
    "receiptPath": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/execution-receipt.json",
    "passedScenarios": [
      "strict-UTF8-SRT-preflight",
      "pinned-font-cmap-coverage",
      "bounded-actual-libass-burnin",
      "font-selection-observed",
      "four-keyframes-decoded",
      "four-subtitle-band-pixel-differences",
      "media-and-frame-output-hashes",
      "valid-four-cue-UTF8-and-CJK-cmap",
      "known-missing-codepoint-detected",
      "invalid-UTF8-rejected",
      "UTF16-BOM-rejected",
      "NUL-control-rejected",
      "timestamp-minute-range-rejected",
      "non-centisecond-SRT-boundaries-rejected",
      "collapsed-ASS-range-rejected",
      "overlapping-cues-rejected",
      "ASS-and-HTML-markup-refused",
      "variation-sequence-refused",
      "truncated-font-refused",
      "CLI-option-value-boundary",
      "CLI-duplicate-options-refused",
      "missing-font-file-refused",
      "font-symlink-refused",
      "input-path-traversal-refused",
      "network-input-refused",
      "output-path-traversal-refused",
      "missing-glyph-stops-before-FFmpeg",
      "pinned-font-hash-drift-refused",
      "special-filename-is-data-not-shell"
    ],
    "productionTaskRun": false,
    "providerModelTest": false,
    "fontProviderObserved": "coretext",
    "preflightReceiptPath": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/preflight-test-receipt.json"
  },
  "hero": {
    "imagePath": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/keyframe-04.png",
    "videoPath": "/learning-assets/pseo-batch2-20261014/cjk-subtitle-font-and-burnin-check/subtitle-burned.mp4",
    "label": {
      "en": "Actual local subtitle render; no provider/model generation",
      "zh": "实际本地字幕渲染；未进行提供商/模型生成"
    }
  },
  "sources": [
    {
      "title": "Noto CJK official Sans2.004 license",
      "url": "https://github.com/notofonts/noto-cjk/blob/523d033d6cb47f4a80c58a35753646f5c3608a78/LICENSE"
    },
    {
      "title": "Noto CJK official language/font download guide",
      "url": "https://github.com/notofonts/noto-cjk/blob/523d033d6cb47f4a80c58a35753646f5c3608a78/Sans/README.md"
    },
    {
      "title": "FFmpeg official subtitle and ASS filter documentation",
      "url": "https://ffmpeg.org/ffmpeg-filters.html#subtitles-1"
    },
    {
      "title": "OpenType official cmap specification",
      "url": "https://learn.microsoft.com/en-us/typography/opentype/spec/cmap"
    }
  ],
  "shots": [],
  "demonstration": null
}
