ffmpeg-mcp
Enables LLMs to safely execute ffmpeg and ffprobe operations by passing arguments as arrays, avoiding shell injection, with support for probe, convert, trim, concat, thumbnail, watermark, speed, loudnorm, and batch processing.
README
<div align="center">
ffmpeg-mcp
ffmpeg / ffprobe を安全な引数渡しで LLM から叩く MCP サーバー
シェル文字列を組み立てずに ffmpeg を駆動する。probe は構造化 JSON で返す。
</div>
概要
LLM に ffmpeg -i ... -c:v libx264 ... を文字列として書かせると、エスケープ事故・シェルインジェクション・クォート漏れが起きる。このサーバーは全ての引数を配列で渡し、spawn でシェルを経由せずに起動する。ffprobe は常に -print_format json で叩いて、LLM に渡す前に構造化する。
| 要素 | 実装 |
|---|---|
| トランスポート | stdio MCP |
| 子プロセス | spawn(ffmpeg|ffprobe, args[]) — シェル不使用 |
| 出力制御 | stderr 末尾 16 KB だけ残す (ffmpeg は verbose) |
| タイムアウト | 既定 600 s、FFMPEG_TIMEOUT または timeout 引数で上書き |
特徴
| アクション | 用途 |
|---|---|
probe |
ffprobe を JSON で叩き、format / streams / chapters を間引いて返す(未知ファイルへの第一手) |
convert |
再エンコード。video_codec / audio_codec / crf / preset / video_bitrate / audio_bitrate / fps / resolution=[w,h] / オプションの start・duration / extra_args |
trim |
既定で -c copy による無劣化カット(再エンコードなし、ほぼ瞬時)。copy: false で再エンコード可。精度注意: copy モードは I-frame 単位で seek する為、start が最大数秒ズレる事がある(ffmpeg の仕様)。フレーム精度が必要なら copy: false |
concat |
concat デマクサで input_paths: string[] を無劣化結合(全入力が同コーデック/同パラメータ前提) |
extract_audio |
-vn + オプションで audio_codec / audio_bitrate。拡張子でコーデック自動選択 |
thumbnail |
指定時刻(既定 00:00:01)の 1 フレームを画像として書き出し、size=[w,h] で縮小可 |
run |
生 args の escape hatch。use_ffprobe: true で ffprobe を叩く |
version |
ffmpeg -version / ffprobe -version の先頭行 |
watermark |
ロゴ画像を動画にオーバーレイ。position (top-left / top-right / bottom-left / bottom-right / center), margin, watermark_scale (メイン動画幅に対する比, デフォルト 0.15), opacity |
loudnorm |
EBU R128 2-pass ラウドネス正規化。1 パス目で measured_I / TP / LRA / thresh / offset を取得、2 パス目で linear モードで再エンコード。target_i (-16), target_tp (-1.5), target_lra (11) がデフォルト |
speed |
再生速度変更。setpts=PTS/speed + atempo チェーン (0.5〜2.0 超える倍率も自動チェーン化)。video_only / audio_only で片方だけ |
batch |
jobs[] を sequential 実行。stop_on_error で中断制御、各ジョブの ok/exit_code/duration/stderr テイルを個別レポート |
処理フロー
sequenceDiagram
participant LLM
participant MCP as ffmpeg-mcp (stdio)
participant FF as ffmpeg / ffprobe
LLM->>MCP: {action: "probe", input: "in.mp4"}
MCP->>FF: spawn(ffprobe, [-v error, -print_format json, -show_format, -show_streams, ...])
FF-->>MCP: stdout (JSON)
MCP->>MCP: JSON.parse + 間引き
MCP-->>LLM: {format, streams[], chapters[]}
LLM->>MCP: {action: "convert", input, output, crf: 23, preset: "medium"}
MCP->>FF: spawn(ffmpeg, [-n, -i, in.mp4, -crf, 23, -preset, medium, out.mp4])
FF-->>MCP: exit_code / stdout / stderr(tail) / duration_ms
MCP-->>LLM: JSON
インストール
git clone https://github.com/cUDGk/ffmpeg-mcp.git
cd ffmpeg-mcp
npm install
npm run build
ffmpeg と ffprobe が PATH にある事が前提。別パスにある場合は FFMPEG_PATH / FFPROBE_PATH で明示する。
使い方
Claude Code に登録
claude mcp add ffmpeg -- node <install-dir>/dist/index.js
環境変数
| 変数 | デフォルト | 用途 |
|---|---|---|
FFMPEG_PATH |
ffmpeg |
ffmpeg 実行ファイル |
FFPROBE_PATH |
ffprobe |
ffprobe 実行ファイル |
FFMPEG_TIMEOUT |
600000 |
単一呼び出しのタイムアウト (ms) |
FFMPEG_MCP_ALLOW_ROOTS |
(未設定) | 出力先のホワイトリスト(OS の path.delimiter 区切り — Windows は ;、POSIX は :)。設定すると、ここで挙げたディレクトリ配下にしか出力できない |
FFMPEG_MCP_MAX_JOBS |
32 |
batch.jobs[] の上限 |
FFMPEG_MCP_ALLOW_ROOTS の例:
# Windows (PowerShell): 区切りは ";"
$env:FFMPEG_MCP_ALLOW_ROOTS = "C:\Users\me\videos;D:\renders"
# Linux / macOS: 区切りは ":"
export FFMPEG_MCP_ALLOW_ROOTS="/home/me/videos:/srv/renders"
セキュリティ
- 既定で出力ファイルは上書きしない (
ffmpeg -n)。意図的に上書きしたい場合はoverwrite: trueを渡す(ffmpeg -y)。 run/convert.extra_argsは無検査ではない。ffmpeg のプロトコルプレフィックス (concat:,subfile:,http:,file:,tee:,data:等) や、ファイルを読む系のフィルタ (movie=...,subtitles=...,drawtext=...textfile=...,sendcmd=...) や、-protocol_whitelist上書き /-f teeは拒否する。それ以外の動作については LLM 任せにせず、ホスト側でもFFMPEG_MCP_ALLOW_ROOTSを設定する事を推奨する。- 全ての
-i呼び出しに-protocol_whitelist file,crypto,dataを強制注入する(HTTP/RTMP/RTSP 経由の任意 URL fetch を遮断する)。
呼び出し例
未知ファイルの確認 → 中央 10 秒を切り出し → H.264 に再圧縮:
{"action": "probe", "input": "C:/tmp/raw.mkv"}
{"action": "trim", "input": "C:/tmp/raw.mkv", "output": "C:/tmp/clip.mkv",
"start": "00:01:00", "duration": 10}
{"action": "convert", "input": "C:/tmp/clip.mkv", "output": "C:/tmp/out.mp4",
"video_codec": "libx264", "crf": 23, "preset": "medium",
"audio_codec": "aac", "audio_bitrate": "128k"}
サムネイル 4 枚(0 / 10 / 20 / 30 秒):
{"action": "thumbnail", "input": "in.mp4", "output": "t0.jpg", "time": 0, "size": [640, 360]}
{"action": "thumbnail", "input": "in.mp4", "output": "t1.jpg", "time": 10, "size": [640, 360]}
{"action": "thumbnail", "input": "in.mp4", "output": "t2.jpg", "time": 20, "size": [640, 360]}
{"action": "thumbnail", "input": "in.mp4", "output": "t3.jpg", "time": 30, "size": [640, 360]}
ラウドネス正規化 (podcast / YouTube 公開用):
{"action": "loudnorm", "input": "raw.wav", "output": "normalized.m4a",
"target_i": -14, "target_tp": -1.0, "target_lra": 7,
"audio_codec": "aac", "audio_bitrate": "192k"}
ロゴ透かし (右上 10% サイズ、60% 透過):
{"action": "watermark", "input": "in.mp4", "output": "out.mp4",
"watermark_path": "logo.png",
"position": "top-right", "margin": 20,
"watermark_scale": 0.1, "opacity": 0.6}
2x 早回し:
{"action": "speed", "input": "in.mp4", "output": "2x.mp4", "speed_factor": 2.0}
複数動画を一括処理 (最初の失敗で中断):
{"action": "batch", "stop_on_error": true, "jobs": [
{"action": "trim", "input": "raw.mp4", "output": "clip.mp4", "start": 10, "duration": 30},
{"action": "convert", "input": "clip.mp4", "output": "final.mp4", "video_codec": "libx264", "crf": 20},
{"action": "thumbnail", "input": "final.mp4", "output": "poster.jpg", "time": 5}
]}
run で完全制御(例: フィルタ複雑グラフ):
{"action": "run", "args": [
"-y", "-i", "in.mp4",
"-filter_complex", "[0:v]scale=1280:720,fps=30[v]",
"-map", "[v]", "-map", "0:a",
"-c:v", "libx264", "-crf", "20",
"out.mp4"
]}
設計メモ
- 意図ベースのアクション(
convert_to_mp4等)を増やさない。増やしても結局extra_argsで逃げるだけで、LLM に覚えさせる面が増える。アクションは処理のカテゴリ単位(convert / trim / concat / thumbnail)に留める。 - stderr は末尾 16 KB だけ残す。ffmpeg は 1 回の実行で数 MB のログを吐く事があり、LLM のコンテキストを焼き尽くす。
- 相対パスは CWD から resolve。LLM が相対パスを渡しても意図通りの場所に書き出される。
- タイムアウト既定 10 分。長時間エンコードは
timeoutで上書き。
v0.3.1 修正
バグ修正:
batchのwatermarkジョブでwatermark_path→watermark/watermark_scale→scaleのフィールドマッピングが欠落していた問題を修正(ウォーターマーク画像と scale が常に無視されていた)。batchのspeedジョブでspeed_factor→speedのフィールドマッピングが欠落していた問題を修正(speedが undefined になりNumber.isFiniteチェックで必ずエラーになっていた)。- README の mermaid ダイアグラムで
-yと表示されていたのを-n(no-clobber デフォルト) に修正。
v0.3.0 修正
セキュリティ・バグ・UX を一括で改修したリリース。
セキュリティ:
run/convert.extra_argsの引数をassertSafeFfmpegArgs()で検査。ffmpeg プロトコルプレフィックス・ファイル読み取り系フィルタ・-protocol_whitelist上書き・-f teeを拒否。- 全ての
-i呼び出しに-protocol_whitelist file,crypto,dataを強制注入。 safeInputPath()を全アクションの入力に適用(Windows ドライブレターC:\...は許可、http:/concat:等は拒否)。- 既定値を
-y(force overwrite) →-n(no clobber) に変更。明示的にoverwrite: trueを渡した時だけ上書きする。 FFMPEG_MCP_ALLOW_ROOTSで出力先をディレクトリ単位でホワイトリスト可能。FFMPEG_MCP_MAX_JOBSでbatch.jobs[]の長さに上限。concatのリストファイルに改行を含むエントリを拒否(行ベースパーサを破壊する為)。
バグ修正:
- stdout / stderr を
Buffer.concat()で組み立てる様に変更(チャンク境界で UTF-8 が壊れる問題を解消)。 - stdout にも 8 MiB の上限を導入。
loudnormPass1の stderr を切り詰めない。loudnorm の JSON ブロックが落ちる事があった。loudnormPass1がtimeoutを尊重していなかった問題を修正。concat()のmkdtempSyncを try の中に移動。例外時の temp dir リーク防止。proc.stdout/proc.stderrにerrorリスナを追加(Windows での EPIPE 未処理を防止)。killProcを非同期化(execFileSyncでイベントループを止めない)。speedでsetpts=Infinity*PTSを防ぐバリデーション。versionの戻り値が空 / 非 0 終了時にisError: trueを立てる様に。tsconfig.jsonにnoUncheckedIndexedAccess: true。
UX:
- ツール説明に
watermark/loudnorm/speed/batchを追記。 thumbnailのデフォルトtimeをドキュメント通りの00:00:01に。batch.jobs[].actionを厳密な enum に。batchで 1 件でも失敗したら全体のisErrorを立てる。extra_argsが convert 専用である事を明記。
v0.2.1 修正
一部の MCP クライアント (Claude Code の LLM ツール使用パス等) が object / array 引数を JSON 文字列化してからサーバーに渡す挙動があり、extra_args / args / input_paths / resolution / size / jobs が文字列で届くと zod バリデーションで落ちるか、args.push(...p.extra_args) で文字列を spread して 1 文字ずつ ffmpeg の引数に混入する等の事故が起きていた。
修正内容:
extra_args/args/input_paths/resolution/size/jobsの zod schema をz.union([<本来の型>, z.string()])に緩和coerceArray()/coerceObject()ヘルパを追加し、文字列で届いた場合はJSON.parseで配列 / オブジェクトに戻してから使用batchの各 job 内部のネスト配列 (extra_args/resolution/size/args/input_paths) も coerce してから dispatch
Attribution
- FFmpeg © FFmpeg developers(LGPL/GPL)— 本 MCP はラッパーであり FFmpeg 本体のライセンスに従う
- Model Context Protocol — 仕様・SDK
ライセンス
MIT License © 2026 cUDGk — 詳細は LICENSE を参照。
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.