Linux サーバーで動画をプログラマブルに生成したいエンジニア向けです。オープンソースの動画レンダリングエンジン HyperFrames を使い、HTML/CSS/GSAP で書いたアニメーションを headless Chrome + FFmpeg 経由で MP4 に変換する環境を、sudo 権限なし(一般ユーザー)の Ubuntu サーバーに構築した記録を全部書きます。最大の詰まりポイントだった日本語フォント豆腐問題(テキストが□□□になる)の解決策まで含めています。
この記事でできること
- HTML/CSS/GSAP で書いたアニメーションを MP4 動画に自動変換できる
- GPU なし・Docker なしで Linux サーバーに動画生成環境を構築できる
- 日本語テキストが豆腐(□□□)になる問題の原因と解決方法がわかる
使ったもの
- HyperFrames — HTML/CSS → MP4 変換エンジン(OSS、Apache 2.0)
- nvm — Node.js バージョンマネージャー(sudo なしでインストール可)
- Node.js 22 — HyperFrames の実行環境(22 以上が必須)
- FFmpeg — 動画エンコーダー(静的バイナリで sudo なしインストール)
- Python 3 — 呼び出し元ラッパースクリプト用
背景
HyperFrames を知ったきっかけは X(Twitter)のタイムラインでした。「GPU なし・Docker なしで HTML を動画に変換できる OSS」という投稿が英語圏のエンジニアを中心にかなり広まっていて、試してみようと思いました。
欲しかったのは SSH 経由で他のスクリプトから MP4 動画を自動生成する仕組みです。GPU を占有したくない、Docker を入れたくない、という縛りの中で HyperFrames は選択肢として合理的でした。HTML/CSS という既存の Web 技術でアニメーションを記述でき、CPU レンダリングで動き、一般ユーザー環境に収まる点が決め手でした。
環境: Ubuntu 22.04、sudo 権限なし(一般ユーザー)。
手順
1. Node.js 22+ のインストール(nvm 経由)
HyperFrames は Node.js 22 以上が必須です。多くの Ubuntu 環境では apt で入る Node.js が古いため、nvm でユーザーレベルにインストールします。
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
$ source ~/.bashrc
$ nvm install 22 && nvm alias default 22
$ node -v
v22.x.x
詰まりポイント: nvm でインストールした node は ~/.nvm/versions/node/v22.x.x/bin/ に置かれます。SSH 経由のスクリプト実行では ~/.bashrc が読み込まれないため PATH にこのパスが含まれません。SSH 経由で呼び出すスクリプトでは冒頭に以下を追加してください。
export NVM_DIR="$HOME/.nvm"
source "$NVM_DIR/nvm.sh"
2. FFmpeg のインストール(静的バイナリ)
sudo なしで FFmpeg を入れるため、静的ビルド済みバイナリを取得して ~/.local/bin/ に配置します。
$ mkdir -p ~/.local/bin
$ cd /tmp
$ curl -L https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz \
| tar xJ
$ cp ffmpeg-*-static/ffmpeg ~/.local/bin/
$ echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
$ source ~/.bashrc
$ ffmpeg -version | head -1
3. HyperFrames のインストール
$ npm install -g hyperframes
$ hyperframes --version
4. Chrome Headless のインストール
HyperFrames はフレームのキャプチャに headless Chrome を使います。以下のコマンドで自動ダウンロードします。
$ hyperframes browser ensure
node と ffmpeg が PATH に通った状態で実行する必要があります。which node && which ffmpeg で両方の場所が表示されることを確認してから実行してください。
5. 日本語フォント問題の解決(最大の詰まりポイント)
HTML テンプレートに font-family: 'Noto Sans JP' を指定して動画を生成すると、日本語テキストが豆腐(□□□)になります。HyperFrames のログには「Fetched 1116 font face(s) for "Noto Sans JP" from Google Fonts」と出るのに、です。
原因
Google Fonts は Noto Sans JP を Unicode の範囲(サブセット)ごとに分割して配信します。HyperFrames がキャッシュしていたのは Latin サブセット(81KB)のみで、日本語グリフを含む CJK サブセット(1 ウェイトあたり 4〜5MB)はダウンロードされていませんでした。
headless Chrome はシステムフォントを直接参照するため、TTF をシステムフォントディレクトリに直接インストールするのが解決策です。
解決手順
以下のように curl で TTF を直接取得します。User-Agent をブラウザに偽装しないと woff2 サブセット版が返るため豆腐が解決しません。
$ mkdir -p ~/.local/share/fonts
# User-Agent をブラウザに偽装して TTF を取得(必須)
$ curl -L -A 'Mozilla/5.0 (X11; Linux x86_64)' \
'https://fonts.gstatic.com/s/notosansjp/v56/-F6ofjtqLzI2JPCgQBnw7HFowAA.ttf' \
-o ~/.local/share/fonts/NotoSansJP-Regular.ttf
# フォントキャッシュを更新
$ fc-cache -f ~/.local/share/fonts/
# 確認
$ fc-list | grep "Noto Sans JP"
fc-list の出力に NotoSansJP が表示されれば成功です。URL 中の版番号(v56)は変わる場合があります。最新の URL は Google Fonts の「Download family」から取得した zip を ~/.local/share/fonts/ に展開する方法でも対応できます(こちらの方が URL に依存しないため安定です)。
ビフォー・アフター
フォント修正前と修正後を並べました。
6. Python ラッパースクリプトの設計(オプション)
他のスクリプトから SSH 経由で呼び出す場合は、HyperFrames を薄くラップした Python スクリプトを用意すると便利です。設計のポイントは以下の 3 点です。
--prompt "テキスト"を受け取り、内部で HTML コンポジションを生成して HyperFrames に渡す(呼び出し元を HTML スキーマから隔離)- スタイル(
fade/slide/motion)を引数で切り替え可能にする fcntl.flockで同時実行を排他制御する(複数プロセスから呼ばれても安全)
呼び出し側は「SSH 1 コマンドで動画ファイルが返ってくる」インターフェースだけ知っていればよく、内部の HTML テンプレートが変わっても呼び出し側を修正する必要がありません。
完成システム
daemon なし、コマンド実行のみ。SSH 1 コマンドで動画ファイルが返ります。
よくある質問
Q. nvm: command not found になります
A. SSH 経由で実行すると ~/.bashrc が読み込まれないため発生します。スクリプト冒頭に source "$HOME/.nvm/nvm.sh" を追加してください。
Q. hyperframes browser ensure が失敗します
A. node と ffmpeg が PATH に通っているか確認してください。which node && which ffmpeg で両方の場所が表示されれば OK です。
Q. 日本語以外のフォント(中国語・韓国語など)も豆腐になります
A. 同様の原因です。対象フォントの完全版 TTF を ~/.local/share/fonts/ にインストールして fc-cache -f を実行してください。
Q. 動画が真っ黒になります
A. Chrome がフレームを描画する前にキャプチャされている場合があります。コンポジションの delay 設定を増やすか、CSS アニメーションの開始タイミングを見直してください。
Q. Node.js 20 でも動きますか?
A. HyperFrames は Node.js 22 以上が公式要件です。nvm install 22 && nvm use 22 で切り替えて使用してください。
※本記事の手順・コードは執筆時点(2026 年 5 月)で動作確認していますが、ライブラリやハードのバージョンが変わるとそのままでは動かない場合があります。動かない場合は コメント欄でお知らせください。
まとめ
HyperFrames を sudo なし Ubuntu サーバーに構築しました。詰まりポイントの本命は日本語フォント豆腐で、Google Fonts のサブセット配信仕様と headless Chrome のシステムフォント参照の組み合わせが原因でした。curl の User-Agent 偽装で TTF を取得してシステムフォントに置くことで解決できます。
この記事が役に立ったら X(Twitter)でシェアしてもらえると喜びます。
HyperFrames で作ったブログプロモーション動画
せっかくなので、このブログ「ON THE HAND」のプロモーション動画を HyperFrames で作りました。過去記事の画像+フェードトランジション+テキストキャプションを組み合わせた 30 秒の動画です。日本語テキストもフォント修正後は正常に表示されています。
このブログを書いた人のアプリ
本ブログの著者が作った iOS 読書管理アプリ わたしのほんやさん を App Store で公開しています。本棚をシンプルに管理したい方はぜひ。
関連記事
- ブログ用 AI 画像をローカル GPU で生成する【SDXL + IP-Adapter + img2img・実生成画像で解説】
- ブログ更新を Claude Code で自動化する仕組み【テーマ選定・画像・週次 cron の試行錯誤を全部書く】
参考
※この記事は Claude Code を使った自動更新を試しています。