Remotion 口播包装デザインシステム(v1 hub)
スタイル目標:基準動画の口播HUD包装を再現する(参考画像はプロジェクトrefs/にあります)。このファイルは厳格な制約ハブです:鉄則 + トークン意味論 + コンポーネントクイックリファレンス + エラー事例集。各セクションの詳細はreferences/にあります(2026-07-16 深層比較による77の差異を反映した集約地点)。システムに記載されていない視覚的決定は、まず該当セクションファイルに追加してからコードを書いてください。
セクションルーティングテーブル(必要なファイルを読む)
| セクション | ファイル | 担当範囲 |
|---|---|---|
| 仕様表(先に確認してから書く) | references/specs.md | 基準動画から実測した数値の真のソース:カード幅/フォントサイズ/位置/アニメーションフレーム数。組み立て前に必ず確認。表にない場合は実測してから記入し、目視は禁止 |
| レイアウト構成 | references/layout.md | 3ゾーン、takeoverメカニズム(A級はPiPなし、暗転スローモーションは却下済み)、1画面1重心、グループテンプレート、噛み合わせ位置 |
| タイポグラフィ | references/typography.md | 唯一の最大フォント、h1義務、heroサンドイッチ、SideLabel titleバリアント |
| 色彩・質感 | references/texture.md | ゼリー状ブロック/glow、SURFACE明暗バリアント、スタンプ仕様唯一線、同一画面色系≤2、明るい背景での文字むき出し禁止の詳細 |
| 動き | references/motion.md | useEnter/useExit、分割拍、build-up、稼働区間、Breathe、クリア画面 |
| 情報デザイン | references/infographic.md | チャート選択、比喩的な図形化、waffle、大きな数字3層、マイクログラフィック語彙 |
| ナレーション/リズム/字幕/素材/音声 | remotion-assembly の references/ | narrative / rhythm / subtitle / broll / audio |
| エラー事例集(症状→修正方法インデックス) | 独立スキル remotion-gotchas-index | 全文「エラー #NN」の修正位置をここで確認。レンダリング異常や画面がおかしい場合はまずここをチェック |
エンジニアリング基盤リスト(substrate —— コールドスタート/新規動画開始前に確認)
このデザインシステムは全リポジトリで共有される基盤であり、各動画で再構築するものではありません。 以下のファイルは、一連のフロー(assembly「入力検収→フレーム出力→3ゲート」+ motion §12ゲート)の実行前提です。新規動画はデフォルトでこれらを再利用し、自身のcomposition + 字幕 + Sceneのみを追加します。基盤を再作成しません。コールドスタート読者(src/を読まない)はよくここでつまずきます——まずこの表でファイルが存在することを確認し、具体的な数値を取得するには対応するファイルを開いて読んでください。スキルに値を書き写すことは期待しないでください。
| 基盤ファイル | 内容 | コールドスタートでの使い方 |
|---|---|---|
src/design/tokens.ts | 数値の唯一の真のソース: COLOR(4意味論 + 基本色hex)、SURFACE、FONT、GRADIENT、SIZE段階(kicker…mega)、GRID、RADIUS、SAFE、MOTIONフレーム数 | SIZE.megaや意味論色hexなど具体的なピクセル/色は、このファイルを直接読んで取得——スキルは意図的に値を書き写さない(スナップショットとコードのずれを防ぐため、§1参照)。ファイルがない=基盤欠落。まず基盤を構築 |
src/design/*.tsx | コンポーネントライブラリ(§3全表:SideLabel/HeroText/Chip…)+ FontGuard.tsx(フォントガード、エラー #01)+ qc.tsx(QCプローブ QcProbe:フレームごとに[data-qc]ボックスを読み重なりを判定、エラー #29) | 包装要素を書く前に§3コンポーネント表でファイルを特定 |
src/design/motion.ts | useEnter/useExit/usePop 基本フック + MOTION定数 | motion.mdのルールで参照されるフックはすべてここ |
src/design/fonts.ts | @fontsource ローカルフォント登録(エラー #01:webfontはネット経由だと静かに明朝体になる) | package.jsonのsideEffectsに必ず含める |
src/koubo/scenes/shared.tsx | 組み立て層ゲート4点セット Enter/DimAfter/Exit/ClearOut(motion §12)+ Place 位置決めボックス + qcAllow QC噛み合わせホワイトリスト(assembly §2.5 ゲート①) | Sceneを組み立てるときは直接これらのラッパーを使用。opacityを手動で操作しない |
src/Root.tsx | composition登録場所(既存<Composition id="Koubo-0715-01" fps={30} …/>) | 新規動画はここに<Composition>を1行追加。idは自由。セグメントレンダリングスクリプトはこのidと一致させる(assembly §6 render-serviceのid変更参照) |
src/koubo/ | 各動画専用: subtitles-<動画名>.ts / SubtitleTrack.tsx / <動画名メインコンポーネント>.tsx / scenes/SceneNN.tsx | 新規動画はこの層にのみファイルを追加(構造はassembly §4参照) |
本当のゼロからのブートストラップ(src/が完全に空): 基盤が存在しないとassemblyフローは開始できません(トークンを取得できず、最初のフレームを出力できず、3ゲートを通過できません)。順序=まず基盤を構築してから組み立て:① tokens.tsで数値の真のソースを定義 → ② fonts.ts + FontGuard.tsx(エラー #01)→ ③ motion.ts 3フック → ④ §3コンポーネントライブラリ → ⑤ src/koubo/scenes/shared.tsx ゲート4点セット + Place/qcAllow → ⑥ src/design/qc.tsx QCプローブ → ⑦ src/Root.tsx composition登録。このリポジトリのsrc/designを参考実装として移植。移植後も数値はtokens.tsから読み取る。スキルに値を書き戻さない。
0. 六つの鉄則
- 情報エリアはデフォルトで左、人物は右: 情報エリアはデフォルトで左(ユーザー裁定の作成者デフォルト)、HUDは左側に垂直方向に固定、人物エリアへの進入は禁止。ただし各動画の構成はまずユーザーに確認し、勝手に決めない。3ゾーン座標とtakeover例外メカニズムはreferences/layout.md ルール1を参照。
- すべてのテキストは二層構造: 英字UPPERCASE広字間kicker(小)+ 中国語太ゴシック(大)。一層のみのテキストコンポーネントは未完成とみなす。
- 1文につき強調する単語は1つだけ: 中国語タイトル内で色を変える/強調する箇所は最大1箇所。色は必ず4色意味論システムから取得。
- 本物の素材を主体とし、Remotionはシンセサイザーであり描画ボードではない(2026-07-16 seg01 決定アップグレード):「製品体験」系の画面(タイピング/生成/インターフェース/デモ)はすべて本物の素材を編集——自分で録画したスクリーン > 公式動画 > ウェブページのスクリーンショット > UIシミュレーションカード。手描きはHUD層(サイドラベル/字幕/チャート/スタンプ/比喩的な図形)のみ。CSSでプロのモーションチームの作品を手作りすることは必ず失敗する。「どう調整してもなんとなく違う/遠く及ばない」の根本原因は、描画ボードでシンセサイザーの戦いをしていることにある。収集と編集パイプラインはassembly references/broll.mdを参照。
- 明るい背景での文字むき出し禁止(2026-07-16 深層比較裁定、6セクションにまたがる最優先クロスルール):明るい背景(白板/白壁/薄色テイクオーバー底面)の上に背景なしの文字を配置してはならない。すべての文字は濃い色のベースパネル(SURFACE.darkPlate)、カード本体、またはlight表面バリアントの上に置く必要がある。textShadowは解決策とみなさない。詳細はreferences/texture.mdを参照。
- 1画面に1つの支配的層: 各情報画面には1つだけ「最大の文字/最大の要素」がある。メインエリアの外には最大2つのチップレベルの小さな要素のみ。詳細はreferences/typography.md と layout.mdを参照。
1. Design Tokens
唯一の真のソース = src/design/tokens.ts。すべてのコンポーネントはそこからの値のみをインポートすること。このセクションでは意味論と使用ルールのみを記述し、数値は書き写さない——以前スナップショットとコードのずれが発生したため(2026-07-16 kicker/h1など複数箇所で不一致を発見)、コードを優先する。
- 4色意味論(唯一許可される強調色):blue=定義/方法/中立的な推進;green=ポジティブ/低障壁/有効済み;yellow=機会/警告/論争/転換;red=ネガティブ/落とし穴/危機。基本色としてwhite/grey/greyDim/cardBg/cardStroke。
- フォント(2層、混同しないこと):MG包装層——
FONT.zh=Noto Sans SC(包装層中国語唯一フォント、タイトルは一律FONT.zhHeavy);FONT.en=Inter(kicker/本文/数字);FONT.enTitle=Archivo Black(英語タイトルと大きな文字の結論、幅狭スーパーブラック、weightは一律400——Interは大きな文字の迫力を支えられない、2026-07字形比較結論)。下部字幕層——FONT.subZh=PingFang SC 400 /FONT.subEn=Inter 300(2026-07-26 5段階実写比較後ユーザー裁定):字幕は読み取り層であり包装層ではない。細い書体だけがApple字幕のような質感を持ち、MG太ゴシックタイトルとの階層差を確保し、注意を奪わない。旧版はNoto 700で全体を構成しており、ステッカーのように見えた。PingFang SCはmacOSシステムフォントであり、@fontsourceパッケージを使用しない——ローカルレンダリングでは問題ないが、Windows/Linux環境ではパッケージされたNoto Sans SC 400細字にフォールバックする(fonts.tsで既に導入されており、見た目は近いが同一ではない)。異なるマシンでのレンダリング前に1フレームレンダリングして字幕の見た目を確認すること。英字字幕行はプロポーショナル欧文フォントを使用する必要がある。エラー #42参照。 - 大きな文字の結論は一律純粋な意味論色 + textShadow。backgroundClip:textグラデーション文字は禁止(エラー #06)。
GRADIENTは色ブロック/ストローク系の用途のみ。 - フォントサイズは
SIZE段階(kicker / subSmall / chip / subZh / subEn / card / h2 / h1 / mega)のみ許可。段階外のフォントサイズは禁止。1080p基準、4K出力は等比×2。 - 間隔は一律
GRID(8px)の倍数。角丸はRADIUS。セーフゾーンはSAFE(サイドラベルアンカー、スタック左端、字幕下端。常駐カードはx55%を超えない。人物進入禁止エリア/右エリア座標はlayout.md参照。字幕禁止エリアはy>82%。左エリア要素の下端はy≤840がy82%よりも厳しい左エリア硬線)。
2. チャプターサイドラベル SideLabel(全編常駐、最優先コンポーネント)
- 構造:
│(4px縦線、意味論色)+ENGLISH KICKER · 中国語フレーズ(1行目、英字はkicker仕様+意味論色、中国語は白34px)+ 2行目グレー24px補足説明。 - 位置:固定
SAFE.sideLabel。切り替え時は古いラベルが12フレームでフェードアウト、新しいラベルが15フレームで左からスライドイン。 - 命名は番号体系:
SCENE 01、PATH 1/2/3、正反対仗(DISSOLVED·01..vsIMMUNE·01..)。 - 色 = このセクションの感情意味論。tokensのコメントを参照。参考:
refs/01-版式与側標/。
3. コンポーネント仕様クイックリファレンス(詳細は実装とともに補充、まず参考図を見てからコードを書く)
| コンポーネント | 主要仕様 | 参考 |
|---|---|---|
| BilingualSub | 中52白+黒影 / 英28純白、下部中央、常に最上層 | 任意のrefs |
| HeroText | kicker + 中国語h1/h2、強調語は意味論色に変更;バリアント:赤取り消し線修正、黄ブラシ下線、傾斜スタンプ | refs/02 |
| Chip | 黒カード RADIUS.chip + カラーアイコン + 34pxテキスト、1箇所色変更可能 | refs/03 |
| Checklist | Chipを縦に積み重ね、1つずつポップイン;未アクティブな項目はopacity 0.35 | refs/03 |
| InfoCard | アイコン + kicker + 44pxタイトル + 青強調語 | refs/01 |
| StepList | ①②③丸数字 + 中国語 + 英語小kicker、順次点灯 | refs/04 |
| FlowChain | 黒カード + → 矢印で連結、ノードごとに出現 | refs/04 |
| CompareCard | logo + 名称 + 赤×弱点chip + 緑✓強みchip、縦積み | refs/04 |
| Formula | 大文字A記号B(>、»、⇄、=)、記号は意味論色 | refs/05 |
| BigNumber | Inter大数字 + 単位小文字 + kicker;カウンターはspringスクロール | refs/05 |
| BarChart | データバー8px角丸;強調バーは黄色 + 上部クラウンchip;その他は灰色 | refs/05 |
| CurveOverlay | 2–3px黄色曲線をB-rollに直接重ね、右端点にラベル | refs/05 |
| Timeline | 両端点区間型 / イベントに赤緑結果chipを付ける型 | refs/05 |
| ScoreBoard | 緑:赤大数字スコア | refs/05 |
| PhoneMockup | iPhoneフレーム + グラデーションストローク発光 + 内蔵スクリーンショット長尺スクロール | refs/06 |
| WindowCard | mac信号アイコン + アプリアイコン + 機能chip、内容は動的 | refs/04 |
| QuoteDoc | 白背景スクリーンショットカード + 黄蛍光マーカー + 黒背景中国語翻訳バーオーバーレイ | refs/07 |
| TweetCard | アバター + 身元kicker + 赤大文字結論 + views chip | refs/07 |
| PersonCard | 丸アバター + 名前 + 身元小文字 + 組織chip | refs/07 |
| Stamp | 傾斜 -8°~-6°ストロークスタンプ文字(赤/緑)、スタンプアニメーション=scale 1.3→1 + 軽微な振動 | refs/08 |
| MatrixIcon | ブロック行列アイコン:赤=溶解される陣営 / 緑=免疫陣営 | refs/08 |
| CardWall | 白い小さなカード3→20枚を1枚ずつ敷き詰め、需要爆発をシミュレート | refs/06 |
| BeforeAfter | 2つのアイコンカード + 青矢印 + 下部結論chip | refs/04 |
| Breathe | idle微動ラッパー:呼吸scale ±0.6% + 浮動±3px、phaseで位相をずらし同期防止;主人公要素の外側をラップ | src/design/Breathe.tsx |
| BrickWall | つなぎ目をずらした金レンガの横壁をブロックごとに積み上げ + 中央ラベル、「壁を建てる/硬い障壁」比喩 | src/design/BrickWall.tsx |
| UnitMatrix | Nグループのブロック行列をセルごとに点灯;fillRatio waffleモード(73%データフィールド) | src/design/UnitMatrix.tsx |
| CloneCascade | ソースアイコンカード + 模倣品が順にフェードイン + 警告chip、「コピー/蒸留される」比喩 | src/design/CloneCascade.tsx |
バッチライン Scene内連要素(2026-07-17 バッチ生産で追加、まだ共有コンポーネントに昇格していない)
以下の要素は現在単一のScene内にのみ存在する。ラベルは「Scene内連。2回目に再利用するときにsrc/design共有コンポーネントに昇格し、specs仕様行を補完する」——新規動画で同じような要件に遭遇した場合はまずここを確認し、再作成しないこと:
| 内連要素 | 位置 | 機能 | 昇格条件 |
|---|---|---|---|
| DissolveGrid | scenes/Scene08.tsx | 溶解グリッド:溶解される陣営のブロックがセルごとに溶け散る、中央⚡基盤がフェードアウト後白い輪郭が浮遊 | 「陣営溶解」比喩が2回目に再利用されるとき |
| VerdictBox(決算枠) | scenes/Scene17.tsx | 赤緑ミラー決算枠:≈400×170ストローク空枠を先に立てる + 枠内header + 横並び3chipをバッチで枠内に入れる(赤が先に満杯、緑が後に満杯、「あなたはどちら側?」という宙ぶらりんを生む) | 「VS決算」が昇格されるとき |
| NamePlate + CtaBadge(CTAバッジ列) | scenes/Scene19.tsx | エンディングCTA下部横一列:NamePlateが先に着地してアンカーに → 4アクションバッジが1枚ずつポップイン(コメントバッジが最後で最も幅広=強調) | 2回目のエンディングCTA終了時 |
アイコン仕様
- アイコンは一律lucide-react line SVGアイコンを使用。色は意味論色(
COLOR[accent])、strokeWidth 2.5程度。絵文字は禁止(カラフルな角丸ブロックは基準動画の単色ラインスタイルと競合する、2026-07 第3回検収の教訓)。 - Chip / Checklist / SideLabelの
iconpropはReactNodeを受け付ける:icon={<Lock size={26} strokeWidth={2.5} />}。
質感仕様 → references/texture.md
ゼリー状ブロックグラデーション、同色glow、vignette、本物のロゴ、SURFACE明暗バリアント、スタンプ仕様唯一線はすべてtexture.mdに記載(2026-07-16以降、質感の唯一の真のソース。このセクションの旧文は既に移動済み)。
4. 動きルール → references/motion.md
useEnter/useExit、分割拍入場、稼働区間、Breathe、章間クリア画面、禁止事項はすべてmotion.mdに記載(2026-07-16以降、動きの唯一の真のソース。このセクションの旧文は既に移動済み。注意:旧ルール「古い情報を透明度下げて常駐」は「稼働区間+退場規律」に置き換え済み)。
5. エクスポート前セルフチェック(レンダリングごとに1回実行)
- grepでコンポーネントがtokens外の色値/フォントサイズ/フォントをインライン化していないか確認。
- すべての常駐カードがfaceZone / subtitleZoneを越えていないか。
- 各タイトルの強調語が≤1箇所か;英字kickerが全大文字+文字間隔か。
- 3–5のキーフレームをrefs/の対応する参考図と並べて比較。似ていない場合は、どのトークンが異なるかを特定し、トークンを変更。コンポーネントのインラインは変更しない。
6. エラー事例集
#01 中国語が静かに明朝体に退化(2026-07-15 · デザインシステム初日)
- 症状: レンダリング/スクリーンショットで中国語が明朝体になり、英字は正常。同じコンポーネントでも時々正常、時々異常(運次第)。
- 原因: 3層、最後の層が真の原因。①
@remotion/google-fontsが実行時にgstaticからフォントを取得、国内ネットワークでは取得できず静かにフォールバック。② 中国語webfontはunicode-rangeでパッケージ分割されており、読み込みとスクリーンショットの間に競合状態が発生。③ ツリーシェイキング:package.jsonのsideEffects: ["*.css"]により、副作用としてのみインポートされるfonts.tsがプロダクションバンドルで完全に除去され、フォントCSSがレンダリングバンドルに含まれない(document.fonts.size === 0)——Studio開発モードではツリーシェイキングされないため、「Studioでは正常、レンダリングで失敗」。 - 修正方法: ① フォントは
@fontsourceローカルパッケージを使用(src/design/fonts.ts)。②package.jsonのsideEffectsに"src/design/fonts.ts"を含める必要がある。③ テキストを含む合成は<FontGuard/>を追加:load→checkループ検証、かつdocument.fonts.size > 0も同時に確認する必要がある(fonts.check()はフォント登録がゼロの場合に空振りでtrueを返す)。タイムアウト時は直接cancelRenderでエラーを報告し、静かに明朝体のフレームを生成してはならない。 - 教訓: 「Studioでは正常、エクスポートで失敗」の場合は、まずプロダクションバンドルの差異(ツリーシェイキング/圧縮)を疑うべきであり、不可解な競合状態ではない。フォントの検収はFontGuardのハードゲートに頼る必要があり、人間の目ではサムネイルを信用できない。
#02 remotion still 出力「○」= 古い画像を再利用
- 症状: コードを変更して再レンダリングしても、出力ファイルに変化がないように見える。コマンドラインに
+ではなく○が表示される。 - 修正方法: レンダリング検収の前に古い出力を削除する(または新しいファイル名にレンダリングする)。必要に応じて
--bundle-cache=falseを追加。+=実際のレンダリング、○=疑わしい。 - 教訓: 比較検収は、確実に新しいレンダリング成果物に基づいて行う必要がある。そうしないと「修正が効かなかった」と誤診する可能性がある(今回、このために2周余計に回した)。
#03 サムネイル比較画像は人を騙す可能性がある
- 症状: 並べて比較した小さな画像では中国語が明朝体に見えるが、原画像は実際には正常。
- 修正方法: フォント/ストロークの詳細を判断する際は、原解像度の部分を切り取って拡大して見る必要がある。フレーム全体のサムネイルで結論を下してはならない。
#04 JSX属性の文字列は\uXXXXエスケープを解析しない
- 症状:
<Chip icon="\u2705" />で画面に✅ではなくリテラル\u2705が表示される。 - 原因: JSX属性の文字列リテラルはHTMLスタイルのテキストであり、JSのエスケープ解析を経由しない。JS式内の文字列(
icon={'\u2705'})のみエスケープを解析する。スクリプトでバッチTSXを書くときに最も踏みやすい。 - 修正方法: JSX属性内の絵文字/特殊文字は直接実際の文字を書く(
icon="✅")。エスケープがどうしても必要な場合はicon={'\u2705'}と書く。
#06 backgroundClip: text グラデーション文字のレンダリングが暗い
- 症状: 大きな文字タイトルでbackgroundImageグラデーション + WebkitBackgroundClip:'text' + WebkitTextFillColor:'transparent'を使用。Studioではまあまあだが、レンダリング出力画像の色が暗くくすむ(明るい赤がレンガ色に)。ユーザーに即座に却下される。
- 修正方法: 大きな文字の結論は一律純粋な意味論色
COLOR[semantic]+ textShadow。階層感が必要な場合は影とフォントウェイトに頼り、グラデーション塗りつぶしには頼らない。tokens.GRADIENTは色ブロック/ストローク系の用途のみ。
#08 完成品MG文字のエッジのにじみ、塗りつぶし感(「MGを追加すると画質が悪くなる」)(2026-07-16 · 0715-01 v3)
- 症状: ユーザーが完成品を見て画質が悪いと言う。拡大するとMG文字のエッジにJPEGモスキートノイズ/にじみがある。シャープな要素ほど顕著。素材自体は15 Mbps HEVCで非常にクリア。
- 原因: Remotionのデフォルトパイプラインによる二重圧縮——各フレームを品質80のJPEGでキャプチャし、次にCRF 18でH264に圧縮。MG大文字/細線は高周波信号であり、最初に圧縮アーティファクトが現れる。MG追加前はアーティファクトが実写テクスチャに隠れて目立たないため、「MGが画質を悪化させている」と誤診される。
- 修正方法:
remotion.config.tsでConfig.setJpegQuality(100)+Config.setCrf(15)を固定(本プロジェクトでは既に設定済み、戻さないこと)。容量は約+20%、レンダリングはやや遅くなるが、価値あり。 - 診断方法: 同じフレームを素材/旧完成品/新パラメータテストセグメントからそれぞれ切り取り、同じMG文字領域を拡大して並べて比較。最初に5秒のテストセグメントをレンダリングしてパラメータを検証してから全編をレンダリングする。
#09 長時間レンダリングの途中消失、mp4が壊れた断片に(2026-07-16 · 0715-01 v3)
- 症状: レンダリングが長時間実行された後、「プロセスは存在する」が成果物ファイルが長時間増加しない。または、レンダリングが静かに消え、開けないmp4が残される。
- 原因: ① レンダリングがAIセッションの子プロセスにぶら下がっており、セッションの再起動/終了がレンダリングも巻き添えで殺す(今回は90%で殺された)。② プロセス検出に
pgrep -f "remotion render"を使用すると、検出スクリプト自身も一致する(コマンドラインに同じ文字列が含まれているため)、「プロセスは生きている」という誤った印象を与える。 - 修正方法: ① 数分を超えるレンダリングは一律
nohup npx remotion render … > /tmp/xx.log 2>&1 & disownでセッションから切り離す。② 完了判定はログ内の+ 出力ファイル名行を認識する(+=実際のレンダリング成功)。プロセスの存在を認識しない。③ プロセス検出は自己一致を除外する(CPU使用率を見るか、正確なPIDを使用)。④ 再レンダリング前に壊れた断片を削除する。 - 教訓: 壊れたmp4断片(長さ/容量が合わない)は絶対に納品しない。まず
ffprobeで長さとオーディオトラックを確認してからユーザーに見せる。