2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【切り抜き動画作成?!】mlx-whisper × Remotion × Claude Codeで会議録画から 60 秒ハイライト動画を自動生成してみた

2
Last updated at Posted at 2026-04-18

こんにちは、takatein です。

突然ですが、みなさんは会議録画ってちゃんと見返してますか?

ぶっちゃけ、わたしはほぼ見返さないです。1 時間の Google Meet 録画が日々溜まっていって、「あとで誰かに共有したいやつだけ抜き出したい」と思いつつ、結局そのまま放置…これ「録画見ない問題」、あるあるじゃないですか?

特に「優先度高い打ち合わせが入ってデイリーの打ち合わせ出れない」のような人向けに展開したいなーと思っていました。

そこで、会議録画を「60 秒のハイライト動画」に自動圧縮するパイプラインを Mac 上で作ってみました!

組み合わせた技術はこちらです。

  • mlx-whisper(Apple Silicon に最適化された Whisper 実装)で文字起こし
  • LLM(Claude Code に直接処理させる)でトピック抽出
  • Remotion(React で動画を作るフレームワーク)4.x で動画合成

会議録画の mp4 を投げると 60 秒の mp4 が出てくる、というところまで持っていきます!

想定読者は、Whisper や Remotion を一度は触ったことがある個人開発者です。コピペでひと通り動くハンズオン記事として書いてみました。

入出力と作業時間

ざっくり書くと、入力は「1 時間前後の会議録画 mp4」と「Gemini Meet の議事録要約」。
出力は「60 秒のテロップ付きハイライト mp4」で、3〜4 トピックを抜粋してくれます。

所要時間は、初回 10〜15 分、2 回目以降は 2〜5 分くらい(M3 Mac 24GB で計測)。これなら「会議終わってから 15 分後にはハイライト動画が共有される」みたいな運用ができそうです。

パイプラインの全体像

処理は 7 つのフェーズに分かれます。

Phase 0  symlink 層を作る(日本語ファイル名対策)
Phase 1  音声を抽出(16kHz mono WAV)
Phase 2  文字起こし(mlx-whisper、word-level timestamps 付き)
Phase 3  トピック × 時刻マッチング(LLM)
Phase 4  60 秒分のハイライト選定(LLM)
Phase 5  クリップ切り出し(CFR 30fps 再エンコ)
Phase 6  Remotion でレンダ

Phase 3 と 4 は Claude Code に「 topics.json 作って」「 highlights.json 作って」と頼むだけで終わらせています。

embedding モデル(テキストの意味をベクトル化するモデル)を別途ダウンロードしなくていいのが、地味ですがかなりラクでした!

使った環境

項目 必須条件
OS macOS 14+(Apple Silicon 推奨)
RAM 16GB+
ディスク 10GB+ 空き
Node.js 18+
Python 3.11(uv 経由)

ちなみに Python は 3.14 系だと mlx-whisper の ImportError でハマります(詳細は後述の「ハマったところ」で)。あとのセットアップ手順では 3.11 を明示します。

セットアップしてみる

コマンドラインツールを入れる

ターミナルで以下を実行します。

brew install ffmpeg jq uv
brew install node  # 未インストールの場合

Python 仮想環境を作る

リポジトリのルートに移動して、以下を実行します。

cd <your-repo>
uv venv --python 3.11 meeting_rec/.venv
source meeting_rec/.venv/bin/activate
uv pip install mlx-whisper

このあと、初回実行時に Hugging Face から Whisper モデル(約 1.5GB)が落ちてきます。1〜5 分ほど、コーヒーを淹れる時間にちょうどいい長さです。

Remotion 側を入れる

cd meeting_rec/remotion
npm install

200 パッケージほど、20〜40 秒で終わります。Chromium Headless Shell(90MB)は最初のレンダ時に勝手に取得されるので、初回だけ少し待ちます。

素材を置いてみる

会議ごとに meeting_rec/rec/<日付>/ フォルダを作って、原本素材を入れます。

meeting_rec/rec/
└── 2025_12_04/
    ├── Meeting Recording.mp4
    ├── geminiまとめ.txt
    └── Meeting Chat.sbv  (任意)
ファイル 必須/任意 用途
*.mp4 必須(1 本のみ) 会議録画本体
geminiまとめ.txt 必須 Gemini Meet の要約。トピック分割の元ネタ
*.sbv 任意 Meet のチャットログ。時刻アンカーとして参考利用

ちなみにファイル名に日本語や全角の が入っていても大丈夫です!

最初は素直に日本語ファイル名のまま ffmpeg に渡してドハマりしたんですが、Phase 0 で ASCII 名の symlink に張り直す層を入れたら一気に安定しました。ありがとうClaudeCode。最近シェルも書かなくなりましたねw
「日本語ファイル名はとりあえず symlink」、シェル芸人やってた頃を思い出しました。

動かしてみる

cd <your-repo>

# Phase 0  symlink 層を作る(rec/ 直下の最新フォルダを自動選択)
bash meeting_rec/scripts/00_setup_symlinks.sh

# Phase 1  音声抽出
bash meeting_rec/scripts/10_extract_audio.sh

# Phase 2  文字起こし
source meeting_rec/.venv/bin/activate
python meeting_rec/scripts/20_transcribe.py

# Phase 3-4  Claude Code に topics.json と highlights.json を作ってもらう
# → 「transcript.json と geminiまとめ.txt から topics.json を作って」と依頼
# → 「topics.json から上位 3〜4 トピックで 60 秒の highlights.json を作って」と依頼

# Phase 5  クリップ切り出し
bash meeting_rec/scripts/50_cut_clips.sh

# Phase 6  Remotion レンダ
cd meeting_rec/remotion
npx remotion render Highlight60 ../out/highlight_60s.mp4 \
  --props=../transcribe/highlights.json --concurrency=4

open ../out/highlight_60s.mp4

過去日の素材を処理したいときは、Phase 0 で DATE=2025_11_20 のように環境変数で日付フォルダを指定すれば OK です。

カスタマイズしたいとき

テロップ文だけ直したい

meeting_rec/transcribe/highlights.jsoncaption / subCaption を編集して、Phase 6 のレンダだけ叩き直せば反映されます。クリップ自体は再生成されないので、文字直しだけならめっちゃ早いです。

クリップ区間を変えたい

同じく highlights.jsonsourceStartSec / sourceEndSec / durationSec を編集(合計 60 秒を維持)したあと、

bash meeting_rec/scripts/50_cut_clips.sh

を再実行すると、変更があったクリップだけ再切り出ししてくれます(キャッシュ判定が入っている)。

Remotion Studio でリアルタイムプレビュー

レイアウトを微調整したいときは Studio の起動が便利です。

cd meeting_rec/remotion
npx remotion studio

ブラウザで http://localhost:3000 を開くと、動画を見ながら触れます。これは触っているだけで楽しい!

ハマったところ

文字起こし後半が同じフレーズで埋まる現象

Whisper の condition_on_previous_text=True による反復ループです。スクリプトの既定は False にしてあるので普段は出ないんですが、過去の出力が壊れているときは再生成すれば戻ります。

CONDITION_PREV=0 FORCE=1 python meeting_rec/scripts/20_transcribe.py

スポーツで言うと、前のプレーを引きずってリズムが崩れてる選手みたいなもんですね…!

固有名詞の誤認識が多い

meeting_rec/scripts/20_transcribe.pyINITIAL_PROMPT に、会議でよく出る単語を足します。

INITIAL_PROMPT = (
    "(会議名、サービス名、製品名、社内用語などをカンマ区切りで列挙)"
)

業界・社内用語や独自プロダクト名も忘れずに入れておくと、文字起こしの精度がぐっと上がります!

Remotion loadFont でエラー

loadFont("normal", {subsets: ["japanese"]}) だと、パッケージ版の登録状況によってコケることがあります。引数なしで loadFont() を呼ぶ形に書き直したら直りました。

mlx-whisper が ImportError(前述の Python バージョン問題)

これは Python 3.14 系で起きるやつです。3.11 で venv を作り直しましょう。

rm -rf meeting_rec/.venv
uv venv --python 3.11 meeting_rec/.venv
source meeting_rec/.venv/bin/activate
uv pip install mlx-whisper

ここで小一時間溶かしました…。Python のバージョンは「とりあえず 3.11」にしておくのが、現時点では正解っぽいです。

やってよかった設計判断

なぜこの構成にしたのかをメモしておきます。

  • 素材は rec/<日付>/ に積む … 複数会議をディレクトリで分離
  • 日本語ファイル名は symlink で ASCII 化 … シェル事故を防ぐ予防線
  • 音声は 16kHz mono … Whisper 内部と一致してリサンプル不要
  • トピックマッチは Claude に直接やらせる … embedding モデル(数百 MB 〜 数 GB クラス)の追加 DL を回避
  • highlights.json を props 化 … テロップ修正は Phase 6 だけで完結

トピック抽出を embedding でやるか LLM でやるかは少し悩んだんですが、議事録のトピック数が片手で数えられる規模なら、LLM の方がトータルでシンプルでした。

「embedding を仕込む前に、まず LLM に聞いてみる」、最近はこの順番でやることが増えてます。

やってみて思ったこと

もともと「録画見ない問題」を自分の手で解決したくて始めた小ネタだったんですが、やってみたら mlx-whisper の早さと Remotion の表現力の両方を一気に味わえて、めちゃくちゃ楽しかったです!

次は VTT 字幕付きで動画を書き出したり、30 秒版や 3 分版も同じ素材から出せるようにしてみたいなと思っています。

本記事のコードは個人のローカルで動かしているもので公開はしていませんが、本文中の手順とスクリプト断片を組み合わせれば、同じパイプラインを手元で再現できるはずです。同じ「録画見ない問題」に悩んでいる方の参考になれば嬉しいです!

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?