媒体处理服务器

一个封装FFmpeg和FFprobe的MCP服务器,为AI助手提供结构化的媒体检查和转换工具。

  • by NoahWorkman
  • TypeScript
  • 本地部署
  • 更新于
在 GitHub 查看 NoahWorkman/mcp-ffmpeg

使用说明

mcp服务器ffmpeg

一个封装FFmpeg和FFprobe的MCP服务器,为AI助手提供对媒体检查和转换工具的结构化访问。

此服务器不解析ffmpeg命令的原始终端输出,而是返回带元数据、验证结果和可操作诊断的类型化JSON。

它做什么

检查工具 (只读,快速):

  • probe --返回任何媒体文件的结构化元数据:格式信息(持续时间、大小、比特率)、流详细信息(编解码器、分辨率、帧率、采样率、频道)和所有嵌入式标签(标题、艺术家、创建日期、编码器)。

  • find_keyframes --列出视频文件中的关键帧(I帧)时间戳,可选择过滤到时间范围。对于设置修剪点而不导致帧冻结至关重要。

  • check_render_ready --根据生产要求验证媒体文件:H.264视频编解码器、48kHz音频采样率、存在的音频流以及给定修剪点的关键帧对齐。返回通过/失败,并给出具体的修复建议。

转换工具 (创建新文件,从不覆盖输入):

  • strip_audio --从视频中删除音轨。视频流被复制而无需重新编码。用于b-roll剪辑,其中单独的旁白在镜头上播放。

  • reencode_h264 --将视频重新编码为H.264,具有可配置的CRF质量。修复了导致渲染失败的VP9/WebM文件。包括用于网络播放的快速启动标志。音频按原样复制。

  • resample_audio --将音频重新采样到目标采样率(默认48kHz)。视频流被复制而无需重新编码。修复了44.1kHz源出现的无声音频漂移。

  • crop_portrait --使用指定的水平偏移将风景(16:9)视频转换为肖像(9:16)格式。根据源分辨率计算裁剪尺寸。音频被剥离(b-roll模式)。

  • extract_audio --从视频文件中提取WAV(PCM 16位)或MP3格式的音轨。始终重新采样到48kHz。

主要特点

转换后验证门。 每个转换工具在返回之前都会自动验证自己的输出。响应包括验证报告(ready: true/false 具有特定问题)以及输入和输出元数据。错误的采样率或编解码器不匹配等问题永远不会消失。

元数据保存。 所有转换都将源元数据(标题、艺术家、创建日期等)通过以下方式复制到输出文件 -map_metadata 0 默认情况下。通过 stripMetadata: true 输出一个干净的文件。

结构性错误。 错误类型为 SpawnError (未找到二进制文件), TimeoutError (操作超出限制),或 ProcessError (ffmpeg失败,从stderr中提取了解析的可操作错误行)。

并发控制。 信号量以CPU数量限制并发ffmpeg进程,防止并行调用多个工具时资源不足。

安全。

  • 所有命令都使用 child_process.spawn 带参数数组(无shell注入)
  • 检查输入路径中的shell元字符,并根据文件扩展名分配列表进行验证
  • FFmpeg协议白名单设置为 file,pipe 仅限(通过网络URL阻止SSRF)
  • 最小文件大小检查快速拒绝空/损坏的输入

安装

需要 FFmpeg 安装在您的PATH上。

克劳德代码(本地开发)

git clone https://github.com/NoahWorkman/mcp-ffmpeg.git
cd mcp-ffmpeg
npm install && npm run build
claude mcp add --transport stdio --scope user ffmpeg -- node /path/to/mcp-ffmpeg/dist/index.js

Claude Code(npm,发布后)

claude mcp add --transport stdio --scope user ffmpeg -- npx -y @noahworkman/mcp-server-ffmpeg

手动配置

添加 ~/.claude.json 在...之下 mcpServers:

{
  "ffmpeg": {
    "type": "stdio",
    "command": "node",
    "args": ["/path/to/mcp-ffmpeg/dist/index.js"]
  }
}

工具参考

探测

Input:  { path: string }
Output: { format: FormatInfo, streams: StreamInfo[], videoStream?: StreamInfo, audioStream?: StreamInfo }

返回编解码器、分辨率、帧率、持续时间、比特率、采样率、通道以及格式和流级别的所有元数据标签。

查找密钥帧

Input:  { path: string, startTime?: number, endTime?: number }
Output: { count: number, keyframes: Array<{ time: number, position: number }> }

check_render_ready

Input:  { path: string, trimStartSeconds?: number }
Output: { ready: boolean, issues: string[], metadata: { codec, resolution, frameRate, audioSampleRate, ... } }

检查:视频为H.264,音频为48kHz,音频流存在。如果 trimStartSeconds 设置后,当最近的关键帧距离超过0.5秒时发出警告。

strip\audio/reencode_h264/重采样音频/滚动肖像/提取音频

所有转换返回:

{
  success: boolean,
  validation: { ready: boolean, issues: string[] },
  output: { codec, resolution, audioSampleRate, duration, size, tags },
  input:  { codec, resolution, audioSampleRate, duration, size, tags }
}
工具 关键参数 它的作用
strip_audio inputPath, outputPath 删除音频,复制视频
reencode_h264 inputPath, outputPath, crf? (0-51,默认23) 重新编码为H.264
resample_audio inputPath, outputPath, sampleRate? (默认值48000) 重新采样音频
crop_portrait inputPath, outputPath, xOffset 农作物16:9至9:16
extract_audio inputPath, outputPath, format? (wav/mp3) 提取音轨

所有转换都接受可选 stripMetadata: boolean (默认为false)。

建筑

src/
  index.ts       -- Server setup, tool registration, MCP protocol
  execute.ts     -- Single execute() function, concurrency semaphore, kill escalation
  ffprobe.ts     -- Probe, keyframe search, render-ready validation
  ffmpeg.ts      -- Transform operations (args builders + validation gate)
  constants.ts   -- Encoding defaults, timeouts, allowlists
  types.ts       -- FfmpegTask, FfmpegError union, MediaInfo types
  validate.ts    -- Path validation, file checks, metachar rejection

所有FFmpeg/FFPprobe操作都通过一个单一的路由 execute() 函数处理:

  • 并发限制(信号量上限为CPU计数)
  • 超时(探头30秒,转换5分钟)
  • 杀戮升级(SIGTERM,然后在5秒后SIGKILL)
  • 已设置保护(防止并发关闭/错误事件导致双重解析)
  • Stderr解析(从FFmpeg的详细输出中提取可操作的错误行)

许可证

麻省理工学院