关于 Video Frames
Video Frames 是面向支持图像输入的模型提供视频帧和可测量视频属性的本地 MCP 服务及命令行工具。它结合带时间码的帧采样、元数据读取,以及可选的场景、静音和响度扫描。
主要功能
- 01按时间码采样并返回图像帧
- 02检查视频元数据
- 03可选扫描场景、静音和响度
- 04复用帧与扫描缓存
- 05检查运行环境和 MCP 连接
适用场景
- 01让支持图像输入的模型查看视频片段
- 02处理前检查视频元数据
- 03扫描片段中的场景切换、静音和响度
- 04复用重叠时间范围内的帧
MCP 相关
Video Frames 通过 stdio 向 MCP 客户端提供 `view_frames` 和 `video_info`。它需要本地安装及 ffmpeg;连接的模型需支持图像输入才能使用返回的帧。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
2收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| end | any | 否 | |
| start | number | 否 | |
| video | string | 是 | |
| format | any | 否 | |
| quality | integer | 否 | |
| interval | number | 否 | |
| max_edge | integer | 否 | |
| max_frames | any | 否 |
详细介绍
mcp-video-frames — 视频 MCP 服务
一个 MCP 服务,让只能处理图像的模型也能查看视频:提供带时间码的帧,以及可测量的视频属性。
可用工具
该服务提供以下工具:
view_frames- 对指定时间范围采样并返回图像帧,每帧前都会附上时间码video_info- 容器元数据,可选扫描整个文件的场景、静音和响度
你正在使用的模型必须接受图像输入。否则,返回的帧会被丢弃或降级为文本。
这是一个本地服务:它并未托管在任何地方,必须将客户端指向它。请参阅下方的可自托管部分。
从 PyPI 安装
pip install mcp-video-frames # or run it without installing: uvx mcp-video-frames
这会安装一个控制台脚本,该脚本就是服务。将客户端指向它:
{
"mcpServers": {
"video-frames": { "command": "mcp-video-frames" }
}
}
不带子命令且通过管道传入标准输入时,它会使用 MCP 协议;在终端中则会打印帮助信息,而不会一直等待。mcp-video-frames doctor 会检查它将要运行的环境。
此安装方式要求 ffmpeg 和 ffprobe 位于 PATH 中。如果你更希望将它们安装到专用虚拟环境中,并同时生成现成的客户端配置,请改用下方的可自托管方式。
可自托管
不会向系统 Python 安装任何内容:依赖项会安装到项目自己的 .venv/ 中,客户端配置则会直接指向该环境中的解释器。
- 克隆仓库
git clone https://github.com/Azzy-H/mcp-video-frames.git
cd mcp-video-frames
- 创建虚拟环境并生成客户端配置
python setup_mcp.py
setup_mcp.py 只会执行三项操作:
- 在此目录中创建
.venv/(使用任意 Python 3.10+ 解释器运行); - 将
requirements.txt中的两个运行时依赖安装到该.venv/中; - 写入
mcp-config.json,并预先填入路径。
选项:
python setup_mcp.py --max-images 12 # match your client's image limit
python setup_mcp.py --print # print the config only; write nothing
python setup_mcp.py --ffmpeg <path> # ffmpeg is not on PATH
如果缺少 ffmpeg,脚本会提供选项:在 .venv/ 中下载预编译版本(Windows)、指定你已安装的版本,或跳过。它绝不会将任何内容安装到系统范围内。
- 配置前检查环境
.venv/Scripts/python run_server.py doctor # Windows
.venv/bin/python run_server.py doctor # macOS / Linux
此检查会报告 ffmpeg/ffprobe 的路径和版本、所需滤镜是否存在,以及缓存目录是否可写;如有缺失,会直接指出,而不让你猜测。它会自动查找虚拟环境中的 ffmpeg,因此无需提前导出任何变量。
test_server.py 会进一步通过标准输入输出与服务进行真正的 MCP 通信,因此在配置任何客户端之前,就可以验证整个流程:
.venv/Scripts/python test_server.py connect <video file path> # Windows
.venv/bin/python test_server.py connect <video file path> # macOS / Linux
它会检查握手、工具列表、2n + 1 内容块的顺序、单帧请求是否以 PNG 格式返回、超出限制的请求是否会被拒绝,以及标准输出是否保持干净,以供 JSON-RPC 流使用。
- 添加此 MCP 服务
将生成的 mcp-config.json 合并到客户端配置中。如果已有 mcpServers 部分,只需向其中添加 video-frames 条目即可。run_server.py 会自行将 src/ 加入 sys.path,因此无需 PYTHONPATH,也无需在任何位置执行 pip install。
替换 /path/to/mcp-video-frames,将其改为此仓库在你系统上的实际路径。在 Windows 上,解释器路径为 .venv\Scripts\python.exe。
卸载:删除 .venv/ 并移除该配置条目。除此之外没有写入任何内容。
要求
- Python 3.10 或更高版本
ffmpeg和ffprobe。setup_mcp.py会将它们安装(或下载)到项目自己的.venv/中,服务会先在自身解释器旁查找,然后再检查PATH—— 因此,在虚拟环境中安装时无需导出FFMPEG_PATH。ffmpeg为必需项;如果没有ffprobe,元数据会退回到解析 ffmpeg 自身的标头输出(字段较少),并且doctor会明确说明这一点- 支持图像输入的客户端模型
工具
view_frames
对一段时间范围进行采样,并返回按时间码与图像交错排列的序列。将 start 和 end 设为相同值即可查看单个时刻。
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
video | string | — | 绝对路径(必需) |
start | number | 0 | 起始时间,单位为秒 |
end | number | start + interval | 结束时间,单位为秒 |
interval | number | 1.0 | 采样间隔,0.05–600 s |
max_frames | integer | 12 | 本次调用的帧数;可提高至图像数量上限 |
max_edge | integer | 768 | 长边尺寸,单位为像素,64–4096 |
format | jpeg | png | 范围采样时为 jpeg,单帧时为 png | |
quality | integer | 85 | jpeg 质量,1–100 |
结果包含 2n + 1 个内容块:
text: {"n":0,"t":0.0}
image: <frame 0>
text: {"n":1,"t":1.0}
image: <frame 1>
...
text: {"video":"...","frames":12,"range":[0.0,11.0],"interval":1.0,
"format":"jpeg","max_edge":768,"clamped":false,"cached":9,
"limits":{"max_images_per_call":20,"max_image_bytes":10485760,
"max_total_bytes":41943040}}
块的顺序至关重要:没有对应时间码的图像无法按时间进行推理。clamped 表示范围是否已裁剪至视频长度,cached 表示来自磁盘的帧数,limits 则重复列出当前生效的预算,这样就无需通过被拒绝来获知这些数值。
范围采样默认使用 jpeg,因为在长边长度相同时,它的体积约小一个数量级,因此可以在客户端字节预算内容纳更多帧。注重细节时,单帧请使用 png。
超出限制时调用会失败:不会截断内容,也绝不会扩大采样间隔。 静默降低采样密度会破坏调用方对时间精度的预期,因此整个调用会直接失败。如果任意单帧未通过验证,则不会返回任何帧。
video_info
返回视频元数据。detail="basic" 仅读取容器标头并立即返回;detail="full" 会额外对整个文件进行详尽扫描,以检测场景切换、静音和 EBU R128 响度。
{
"path": "", "sha256": "", "size_bytes": 0,
"duration": 0.0, "fps": 0.0, "width": 0, "height": 0,
"video_codec": "", "pix_fmt": "",
"color_range": "", "color_space": "", "is_hdr": false,
"audio_tracks": [], "subtitle_tracks": [], "chapters": [],
"detail": "full",
"scene_cuts": [1.23, 5.67],
"silences": [{"start": 12.0, "end": 14.5, "duration": 2.5}],
"loudness": {"integrated_lufs": -23.0, "true_peak_dbfs": -1.2, "lra": 5.0},
"scan": {"ffmpeg_version": "", "computed_at": "", "cached": false}
}
使用 detail="basic" 时,scene_cuts / silences / loudness / scan 字段会缺省,而非为空——“没有值”和“未扫描”含义不同。首次调用 full 会扫描整个文件;之后的调用会复用缓存。force=true 会重新计算。
配置
环境变量优先于默认值。
| 变量 | 默认值 | 用途 |
|---|---|---|
MCP_VIDEO_MAX_IMAGES | 20 | 每次调用的最大图像数(最重要的限制) |
MCP_VIDEO_CACHE_DIR | setup_mcp.py 生成的 .cache/;否则为 <system temp>/mcp-video-frames-cache | 缓存根目录 |
FFMPEG_PATH / FFPROBE_PATH | 自动检测 | 在检查 PATH 之前查找 |
MCP_VIDEO_MAX_IMAGE_BYTES | 10485760 | 单帧字节数上限 |
MCP_VIDEO_MAX_TOTAL_BYTES | 41943040 | 每个结果的总字节数上限 |
MCP_VIDEO_MAX_IMAGE_DIM | 8192 | 单帧边长上限 |
MCP_VIDEO_CACHE_MAX_BYTES | 5368709120 | 缓存大小上限 |
MCP_VIDEO_FRAME_MAX_AGE_DAYS | 14 | 帧的最长存留天数 |
MCP_VIDEO_SCENE_THRESHOLD | 0.3 | 场景变化灵敏度 |
MCP_VIDEO_MAX_IMAGES 限制单次调用可返回的帧数。请将其设为与客户端相符的值:不同客户端的限制各不相同,设得过低只是过于保守,而设得过高则会导致整个批次无法使用。max_frames 默认值为 12,且最多只能提高到此上限。
有效限制也会在工具说明中列出,并在每个 view_frames 结果中重复显示,因此调用方无需先被拒绝,就能查看这些限制。
命令行
同一个软件包还提供了一个命令行工具,用于故障排查和批量处理:
mcp-video-frames doctor # environment self-check
mcp-video-frames info video.mp4 # basic metadata
mcp-video-frames scan video.mp4 # pre-build the full scan
mcp-video-frames scan --dir ./videos # process a whole directory
mcp-video-frames frames video.mp4 --start 0 --end 5 # frames, as content-block JSON
mcp-video-frames cache --stats # cache usage
mcp-video-frames cache --prune # evict cache entries
如果不安装项目(见上文 可自托管),请使用启动器运行相同的子命令:
.venv/Scripts/python run_server.py doctor # Windows
.venv/bin/python run_server.py info video.mp4 # macOS / Linux
不带参数运行时会打印帮助信息;作为 MCP 服务运行时不接受任何参数。当标准输入是管道(如 MCP 客户端提供的情况)时,直接调用即可启动服务,因此在标准输入/输出场景下无需进行任何配置。
doctor 会打印 JSON 报告,然后输出一行简短的人工可读结论(“Self-check passed”/“Self-check failed”),因此它是唯一一个标准输出并非纯 JSON 的子命令。命令行工具和 MCP 工具调用相同的核心函数,因此终端中有效的行为不会与模型使用的行为产生偏差。
缓存
位置:取决于服务的启动方式。
| 部署方式 | 缓存根目录 |
|---|---|
setup_mcp.py(推荐方式) | 此项目内部的 .cache/ |
未设置 MCP_VIDEO_CACHE_DIR 的普通软件包安装 | <system temp>/mcp-video-frames-cache |
设置脚本会有意将项目本地的 .cache/ 配置为缓存目录,并同时设置 cwd。相对路径会根据客户端的工作目录解析,因此不设置 cwd 时,缓存会被放到客户端启动时所在的位置——这比临时目录默认位置更难预测,而不是更容易预测。该目录已列入 .gitignore。
MCP_VIDEO_CACHE_DIR 会覆盖上述任一默认值,解析后的路径会在启动时打印到标准错误。
缓存中的所有内容都可以重新生成——删除该目录始终安全,只会导致再次探测。
条目以内容哈希为键(大小 + 修改时间 + 前后各 1 MB),帧则按绝对时间戳分别存储,因此重叠的视图可以复用已有工作:先查看 0–20 秒,再查看 10–30 秒,10–20 秒的内容已经在磁盘上。
如果缓存位于系统临时目录中,请勿依赖操作系统清理它——各平台的行为差异很大:
| 平台 | 临时目录清理方式 |
|---|---|
| Windows | 基本不会清理。存储感知仅在磁盘空间紧张时运行,并会跳过正在使用的文件 |
| Linux | systemd-tmpfiles 会清理超过指定期限的 /tmp 文件(约 10 天);/tmp 通常使用 tmpfs,并会在重启时清空 |
| macOS | 系统会在不确定的时间清理 $TMPDIR |
因此,服务会自行清理:超出 MCP_VIDEO_CACHE_MAX_BYTES(默认 5 GB)时,按 LRU 策略逐出整个视频条目;同时还会将帧的存留时间限制为 14 天(MCP_VIDEO_FRAME_MAX_AGE_DAYS)。
分层策略依据的是重新计算的成本:帧重新生成的成本较低,因此优先逐出;而整个文件的扫描结果(video_info(detail="full"))重新生成的成本较高,因此会优先保留。
逐出操作会在工具调用返回后异步运行——不会阻塞响应,且启动时不会执行完整扫描。
多个客户端共享同一缓存。读写操作受文件锁保护,写入会先写入临时文件,再通过 os.replace 替换;如果某帧在列出后、读取前被逐出,则会重新生成,而不会报错。
许可证
MIT — 详见 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。