The YuE2 and subtitles posts shipped text-only: render_from_art.mjs only READS
ogImage/banner, and after the 2026-10-19 bulk migration no script had to write
them, so both pages advertised /og-default.jpg and rendered no hero banner.
- new metaphors (in build_captions.py, frozen here via sync_prompts_catalog.py),
captions, art-meta evidence, banner plan and the five derived files per slug
- frontmatter: ogImage + banner in EN and ZH for both posts
- scripts/check-assets.mjs is now step 1 of npm run build, so CI fails when a
published post lacks a language-correct og card, banner, banner .webp or
400/800 list thumb. It reported 16 problems on the unfixed tree, all here.
The ::before used CSS escapes written through a Python string, which ate them
(octal escape) and shipped control bytes — the button read as mojibake.
- use a literal UTF-8 arrow instead of \2193\0020
- figcaption is now flex, so a long title wraps under the button rather than
being crowded by a float; verified at 360px and 680px
- round the shown duration down so it matches the player's clock (197 s = 3:17)
Tutorial on turning untimed AI-generated audio into LRC + SRT: align ASR word
timestamps against the KNOWN lyrics (SequenceMatcher) instead of trusting a
transcript, then a governor that rejects impossible anchors, refills runs by
unit-proportional duration, and enforces a 1.2 s minimum line gap.
Ships 18 English songs (342 subtitle lines, mean anchor coverage 0.96, 9/18
fully anchored) with synced lyrics plus downloadable .srt per track. Documents
both player bugs and the headless-Chrome numeric probe that finally caught them.