FFmpeg 8.0で文字起こしができるようになるんだってさ

FFmpeg 8.0で文字起こしができるようになるんだってさ
Photo by Aaron Burden / Unsplash

この前Whisperでの文字起こしをするために試行錯誤する記事を書いたばかり。

AIを使って寝てる間に文字起こしをしてもらいたい!
文字起こしをAIにやらせることができたらいいなあと思い立ち、とにかくやってみた。 私のラップトップはLenovoの「ThinkBook 16p G2 ACH Laptop - Type 20YM」。詳細スペックはこんな感じ。 構成 ハードウェア構成 * CPU: AMD Ryzen 7 5800H (3.20 GHz、8コア16スレッド) * GPU: NVIDIA GeForce RTX 3060 Laptop GPU (6GB VRAM) * メモリ: 40GB DDR4-3200 ※標準16GBから増設済み * ストレージ: 512GB SSD PCIe ソフトウェア環境 * OS: Windows 11 Pro (64bit) * バージョン: 24H2 パフォーマンス的なお話 このスペックでは、

まさか、FFmpegで文字起こし機能が直接使えるようになるっぽい。

ソースコードを見ると、OpenAI謹製のWhisperではなく、C++で書き直されたwhisper.cppライブラリが使用されていますね。元祖Whsperに比べて高速に処理ができそう。

というか、面倒だった環境構築がいらなくなりそうだね。PyTorchは依存関係にうるさくて、バージョン管理が面倒だったのだけれど、whisper.cppさえ入れておけば、あとはFFmpegのほうで指定するだけでうまいこと動くことになりそう!ワクワク!

FFmpegのメーリングリストみててびっくり!

いろいろ記事で取り上げられていたこともあって、2025年7月、FFmpegの開発メーリングリストに投稿されたパッチを見てみました。

重い腰を上げて作ってみたWhisperの文字起こし環境がいらなくなるみたい。

Whisper.csppよる文字起こし機能をFFmpegのフィルター機能として統合するみたいで、使うまでのステップが劇的に簡素化されそう。

出典情報

主要ソース

  • FFmpeg開発メーリングリスト: [PATCH] Whisper audio filter(2025年7月9日投稿)
  • 投稿者: Vittorio Palmisano氏
[FFmpeg-devel] [PATCH] Whisper audio filter

参考記事

  • Vittorio Palmisano氏による解説記事(Medium)
Run Whisper audio transcriptions with one FFmpeg command
Introduction

技術的な実装をチラッと見てみる

採用されたライブラリについて

ソースコードを見ると、FFmpegに統合されるのはOpenAI謹製のPython版Whisperではなく、whisper.cppのほうであるのがわかるね。

#include "whisper.h"  // whisper.cppのヘッダファイル

struct whisper_context *ctx_wsp;
struct whisper_state *whisper_state;

whisper.cppはC++で書き直されたWhisperの実装で、元のPython版と比較して3〜10倍の高速化を実現しているっぽいです。同じ精度ならそりゃあ速いほうがいいよね。しかもGPUなしで高速に動作するんだってさ。

GitHub - ggml-org/whisper.cpp: Port of OpenAI’s Whisper model in C/C++
Port of OpenAI’s Whisper model in C/C++. Contribute to ggml-org/whisper.cpp development by creating an account on GitHub.

ビルド設定も見てみる

configureスクリプトに追加されたオプションを見ると、どんな感じで統合されていてどんな感じで使うのかなあと雰囲気だけ知れます。

--enable-whisper enable whisper filter [no]

この設定から、FFmpegのビルド時にWhisper機能を有効化できるようですね。ソースコードの依存関係設定では以下のように定義されています。

whisper_filter_deps="whisper"
enabled whisper && require_pkg_config whisper "whisper >= 1.7.5" whisper.h whisper_init_from_file_with_params

whisper.cppライブラリのバージョン1.7.5以上が必要で、pkg-configを通じて自動的に依存関係が解決される仕組みになっていますね。

フィルターの詳細機能解説

基本的なパラメータ構成

新しく追加されたaf_whisper.cファイルには、いろいろな設定オプションが定義されました。

パラメータ デフォルト値 説明
model STRING - whisper.cppモデルファイルのパス(必須)
language STRING "auto" 言語指定(自動検出も可能)
queue INT 3000 音声バッファサイズ(ミリ秒)
use_gpu BOOL true GPU使用の有効化
gpu_device INT 0 使用するGPUデバイス番号
destination STRING "" 出力先(ファイル、URL、標準出力)
format STRING "text" 出力フォーマット(text/srt/json)

VAD(Voice Activity Detection)の高度な統合

これは便利だろうなと思ったのが、Silero VADモデルとの統合ですよ。音声認識システム自体は音声があるのかどうかを識別できないので、BGMなんかを必死に文字お越ししようと頑張ってくれるのだよね。BGMならまだしも無音区間を一生懸命認識したって時間が無駄なので、無音区間はスキップしてくれるよって機能だと思う。効率的。

VADパラメータ デフォルト値 説明
vad_model STRING - VADモデルファイルのパス
vad_threshold FLOAT 0.5 音声検出の閾値(0.0-1.0)
vad_min_speech_duration INT 50 最小音声継続時間(ミリ秒)
vad_min_silence_duration INT 500 最小無音継続時間(ミリ秒)

実際、当該ソースコードの実装を見ると、VAD機能でWhisperの処理効率を向上させる仕組みなんだなあってわかります。

struct whisper_vad_segments *segments = whisper_vad_segments_from_samples(
    wctx->ctx_vad, wctx->vad_params, wctx->audio_buffer, wctx->audio_buffer_fill_size);

さっきも言った通り、この機能によって音声が含まれる区間のみを処理し、無音部分をスキップすることで効率的に処理が進むようになります。

処理フローの技術的詳細についてちょこっと

音声データの前処理要件

ソースコードから、Whisperフィルターが要求する音声形式についても見てみましょう。

FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP)

このフィルターは32ビット浮動小数点形式(FLT/FLTP)の音声データのみを受け付けます。また、Whisperの仕様により16kHzのサンプリングレートとモノラルチャンネルが必要です。

出力フォーマットについて

FFmpegなので当然実装されている出力フォーマットはいろいろ選べて、超実用的。

SRT形式の出力例

buf = av_asprintf("%d\n%02ld:%02ld:%02ld.%03ld --> %02ld:%02ld:%02ld.%03ld\n%s\n\n",
                  wctx->index,
                  start_t / 3600000, (start_t / 60000) % 60, (start_t / 1000) % 60, start_t % 1000,
                  end_t / 3600000, (end_t / 60000) % 60, (end_t / 1000) % 60, end_t % 1000,
                  text_cleaned);

JSON形式の出力例

buf = av_asprintf("{\"start\":%ld,\"end\":%ld,\"text\":\"%s\",\"turn\":%s}\n",
                  start_t, end_t, text_cleaned, turn ? "true" : "false");

従来の実装との比較分析

環境構築の複雑さの解消

従来のWhisper環境構築で必要だった手順と新しい統合版を比較してみましょう。

私がやってた従来のPython版Whisperセットアップ(複雑)
  1. Python環境の準備
    • Anacondaまたは仮想環境の構築
    • Python 3.8以上の確認
  2. GPU関連の複雑な設定
    • CUDAツールキットのインストール
    • nvidia-smiでの対応バージョン確認
    • cuDNNライブラリの手動設定
  3. PyTorchの慎重なインストール
    • CUDA版PyTorchの正確なバージョン選択
    • 依存関係の手動解決
  4. Whisperライブラリの導入
    • OpenAI Whisperパッケージのインストール
    • モデルファイルの個別ダウンロード
新しいFFmpeg統合版(簡単!たぶん)

即座に実行可能

ffmpeg -i input.wav -af "whisper=model=ggml-base.bin" output.srt

モデルファイルの準備

# whisper.cppからモデルをダウンロード
wget https://huggingface.co/ggml-org/whisper.cpp/resolve/main/ggml-base.bin

ビルド時の簡単な設定

./configure --enable-whisper
make && make install

パフォーマンスの大幅改善

whisper.cppの採用により実現される性能向上について、技術的な背景を解説します。

メモリ使用量の最適化

C++実装により、Pythonインタープリターのオーバーヘッドが完全に排除されます。また、whisper.cppは量子化技術を活用して、モデルサイズを大幅に削減しています。

並列処理の効率化

ソースコードに見られるGPU処理の実装もあったので、CPUだけでなくGPUのCUDAを使って高速に処理することも考えられていますね。

struct whisper_context_params params = whisper_context_default_params();
params.use_gpu = wctx->use_gpu;
params.gpu_device = wctx->gpu_device;

実践的な使用例とその解説

多分こんな感じで使えるようになるんじゃないかなあっていう。

基本的な動画からの文字起こし

ffmpeg -i presentation.mp4 -vn \
  -af "aformat=sample_rates=16000:channel_layouts=mono,whisper=model=./ggml-base.en.bin:language=en:destination=transcript.srt:format=srt" \
  -f null -

このコマンドの各部分を詳しく解説します。

  • -vn: 動画ストリームを無効化(音声のみ処理)
  • aformat=sample_rates=16000:channel_layouts=mono: Whisperが要求する音声形式に変換
  • whisper=model=./ggml-base.en.bin: whisper.cppモデルファイルを指定
  • language=en: 英語として処理
  • destination=transcript.srt: SRT形式で出力
  • -f null -: 音声出力は破棄(文字起こしのみが目的)

リアルタイム文字起こしの実現

ffmpeg -f alsa -i hw:0 \
  -af 'highpass=f=200,lowpass=f=3000,aformat=sample_rates=16000:channel_layouts=mono,whisper=model=./ggml-medium.bin:language=ja:queue=10000:destination=-:format=json:vad_model=./ggml-silero-v5.1.2.bin' \
  -f null -

こんな感じで処理ができるかなあと。

  1. 音声フィルタリング: ハイパス(200Hz)とローパス(3000Hz)フィルターで会話部分を強調
  2. 拡張バッファ: 10秒間のキューで長い発話にも対応
  3. VAD統合: Sileroモデルで音声区間を自動検出
  4. 標準出力: リアルタイムでJSON形式の結果を出力

まとめ

FFmpeg 8.0はwhisper.cppを採用して統合するようですね。複雑な環境構築から解放されそうなのがうれしい。それに高速で軽量な文字起こし処理が実現できるなら本当にいろいろな場面で有効活用できそうです。

現在の開発状況から、FFmpeg 8.0は2025年8月中のリリースが予定されています。

8月のリリースが待ち遠しいですねえ。


本記事は2025年7月のFFmpeg開発メーリングリストに投稿されたパッチコードを雰囲気で分析しているだけです。実際のリリース版では仕様が変更される可能性があります。

Read more

TailscaleのSubnet Routesを消す

SynologyのNASにTailscaleを導入し、便利に使っている。 TailscaleにはSubnet routersという機能がある。 これは、Tailscaleネットワークに接続されたデバイスが、そのデバイスが接続されているローカルネットワーク(サブネット)全体へのアクセスを他のTailscaleデバイスに提供できる機能だ。つまり、Subnet routerとして設定されたデバイスを経由することで、Tailscaleネットワーク上の他のデバイスから、そのローカルネットワーク内の機器にアクセスできるようになる。 Subnet routers · Tailscale DocsUse subnet routers to give devices outside your local network access to services within specific subnets. Extend your private network with Tailscale.Tailscale 便利そうだなと思って設定をしてみたものの、結局使うことがなかった。 公式ドキュメント

By Sakashita Yasunobu

Boids

群れに指揮者はいない 鳥の群れは、誰かが指示を出しているわけではない。魚の群れも同じ。それぞれが周囲を見て、少しだけ動く。その繰り返しが、全体として秩序ある動きを生む。 これを1986年にCraig Reynoldsがコードで再現した。名前は Boids(bird + oid)。個体に与えるルールは3つだけ。 1. Separation ── 近すぎたら離れる 2. Alignment ── 周囲と同じ方向を向く 3. Cohesion ── 群れの中心に寄る これだけで、群れは群れらしく動く。 なぜ作ったか 群れの動きは、見ていて飽きない。 * 単純なルールから複雑な動きが生まれる ── 創発(emergence)の典型例。設計していないのに、設計したかのように見える。 * 自分のブログに置きたかった ── 静的なページに、動くものがあると空気が変わる。 * Web Components で作りたかった ── どこにでも持っていける部品として。 設計の話 見えないときは止める 画面外でアニメーションを回し続けるのは無駄。Inte

By Sakashita Yasunobu

Days Elapsed

一年を「面」で見る 一年は365日。数字で見ると多いけど、並べてみると案外少ない。 12ヶ月を並べて、過去を塗りつぶして、今日を光らせる。それだけのカレンダーを作った。進捗バーが「一次元」なら、これは「二次元」の進捗表示。 Year Progress一年は50週ちょっとしかない 2026年を週で数えると、52週とちょっと。 カレンダーで見ると長そうなのに、週で数えると急に短くなる。そんな感覚を形にしたくて、このページの上の方に進捗バーを置いた。 やっていることは単純で、「今年が何%進んだか」をリアルタイムで表示しているだけ。 なぜ作ったか 理由は3つある。 1. 時間を「量」として見たかった ── イベントや予定ではなく、単純に「どれだけ経ったか」を数値で見たかった。 2. 目に見える形にしたかった ── 抽象的な「一年」を、動く数字に落とすとどう感じるか試したかった。 3. 自分の場所に置きたかった ── 誰かのツールを借りるのではなく、自分のブログに自分で作ったものを置きたかった。 実装の話 せっかく作るなら、

By Sakashita Yasunobu