SKILL: Subtitles Studio — 動的サブタイトルのモジュラーライブラリ (subtitles_studio)
1. AIのための概要
公式リポジトリ:https://github.com/NicolasCoder/subtitles_studio.git
このフォルダは、HyperFrames (1080x1920 @ 30fps) 向けにLockupスタイル(フォントのアセンダー/ディセンダーの実際の隙間を利用して、中央に巨大なメインワードを配置し、その隙間に小さな単語を収める)の動的サブタイトルを生成するための100%独立した共有可能なツールボックスです。
フォルダ構造
subtitles_studio/
├── SKILL.md # AIエージェント向け完全ガイド
├── README.md # 人間向けクイックガイド
├── requirements.txt # fonttools, brotli, Pillow, numpy
├── cli.py # 即時利用可能なコマンドラインインターフェース
├── fonts/ # 事前パッケージ化されたローカル .woff2 フォント(+ Google Fonts 自動ダウンロード)
├── caption_kit/ # インポート可能なPythonパッケージ
│ ├── __init__.py # 公開API
│ ├── nesting.py # 実際のグリフジオメトリエンジン + Google Fonts 自動ダウンロード
│ ├── grouper.py # 賢い単語単位のグルーピング(ホールド0.38秒以上、ちらつき防止)
│ ├── renderer.py # HTML/CSS/GSAP コンパイラ、styles/ からの動的読み込み
│ └── transcribe.py # 単語単位の文字起こし (CrisperWhisper / faster-whisper / whisper)
├── styles/ # スタイルモジュール(1 .py または .json ファイル = 1つの共有可能スタイル!)
│ ├── _TEMPLATE_NOVO_ESTILO.py # 新しいスタイル作成用コメント付きテンプレート
│ ├── bold_ciano.py # ボールドソーシャル — シアン (#3de0c8)
│ ├── bold_vermelho.py # ボールドソーシャル — レッド (#ff3355)
│ ├── bold_roxo.py # ボールドソーシャル — パープル (#b855ff)
│ ├── bold_dourado.py # ボールドソーシャル — ゴールド (#ffd24a)
│ ├── editorial.py # エディトリアルミックス (Inter 900 + Playfair Display Italic)
│ ├── gold_script.py # ゴールドスクリプト (Pinyon Script + Oswald)
│ └── poster_impact.py # ポスターインパクト (League Gothic + Montserrat 900)
└── examples/ # テスト用の既製サンプル(ポルトガル語)
├── demo_words_pt.json # タイムスタンプ付き単語(ポルトガル語)
└── demo_groups_pt.json # lockup/plain グループ(ポルトガル語)
2. コマンドラインでの使用法 (cli.py)
# 1. styles/ にインストールされている全スタイルを一覧表示
python cli.py --list-styles
# 2. 任意のスタイルで簡単デモを生成
python cli.py --demo --style bold_roxo
# 3. タイムスタンプ付き単語JSON (word, start, end) から生成
python cli.py --words examples/demo_words_pt.json --style bold_vermelho --out output/meu_teste
# 4. スタイルを編集せずにアクセントカラーをその場で変更
python cli.py --words examples/demo_words_pt.json --style bold_ciano --accent "#00ff88"
# 5. 動画/音声 (.mp4/.wav/.mp3) を文字起こしし、同期サブタイトルを生成
python cli.py --media meu_video.mp4 --lang pt --style bold_dourado --video meu_video.mp4
3. Pythonでの使用法(HyperFramesプロジェクトへの組み込み)
HyperFramesでAロール、Bロール、モーション、SFX、音楽を含む完全なコンポジションを組んでいる場合、caption_kitをインポートし、render_embeddable()を使用します。
import sys
sys.path.insert(0, "caminho/para/legendas_dinamicas_kit")
from caption_kit import build_groups_from_words, render_embeddable
# 1. `words` はリスト [{"word": "Criar", "start": 0.15, "end": 0.42}, ...]
groups = build_groups_from_words(words, min_hold=0.38)
# 2. CSS、DOM(lint警告ゼロの内部 <span> 付き)、GSAP JSを生成:
caps_css, caps_dom, caps_js, report = render_embeddable(
groups,
prefix="v1", # IDの一意なプレフィックス(#v1-g0, #v1-g1...)
style_name="bold_vermelho", # styles/<名前>.py の任意のファイル
accent_override=None, # または例: "#ff3355" で色だけ変更
y_lockup=0.74, # Reels安全圏(1080x1920で1300-1560px)
y_plain=0.75,
track_index=3,
z_index=95,
)
あとは以下を注入するだけです:
{caps_css}をコンポジションの<style>タグ内に{caps_dom}を<div id="root" ...>内に{caps_js}をconst tl = gsap.timeline({ paused: true });直後の<script>内に
4. 新しい共有可能スタイルの作成方法 (styles/ プラグインシステム)
スタイルシステムは100%プラグアンドプレイとして設計されています:
styles/フォルダ内の、名前が_で始まらないすべての.py(または.json)ファイルは、load_styles()によって自動的に検出されます。- ユーザーから新しいスタイルのリクエストがあった場合:
styles/_TEMPLATE_NOVO_ESTILO.pyをstyles/<スタイル名>.pyにコピーします。- 辞書
STYLE = { ... }を編集します。 - Google Fonts の新しいフォント(例:“Bebas Neue”、“Poppins”、“Syne”)を使用する場合、手動でダウンロードする必要はありません:エンジン
caption_kit/nesting.pyが初回実行時に自動的に.woff2ファイルをダウンロードし、fonts/<ファミリー>/に保存します! - ユーザーがこのスタイルを他の人と共有するには、この単一のファイル
styles/<スタイル名>.pyを送信するだけです!
STYLE 辞書の構造
STYLE = {
"id": "neon_cyber",
"label": "Neon Cyber (Montserrat 900 + グリーングロー)",
# メインワード(lockupの中央)
"main_font": "Montserrat",
"main_weight": 900,
"main_style": "normal",
"main_track": -0.05,
"main_case": "none", # 重要:アセンダー/ディセンダーを保持し、収まりを可能にするには "none" を使用! "nest_mode": "overlap" の場合のみ "upper" を使用。
"main_lh": 0.80,
"main_css": "color:#ffffff;text-shadow:0 10px 34px rgba(0,0,0,.6);",
"max_px": 280,
# 補助の小さな単語(上と下)
"small_font": "Inter",
"small_weight": 800,
"small_style": "normal",
"small_track": -0.03,
"small_case": "none",
"small_css": "color:#ffffff;text-shadow:0 5px 20px rgba(0,0,0,.6);",
"small_scale": 0.44, # メインサイズの0.25〜0.50
# シンプルな連続字幕
"plain_font": "Inter",
"plain_weight": 800,
"plain_style": "normal",
"plain_case": "none",
"plain_css": "color:#ffffff;text-shadow:0 5px 20px rgba(0,0,0,.6);",
# アクセントカラーと光彩
"accent": "#00ff88",
"accent_extra_css": "text-shadow:0 0 24px rgba(0,255,136,0.55);",
"shine": ("#ffffff", "rgba(0,255,136,.9)"),
# ジオメトリとアニメーション
"tilt": (-2, 2), # 上段・下段の行の傾き(度)
"clear": 0.03, # インク間の最小クリアランス
"variants": ("slam", "letters", "rise", "blur"),
}
5. 品質の黄金律(本番で学んだこと)
- 読み取り時間(最小ホールド): グルーパー(
caption_kit/grouper.py)は、ブロックを切り替える前に文全体が画面に表示されている時間を最低0.38秒保証します。話す速度が速い場合、単語のステガーエントリーを圧縮し、文の終わりが途切れないようにします。 - 時系列順: 行は常に実際に話された順序で入力されます(
above→main→below)。 - Instagram Reels / TikTok のセーフゾーン (
1080x1920):- デフォルト
y_lockup=0.74(~1420px)で、安全圏1300–1560px(顔やモーションカードの下、Reelsの下部ボタンの上)に収まります。
- デフォルト
- HyperFramesでの音声同期:
- 動画が複数のセグメントに分割された音声を使用する場合、決して複数の
<audio>タグを同じファイルに対してdata-media-startで使用しないでください(HyperFramesで音声がずれます)。常に音声を連続した単一の.wavファイルに事前にカットし、単一の<audio data-start="0.000">タグを使用してください。
- 動画が複数のセグメントに分割された音声を使用する場合、決して複数の