Skip to main content
Glama

MCP 视频生成

一个自托管的 MCP 服务器,可以暴露本地媒体生成后端(如 ComfyUI 和 Blender),同时提供本地媒体分析、编辑、FFmpeg、HyperFrames、时间线、字幕、语音和音频工具。

该项目设计为仅限 Portainer 部署:公共仓库包含一个常规的多文件应用,而单个 video-mcp.yml Stack 作为不可变的 GitHub 版本的引导加载器。

能力

  • 发现 ComfyUI 节点(当 ComfyUI 可用时,通过 /object_info 实际注册)。

  • 扫描只读的 ComfyUI models/ 和 custom_nodes/ 目录(当挂载时)。

  • 检查兼容的自定义节点源/文档文件。

  • 提交任意的有效 ComfyUI API 工作流 JSON 并检查队列/历史/输出状态。

  • 可选择通过经过身份验证的桥接器控制主机安装的 Blender,用于 bpy 自动化、渲染、动画渲染和 GLB 导出。

  • 使用文本、一次性 base64 或分块二进制传输,将文件从 MCP 客户端/AI 导入持久缓存。

  • 通过经过身份验证的 HTTP 下载、内联 base64 或有限的分块 base64 读取,将缓存文件返回给客户端/AI。

  • 通过一个 file_id 契约上传输入、缓存输出,并检索生成的图像、视频、音频、3D、场景、字幕和其他文件。

  • 使用 HTML/CSS/媒体创建和渲染本地 HyperFrames 项目。

  • 使用 FFmpeg 进行探测、转码、拼接、叠加、混流音频、裁剪、反转、循环、速度渐变和提取帧。

  • 检测静音、黑屏/冻结片段、响度、隔行扫描、裁剪区域、关键帧以及客观的 SSIM/PSNR 差异。

  • 构建联系表/故事板,并执行轻量级的帧相似度、运动、重复帧和最佳帧分析。

  • 使用 PySceneDetect 检测和分割场景。

  • 使用 pysubs2 + FFmpeg 创建、重新计时、转换、样式化和烧录字幕。

  • 维护持久的 OpenTimelineIO 时间线,包含轨道、剪辑、转场、标记、重新排序、检查和导出。

  • 使用 aubio 检测节拍、节奏、起始时间和音高。

  • 使用 RNNoise 本地降噪语音。

  • 使用小型 Silero VAD ONNX 模型检测语音片段。

  • 使用 whisper.cpp 本地转录音频、生成字幕并获得类似单词的时间戳。

  • 可选择使用用户提供的 Piper 语音合成语音;Piper 默认禁用。

  • 可选择在源站验证 Cloudflare Access JWT 并运行 Cloudflare Tunnel 边车。

此服务器有意不包含固定的 AI 生成工作流、长期记忆或代理技能。它暴露执行原语,以便客户端或单独的知识/技能 MCP 决定如何构建工作流。

ComfyUI 和 Blender 是外部可选后端。如果任一后端被禁用、缺失或暂时不可达,MCP 本身保持健康。网络相关工具返回模型可读的 available=false 结果,而不是关闭服务器或暴露后端缺失的工具错误。

Related MCP server: comfyui-mcp-server-node

架构

MCP client / AI
   |
   |<------ generic MCP file transfer ------>
   v
MCP Video Gen + persistent file_id cache
   |
   |---------------- optional ComfyUI API
   |                    |
   |                    +-- installed models
   |                    +-- custom nodes
   |                    +-- image/video/audio generation
   |
   |---------------- optional Blender bridge on VM
   |                    |
   |                    +-- bpy scene creation/editing
   |                    +-- .blend / GLB export
   |                    +-- still / animation rendering
   |
   |---------------- HyperFrames
   |---------------- OpenTimelineIO / subtitles
   |---------------- scene / frame analysis
   |---------------- whisper.cpp / Silero VAD / RNNoise / aubio
   +---------------- FFmpeg

All execution paths exchange files through the same MCP cache.

Portainer 部署

使用 video-mcp.yml 作为 Stack 定义。

可选的 ComfyUI

典型的 ComfyUI 连接变量是:

COMFYUI_HOST=host.docker.internal
COMFYUI_PORT=8188
COMFYUI_SCHEME=http

对于文件系统发现,当 ComfyUI 存在时设置主机路径:

COMFYUI_MODELS_PATH=/host/path/to/ComfyUI/models
COMFYUI_CUSTOM_NODES_PATH=/host/path/to/ComfyUI/custom_nodes

这些路径变量对于 MCP 启动不再是必需的。Stack 具有通用的空目录后备,因此它可以在安装 ComfyUI 之前启动。如果 ComfyUI 不可达,其网络工具会向模型报告该状态,而本地 MCP 工具继续工作。

可选的 Blender

Blender 默认禁用:

BLENDER_ENABLED=false
BLENDER_BRIDGE_URL=http://host.docker.internal:9876
BLENDER_BRIDGE_TOKEN=
BLENDER_BRIDGE_TIMEOUT_SEC=7200

推荐的集成方式是将 scripts/blender_bridge.py 直接作为专用的低权限操作系统账户在虚拟机中运行。容器通过经过身份验证的本地 HTTP 桥接器与其通信;Blender 本身在主机上无头运行。这避免了将主机根文件系统或主机可执行文件挂载到 MCP 容器中。

安装桥接器后,在 Portainer 中私有配置:

BLENDER_ENABLED=true
BLENDER_BRIDGE_URL=http://host.docker.internal:9876
BLENDER_BRIDGE_TOKEN=<same long random token used by the host bridge>

有关设置、安全性、systemd 强化、文件流程和示例,请参阅 docs/BLENDER_BRIDGE.md。

Cloudflare Tunnel

如果您使用包含的 Cloudflare Tunnel 边车,请提供:

CLOUDFLARED_TUNNEL_TOKEN=<set privately in Portainer>

将远程 Tunnel 主机名指向:

http://video-mcp:8000

MCP 端点是:

https://your-public-host.example/mcp

Cloudflare Access / 托管 OAuth

应用程序可以在源站验证 Cloudflare Access JWT。在 Portainer 中私有配置这些值:

CF_ACCESS_VERIFY=true
CF_ACCESS_TEAM_DOMAIN=https://your-team.cloudflareaccess.com
CF_ACCESS_AUD=<Access application audience tag>
PUBLIC_BASE_URL=https://your-public-host.example

任何真实的域名、受众、隧道令牌、桥接令牌、内部 IP 或凭据都不应属于此公共仓库。

外部后端可用性

external_backends_status 报告 ComfyUI 和 Blender 的当前状态。inventory_summary 包含相同的后端状态以及本地能力。

当外部后端不可用时,调用返回类似以下的结构:

{
  "ok": false,
  "available": false,
  "backend": "blender",
  "status": "unavailable",
  "message": "Blender integration is disabled..."
}

这与 MCP 服务器故障故意不同:模型了解到一个可选执行路径不可用,并可以继续使用另一个路径。

文件传输和共享缓存

每个生成的/导入的工件都被规范化为 MCP 缓存,并由 file_id 标识。这是 AI 客户端、ComfyUI、Blender、FFmpeg、HyperFrames、字幕、时间线和音频工具之间的交换层。

客户端 / AI -> MCP

对于小文件:

cache_text_file
cache_file_base64

对于较大的二进制文件:

file_upload_begin
file_upload_chunk
file_upload_finish
file_upload_abort

分块上传可以在提升到持久缓存之前指定预期的字节长度和 SHA-256。

MCP -> 客户端 / AI

元数据:

get_cached_file_info

小型现有兼容性路径:

get_output_inline_base64

有限制的通用读取:

read_cached_file_chunk_base64

每个正常缓存元数据对象还包含 /files/{file_id},并且当配置了 PUBLIC_BASE_URL 时,包含完整的经过身份验证的下载 URL。

这意味着 AI 可以将 Blender Python 脚本编写为文本,将任意引用的资源放入缓存,将这些 file_id 值发送给 Blender,接收 .blend/.glb/渲染结果作为新的 file_id 值,然后将这些文件馈送到 ComfyUI 或本地后处理堆栈中。

高级本地媒体工具

运行时除了 FFmpeg/HyperFrames 之外,还准备了几个小型本地工具。Python 虚拟环境包含 PySceneDetect、OpenTimelineIO、pysubs2、ONNX Runtime、NumPy 和无头 OpenCV。Debian 提供了小型 aubio-tools CLI 包。RNNoise 和 whisper.cpp 是从锁定的上游源代码构建到持久数据卷中的。

Silero VAD、RNNoise 和 whisper.cpp 模型/源工件存储在持久数据卷下。RNNoise 源代码和模型以及 Silero/Whisper 模型下载使用显式的 SHA-256 验证。默认的 Whisper 模型是一个小型量化模型,旨在用于轻量级本地转录;模型 URL/哈希和源引用可以通过 Stack 变量覆盖。

相关变量包括:

SILERO_VAD_ENABLED=true
SILERO_VAD_MODEL_URL=<public model URL>
SILERO_VAD_MODEL_SHA256=<expected sha256>

RNNOISE_ENABLED=true
RNNOISE_REF=<pinned upstream commit>
RNNOISE_SOURCE_URL=<public source archive URL>
RNNOISE_SOURCE_SHA256=<expected sha256>
RNNOISE_MODEL_URL=<public model URL>
RNNOISE_MODEL_SHA256=<expected sha256>

WHISPER_CPP_ENABLED=true
WHISPER_CPP_REF=v1.8.6
WHISPER_CPP_BUILD_JOBS=2
WHISPER_MODEL_AUTO_DOWNLOAD=true
WHISPER_MODEL_NAME=tiny-q5_1
WHISPER_MODEL_URL=<public model URL>
WHISPER_MODEL_SHA256=<expected sha256>

启用这些工具后的第一次启动可能需要更长时间,因为 RNNoise 和 whisper.cpp 是本地构建的,并且所选资产被下载。它们的结果构建和模型保留在 /data 中,因此在保留持久卷的情况下,正常的容器重新创建不会重复这些构建。Stack 为此给第一次启动提供了扩展的健康检查宽限期。

可选的 Piper TTS

Piper 作为可选运行时实现,并默认禁用:

PIPER_ENABLED=false
PIPER_PACKAGE_SPEC=piper-tts

启用时,不会自动下载任何语音。语音 .onnx 和匹配的配置文件位于 /data/piper/voices 下;可以通过 piper_import_voice_file 从 MCP 媒体缓存导入。这样可以保持 TTS 可选,因为 ComfyUI 本身也可以托管音频/TTS 工作流。

有关第三方许可注意事项,请参阅 THIRD_PARTY.md。

版本选择

Stack 支持:

VIDEO_MCP_VERSION=latest
VIDEO_MCP_CHECK_UPDATES_ON_START=true
VIDEO_MCP_FORCE_REFRESH=false

latest 表示最高的非草稿、非预发布 GitHub Release,其标签完全匹配 vX.Y.Z。它不表示 main。

您也可以固定一个版本:

VIDEO_MCP_VERSION=v2.4.0

或一个提交 SHA:

VIDEO_MCP_VERSION=<commit-sha>

当禁用更新检查且存在有效的 /current 源时,启动完全优先使用缓存。失败的版本查找、下载或存档验证会回退到最后已知的良好源(只要存在)。

持久卷

Stack 分离三个关注点:

video_mcp_code  -> /opt/video-mcp   versioned source cache + /current
video_mcp_venv  -> /opt/venv        persistent Python virtual environment
video_mcp_data  -> /data             media, timelines, models, local tooling, HyperFrames projects/cache

应用程序运行时数据根默认为 /data。直接/非 Stack 部署可以使用 VIDEO_MCP_DATA_ROOT 覆盖它;导入 video_mcp.server 或 video_mcp.entrypoint 不会创建该目录。运行时目录仅在应用程序启动时创建。

Python 环境仅在 requirements.txt 更改时重建。重建会清除挂载的 venv 目录的内容;它永远不会移除 Docker 挂载点本身。

源引导安全性

源存档从 GitHub codeload 下载到暂存目录,并在提取前进行验证。引导程序拒绝:

  • 绝对路径;

  • .. 遍历;

  • 符号链接;

  • 硬链接;

  • 具有多个顶级根的存档。

只有在提取和运行时契约检查成功后,版本才会收到 .mcp-source-ready。只有在此时才切换 /current,因此中断或格式错误的更新不能替换最后已知的良好源。

ComfyUI 模型和自定义节点文件系统挂载是只读的。AI 工具源/模型下载使用临时文件和 SHA-256 验证,然后再替换缓存的工件。可选的 Blender 桥接器使用 bearer 令牌认证,并且只传输声明的作业输入/输出,但任意的 Blender Python 仍然是强大的,因此必须使用非特权操作系统账户隔离桥接器。

HyperFrames

HyperFrames 在 MCP 容器中本地运行,并使用与 MCP 媒体缓存相同的持久 /data 区域。浏览器资产在 /data/hyperframes-home 下持久缓存。

默认的包规范在 Stack 中固定以确保可重现性,并且可以私有覆盖:

HYPERFRAMES_NPM_SPEC=hyperframes@0.7.111

HyperFrames 技能在此执行服务器中被有意禁用(HYPERFRAMES_SKIP_SKILLS=1)。

开发

python -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt pytest PyYAML
PYTHONPATH=src python -m pytest -q
python scripts/check_public_repo.py

CI 检查 Python 编译、服务器/入口点导入、测试、YAML 解析、shell/Python 辅助语法、Compose 渲染、版本/更新日志一致性以及公共仓库秘密/私有网络防护栏。

发布流程

  1. 在分支上开发并打开 PR。

  2. CI 必须通过。

  3. 更新 VERSION 和 CHANGELOG.md。

  4. 合并到 main。

  5. 如果尚不存在,CI 会创建不可变的 vX.Y.Z 标签和匹配的稳定 GitHub Release。

应用程序标签/版本保留给精确的 vX.Y.Z 名称,以便不相关的模型或资产版本不会影响 VIDEO_MCP_VERSION=latest 解析。

许可和归属

根据 Apache License 2.0 许可。请参阅 LICENSE。

根据 Apache License 2.0 的要求,再分发和衍生作品必须保留 NOTICE 中的归属声明。第三方组件保留其自己的许可证;请参阅 THIRD_PARTY.md。

Related MCP Connectors

Related MCP Servers