timeverse-hyperframes-mcp 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (21) hide show
  1. timeverse_hyperframes_mcp-0.1.0/PKG-INFO +8 -0
  2. timeverse_hyperframes_mcp-0.1.0/README.md +114 -0
  3. timeverse_hyperframes_mcp-0.1.0/pyproject.toml +20 -0
  4. timeverse_hyperframes_mcp-0.1.0/setup.cfg +4 -0
  5. timeverse_hyperframes_mcp-0.1.0/src/timeverse_hyperframes_mcp/__init__.py +23 -0
  6. timeverse_hyperframes_mcp-0.1.0/src/timeverse_hyperframes_mcp/__main__.py +4 -0
  7. timeverse_hyperframes_mcp-0.1.0/src/timeverse_hyperframes_mcp/cli_executor.py +196 -0
  8. timeverse_hyperframes_mcp-0.1.0/src/timeverse_hyperframes_mcp/server.py +57 -0
  9. timeverse_hyperframes_mcp-0.1.0/src/timeverse_hyperframes_mcp/tools/__init__.py +26 -0
  10. timeverse_hyperframes_mcp-0.1.0/src/timeverse_hyperframes_mcp/tools/init.py +121 -0
  11. timeverse_hyperframes_mcp-0.1.0/src/timeverse_hyperframes_mcp/tools/lint.py +74 -0
  12. timeverse_hyperframes_mcp-0.1.0/src/timeverse_hyperframes_mcp/tools/media.py +128 -0
  13. timeverse_hyperframes_mcp-0.1.0/src/timeverse_hyperframes_mcp/tools/preview.py +61 -0
  14. timeverse_hyperframes_mcp-0.1.0/src/timeverse_hyperframes_mcp/tools/render.py +105 -0
  15. timeverse_hyperframes_mcp-0.1.0/src/timeverse_hyperframes_mcp/tools/system.py +168 -0
  16. timeverse_hyperframes_mcp-0.1.0/src/timeverse_hyperframes_mcp.egg-info/PKG-INFO +8 -0
  17. timeverse_hyperframes_mcp-0.1.0/src/timeverse_hyperframes_mcp.egg-info/SOURCES.txt +19 -0
  18. timeverse_hyperframes_mcp-0.1.0/src/timeverse_hyperframes_mcp.egg-info/dependency_links.txt +1 -0
  19. timeverse_hyperframes_mcp-0.1.0/src/timeverse_hyperframes_mcp.egg-info/entry_points.txt +2 -0
  20. timeverse_hyperframes_mcp-0.1.0/src/timeverse_hyperframes_mcp.egg-info/requires.txt +3 -0
  21. timeverse_hyperframes_mcp-0.1.0/src/timeverse_hyperframes_mcp.egg-info/top_level.txt +1 -0
@@ -0,0 +1,8 @@
1
+ Metadata-Version: 2.4
2
+ Name: timeverse-hyperframes-mcp
3
+ Version: 0.1.0
4
+ Summary: MCP server wrapping HyperFrames CLI — turn HTML/CSS/JS into MP4 videos
5
+ Requires-Python: >=3.11
6
+ Requires-Dist: mcp>=1.0.0
7
+ Requires-Dist: httpx>=0.27.0
8
+ Requires-Dist: pydantic>=2.0.0
@@ -0,0 +1,114 @@
1
+ # TimeVerse HyperFrames MCP
2
+
3
+ 将 [HyperFrames](https://github.com/heygen-com/hyperframes) CLI 包装为 MCP 工具服务,让 AI Agent 可以:
4
+ - 创建/初始化视频项目
5
+ - 实时预览 HTML 视频
6
+ - 渲染为 MP4/WebM
7
+ - 检查语法完整性
8
+ - 文本转语音 / 音频转录
9
+
10
+ ## 前置依赖
11
+
12
+ - Python >= 3.11
13
+ - Node.js >= 22
14
+ - FFmpeg
15
+
16
+ ```bash
17
+ # macOS
18
+ brew install ffmpeg
19
+
20
+ # Ubuntu
21
+ sudo apt install ffmpeg
22
+ ```
23
+
24
+ ## 安装
25
+
26
+ ### 方式一:pip 安装
27
+
28
+ ```bash
29
+ pip install -e .
30
+ ```
31
+
32
+ ### 方式二:uvx 运行(无需安装)
33
+
34
+ 需要先安装 [uv](https://docs.astral.sh/uv/):
35
+
36
+ ```bash
37
+ # macOS / Linux
38
+ curl -LsSf https://astral.sh/uv/install.sh | sh
39
+
40
+ # 然后直接通过 uvx 运行
41
+ uvx timeverse-hyperframes-mcp
42
+ ```
43
+
44
+ `uvx` 会自动下载依赖并缓存,下次运行更快。
45
+
46
+ ## 使用
47
+
48
+ ### 直接运行 MCP 服务器
49
+
50
+ ```bash
51
+ # pip 安装后
52
+ timeverse-hyperframes-mcp
53
+
54
+ # 或用 uvx
55
+ uvx timeverse-hyperframes-mcp
56
+
57
+ # 或用 python -m
58
+ python -m timeverse_hyperframes_mcp.server
59
+ ```
60
+
61
+ ### 注册到 TimeVerseStudio
62
+
63
+ 在 MCP 设置页面点击 **JSON 导入**,填入以下内容:
64
+
65
+ ```json
66
+ {
67
+ "mcpServers": {
68
+ "hyperframes": {
69
+ "description": "HyperFrames MCP — 将 HTML/CSS/JS 渲染为 MP4 视频",
70
+ "command": "uvx",
71
+ "args": ["timeverse-hyperframes-mcp"]
72
+ }
73
+ }
74
+ }
75
+ ```
76
+
77
+ 或通过 API 创建:
78
+
79
+ ```json
80
+ {
81
+ "name": "hyperframes",
82
+ "server_type": "local",
83
+ "transport": "stdio",
84
+ "command": "uvx",
85
+ "args": "timeverse-hyperframes-mcp",
86
+ "description": "HyperFrames MCP — 将 HTML/CSS/JS 渲染为 MP4 视频"
87
+ }
88
+ ```
89
+
90
+ 完整示例见 `examples/timeverse-integration.json`。
91
+
92
+ ## 可用工具
93
+
94
+ | 工具 | 对应 CLI 命令 | 说明 |
95
+ |---|---|---|
96
+ | `hyperframes_init` | `npx hyperframes init` | 创建视频项目 |
97
+ | `hyperframes_list_templates` | - | 列出可用模板 |
98
+ | `hyperframes_render` | `npx hyperframes render` | 渲染视频 |
99
+ | `hyperframes_preview` | `npx hyperframes preview` | 启动本地预览 |
100
+ | `hyperframes_lint` | `npx hyperframes lint` | 语法检查 |
101
+ | `hyperframes_doctor` | `npx hyperframes doctor` | 环境检测 |
102
+ | `hyperframes_info` | `npx hyperframes info` | 版本信息 |
103
+ | `hyperframes_upgrade` | `npx hyperframes upgrade` | 检查更新 |
104
+ | `hyperframes_compositions` | `npx hyperframes compositions` | 列出 composition |
105
+ | `hyperframes_benchmark` | `npx hyperframes benchmark` | 性能基准测试 |
106
+ | `hyperframes_tts` | `npx hyperframes tts` | 文本转语音 |
107
+ | `hyperframes_list_voices` | `npx hyperframes tts --list` | 列出语音角色 |
108
+ | `hyperframes_transcribe` | `npx hyperframes transcribe` | 音频/视频转录 |
109
+
110
+ ## 环境变量
111
+
112
+ | 变量 | 说明 | 默认值 |
113
+ |---|---|---|
114
+ | `HYPERFRAMES_WORKSPACE_DIR` | 视频项目工作目录 | 当前工作目录 |
@@ -0,0 +1,20 @@
1
+ [project]
2
+ name = "timeverse-hyperframes-mcp"
3
+ version = "0.1.0"
4
+ description = "MCP server wrapping HyperFrames CLI — turn HTML/CSS/JS into MP4 videos"
5
+ requires-python = ">=3.11"
6
+ dependencies = [
7
+ "mcp>=1.0.0",
8
+ "httpx>=0.27.0",
9
+ "pydantic>=2.0.0",
10
+ ]
11
+
12
+ [project.scripts]
13
+ timeverse-hyperframes-mcp = "timeverse_hyperframes_mcp.server:main"
14
+
15
+ [tool.setuptools.packages.find]
16
+ where = ["src"]
17
+
18
+ [build-system]
19
+ requires = ["setuptools>=68.0"]
20
+ build-backend = "setuptools.build_meta"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,23 @@
1
+ """
2
+ timeverse-hyperframes-mcp — MCP server for HyperFrames
3
+
4
+ 功能简述:
5
+ MCP 服务器,将 HyperFrames CLI(HTML 转视频渲染引擎)包装为 MCP 工具。
6
+ 支持视频项目初始化、预览、渲染、lint、TTS 等能力。
7
+ 兼容 TimeVerseStudio 的 MCP 注册体系(local/stdio 模式)。
8
+
9
+ 主要工具清单:
10
+ - hyperframes_init: 创建新的视频项目
11
+ - hyperframes_render: 渲染视频为 MP4/WebM
12
+ - hyperframes_preview: 启动本地实时预览
13
+ - hyperframes_lint: 检查项目语法完整性
14
+ - hyperframes_doctor: 检测运行环境
15
+ - hyperframes_tts: 文本转语音
16
+ - hyperframes_transcribe: 音频/视频转录文字
17
+
18
+ 使用示例:
19
+ # 作为 stdio MCP 服务器运行
20
+ python -m timeverse_hyperframes_mcp.server
21
+ """
22
+
23
+ __version__ = "0.1.0"
@@ -0,0 +1,4 @@
1
+ """python -m 入口"""
2
+ from .server import main
3
+
4
+ main()
@@ -0,0 +1,196 @@
1
+ """
2
+ CLI 执行器 — 统一执行 HyperFrames CLI 命令
3
+
4
+ 功能简述:
5
+ 提供异步执行 npx hyperframes 命令的统一接口。
6
+ 处理命令超时、错误捕获、标准输出解析。
7
+
8
+ 主要方法清单:
9
+ - run_hyperframes: 执行任意 hyperframes 子命令
10
+ - check_environment: 检测 ffmpeg / node 环境
11
+ - parse_lint_output: 解析 lint --json 输出
12
+ - find_workspace: 查找或创建项目工作目录
13
+
14
+ 使用示例:
15
+ result = await run_hyperframes(["init", "my-video", "--non-interactive"])
16
+ """
17
+
18
+ import asyncio
19
+ import json
20
+ import logging
21
+ import os
22
+ import shutil
23
+ from pathlib import Path
24
+ from typing import Optional
25
+
26
+ logger = logging.getLogger(__name__)
27
+
28
+ # ==================== 常量定义 ====================
29
+
30
+ DEFAULT_TIMEOUT = 120 # 默认超时(秒)
31
+ RENDER_TIMEOUT = 600 # 渲染超时(秒)
32
+ WORKSPACE_ENV_VAR = "HYPERFRAMES_WORKSPACE_DIR"
33
+
34
+
35
+ # ==================== 核心方法 ====================
36
+
37
+ async def run_hyperframes(
38
+ args: list[str],
39
+ cwd: Optional[str] = None,
40
+ timeout: int = DEFAULT_TIMEOUT,
41
+ ) -> dict:
42
+ """
43
+ 执行 npx hyperframes <args> 命令
44
+
45
+ Args:
46
+ args: 子命令及参数列表,如 ["init", "my-video", "--non-interactive"]
47
+ cwd: 工作目录,默认为 WORKSPACE_ENV_VAR 指向的目录或当前目录
48
+ timeout: 超时秒数
49
+
50
+ Returns:
51
+ {
52
+ "success": bool,
53
+ "stdout": str,
54
+ "stderr": str,
55
+ "exit_code": int,
56
+ "command": str
57
+ }
58
+
59
+ Raises:
60
+ TimeoutError: 命令执行超时
61
+ """
62
+ cmd = ["npx", "hyperframes", *args]
63
+ cmd_str = " ".join(cmd)
64
+
65
+ if cwd is None:
66
+ cwd = os.environ.get(WORKSPACE_ENV_VAR, os.getcwd())
67
+
68
+ try:
69
+ proc = await asyncio.wait_for(
70
+ asyncio.create_subprocess_exec(
71
+ *cmd,
72
+ cwd=cwd,
73
+ stdout=asyncio.subprocess.PIPE,
74
+ stderr=asyncio.subprocess.PIPE,
75
+ env={**os.environ, "PAGER": "cat"},
76
+ ),
77
+ timeout=timeout,
78
+ )
79
+ stdout, stderr = await proc.communicate()
80
+ stdout_str = stdout.decode("utf-8", errors="replace").strip()
81
+ stderr_str = stderr.decode("utf-8", errors="replace").strip()
82
+
83
+ return {
84
+ "success": proc.returncode == 0,
85
+ "stdout": stdout_str,
86
+ "stderr": stderr_str,
87
+ "exit_code": proc.returncode or 0,
88
+ "command": cmd_str,
89
+ }
90
+ except asyncio.TimeoutError:
91
+ raise TimeoutError(f"命令超时({timeout}s): {cmd_str}")
92
+ except FileNotFoundError:
93
+ return {
94
+ "success": False,
95
+ "stdout": "",
96
+ "stderr": "未找到 npx,请确认 Node.js >= 22 已安装",
97
+ "exit_code": -1,
98
+ "command": cmd_str,
99
+ }
100
+
101
+
102
+ async def check_environment() -> dict:
103
+ """
104
+ 检测运行环境是否满足 HyperFrames 要求
105
+
106
+ Returns:
107
+ {
108
+ "node_ok": bool, "node_version": str,
109
+ "ffmpeg_ok": bool, "ffmpeg_version": str,
110
+ "npx_ok": bool,
111
+ "all_ok": bool
112
+ }
113
+ """
114
+ checks = {
115
+ "node_ok": False,
116
+ "node_version": "",
117
+ "ffmpeg_ok": False,
118
+ "ffmpeg_version": "",
119
+ "npx_ok": False,
120
+ "all_ok": False,
121
+ }
122
+
123
+ # 检测 Node.js
124
+ try:
125
+ proc = await asyncio.create_subprocess_exec(
126
+ "node", "--version",
127
+ stdout=asyncio.subprocess.PIPE,
128
+ stderr=asyncio.subprocess.PIPE,
129
+ )
130
+ stdout, _ = await proc.communicate()
131
+ version = stdout.decode("utf-8", errors="replace").strip()
132
+ checks["node_version"] = version
133
+ checks["node_ok"] = bool(version) and proc.returncode == 0
134
+ except FileNotFoundError:
135
+ checks["node_version"] = "未安装"
136
+
137
+ # 检测 npx
138
+ try:
139
+ proc = await asyncio.create_subprocess_exec(
140
+ "npx", "--version",
141
+ stdout=asyncio.subprocess.PIPE,
142
+ stderr=asyncio.subprocess.PIPE,
143
+ )
144
+ stdout, _ = await proc.communicate()
145
+ checks["npx_ok"] = proc.returncode == 0
146
+ except FileNotFoundError:
147
+ pass
148
+
149
+ # 检测 ffmpeg
150
+ try:
151
+ proc = await asyncio.create_subprocess_exec(
152
+ "ffmpeg", "-version",
153
+ stdout=asyncio.subprocess.PIPE,
154
+ stderr=asyncio.subprocess.PIPE,
155
+ )
156
+ stdout, _ = await proc.communicate()
157
+ if proc.returncode == 0:
158
+ first_line = stdout.decode("utf-8", errors="replace").split("\n")[0].strip()
159
+ checks["ffmpeg_version"] = first_line
160
+ checks["ffmpeg_ok"] = True
161
+ except FileNotFoundError:
162
+ checks["ffmpeg_version"] = "未安装"
163
+
164
+ checks["all_ok"] = checks["node_ok"] and checks["ffmpeg_ok"] and checks["npx_ok"]
165
+ return checks
166
+
167
+
168
+ def parse_lint_json(stdout: str) -> dict:
169
+ """
170
+ 解析 hyperframes lint --json 输出
171
+
172
+ Args:
173
+ stdout: lint --json 的标准输出
174
+
175
+ Returns:
176
+ 解析后的 lint 结果字典,包含 errorCount, warningCount, findings 等字段
177
+ """
178
+ try:
179
+ return json.loads(stdout)
180
+ except json.JSONDecodeError:
181
+ return {"error": "无法解析 lint 输出", "raw": stdout}
182
+
183
+
184
+ # ==================== 工具函数 ====================
185
+
186
+ def find_workspace() -> str:
187
+ """
188
+ 获取工作目录(优先从环境变量读取,否则用当前目录)
189
+
190
+ Returns:
191
+ 工作目录绝对路径
192
+ """
193
+ workspace = os.environ.get(WORKSPACE_ENV_VAR)
194
+ if workspace and os.path.isdir(workspace):
195
+ return workspace
196
+ return os.getcwd()
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ timeverse-hyperframes-mcp — MCP 服务器主入口
4
+
5
+ 功能简述:
6
+ 使用 FastMCP 创建 MCP 服务器,将所有 HyperFrames CLI 命令包装为 MCP 工具。
7
+ 通过 stdio 协议与 MCP 客户端(如 TimeVerseStudio)通信。
8
+
9
+ 使用示例:
10
+ # 直接运行
11
+ python -m timeverse_hyperframes_mcp.server
12
+
13
+ # 或作为 CLI 命令(安装后)
14
+ timeverse-hyperframes-mcp
15
+ """
16
+
17
+ import asyncio
18
+ import logging
19
+ import sys
20
+
21
+ from mcp.server import FastMCP
22
+
23
+ from . import __version__
24
+ from .tools import register_all
25
+
26
+ # ==================== 日志配置 ====================
27
+
28
+ logging.basicConfig(
29
+ level=logging.WARNING,
30
+ format="[%(levelname)s] %(name)s: %(message)s",
31
+ stream=sys.stderr,
32
+ )
33
+ logger = logging.getLogger(__name__)
34
+
35
+ # ==================== 创建 MCP 服务器 ====================
36
+
37
+ mcp = FastMCP(
38
+ name="timeverse-hyperframes-mcp",
39
+ instructions="HyperFrames MCP Server — 将 HTML/CSS/JS 渲染为 MP4 视频。支持 init / preview / render / lint / TTS / transcribe 等命令。",
40
+ )
41
+
42
+
43
+ # ==================== 注册工具 ====================
44
+
45
+ register_all(mcp)
46
+
47
+
48
+ # ==================== 启动 ====================
49
+
50
+ def main() -> None:
51
+ """启动 MCP 服务器(stdio 模式)"""
52
+ logger.info("启动 timeverse-hyperframes-mcp v%s(stdio 模式)", __version__)
53
+ mcp.run(transport="stdio")
54
+
55
+
56
+ if __name__ == "__main__":
57
+ main()
@@ -0,0 +1,26 @@
1
+ """
2
+ HyperFrames MCP 工具模块
3
+
4
+ 功能简述:
5
+ 将所有工具函数注册到 FastMCP 服务器实例。
6
+ 每个子模块的 register_xxx(mcp) 函数负责注册对应的 MCP 工具。
7
+
8
+ 主要方法清单:
9
+ - register_all(mcp): 注册所有工具到指定 FastMCP 实例
10
+
11
+ 使用示例:
12
+ from . import register_all
13
+ register_all(mcp)
14
+ """
15
+
16
+ from . import init, render, preview, lint, media, system
17
+
18
+
19
+ def register_all(mcp) -> None:
20
+ """注册所有 HyperFrames MCP 工具"""
21
+ init.register_tools(mcp)
22
+ render.register_tools(mcp)
23
+ preview.register_tools(mcp)
24
+ lint.register_tools(mcp)
25
+ media.register_tools(mcp)
26
+ system.register_tools(mcp)
@@ -0,0 +1,121 @@
1
+ """
2
+ hyperframes_init — 视频项目初始化工具
3
+
4
+ 功能简述:
5
+ 封装 npx hyperframes init 命令,支持创建新视频项目。
6
+ 可选择模板、预设示例、附带视频/音频素材。
7
+
8
+ 主要方法清单:
9
+ - register_tools(mcp): 注册 hyperframes_init / hyperframes_list_templates
10
+ """
11
+
12
+ import os
13
+ from typing import Optional
14
+
15
+ from ..cli_executor import run_hyperframes, find_workspace
16
+
17
+ # ==================== 常量定义 ====================
18
+
19
+ AVAILABLE_TEMPLATES = [
20
+ "blank",
21
+ "warm-grain",
22
+ "play-mode",
23
+ "swiss-grid",
24
+ "vignelli",
25
+ "decision-tree",
26
+ "kinetic-type",
27
+ "product-promo",
28
+ "nyt-graph",
29
+ ]
30
+
31
+
32
+ def register_tools(mcp) -> None:
33
+ """注册初始化相关的 MCP 工具"""
34
+
35
+ @mcp.tool(
36
+ name="hyperframes_init",
37
+ description="创建新的 HyperFrames 视频项目。初始化目录结构、安装依赖。"
38
+ )
39
+ async def hyperframes_init(
40
+ project_name: str,
41
+ template: Optional[str] = None,
42
+ video_path: Optional[str] = None,
43
+ audio_path: Optional[str] = None,
44
+ non_interactive: bool = True,
45
+ parent_dir: Optional[str] = None,
46
+ ) -> str:
47
+ """
48
+ 创建新的 HyperFrames 视频项目
49
+
50
+ Args:
51
+ project_name: 项目目录名称(如 "my-video")
52
+ template: 模板名称。可选值:blank, warm-grain, play-mode, swiss-grid, vignelli, decision-tree, kinetic-type, product-promo, nyt-graph
53
+ video_path: 附带已有视频文件路径(将自动拷贝到项目中)
54
+ audio_path: 附带音频文件路径(将自动拷贝并转写)
55
+ non_interactive: 是否静默模式(默认 True,适合 AI 调用)
56
+ parent_dir: 父级目录,默认为当前工作空间
57
+
58
+ Returns:
59
+ 项目的标准输出信息
60
+ """
61
+ args = ["init", project_name]
62
+
63
+ if non_interactive:
64
+ args.append("--non-interactive")
65
+
66
+ if template:
67
+ if template not in AVAILABLE_TEMPLATES:
68
+ available = ", ".join(AVAILABLE_TEMPLATES)
69
+ return (
70
+ f"❌ 无效模板: {template}\n"
71
+ f"可用模板: {available}"
72
+ )
73
+ args.extend(["--example", template])
74
+
75
+ if video_path:
76
+ args.extend(["--video", video_path])
77
+
78
+ if audio_path:
79
+ args.extend(["--audio", audio_path])
80
+
81
+ workspace = parent_dir or find_workspace()
82
+ result = await run_hyperframes(args, cwd=workspace)
83
+
84
+ if result["success"]:
85
+ project_dir = os.path.join(workspace, project_name)
86
+ return (
87
+ f"✅ 项目创建成功\n"
88
+ f" 路径: {project_dir}\n"
89
+ f" 模板: {template or 'blank'}\n"
90
+ f"{result['stdout']}"
91
+ )
92
+ else:
93
+ return f"❌ 项目创建失败\n{result['stderr']}"
94
+
95
+ @mcp.tool(
96
+ name="hyperframes_list_templates",
97
+ description="列出 HyperFrames 所有可用的项目模板。"
98
+ )
99
+ async def hyperframes_list_templates() -> str:
100
+ """
101
+ 列出所有可用的项目模板
102
+
103
+ Returns:
104
+ 模板列表与说明
105
+ """
106
+ templates_info = {
107
+ "blank": "空项目,从零开始",
108
+ "warm-grain": "暖色颗粒纹理风格",
109
+ "play-mode": "Play 模式示例",
110
+ "swiss-grid": "瑞士网格排版风格",
111
+ "vignelli": "Vignelli 风格",
112
+ "decision-tree": "决策树流程图",
113
+ "kinetic-type": "动态文字排版",
114
+ "product-promo": "产品宣传视频模板",
115
+ "nyt-graph": "纽约时报风格数据可视化",
116
+ }
117
+ lines = ["📁 HyperFrames 可用模板:\n"]
118
+ for t in AVAILABLE_TEMPLATES:
119
+ desc = templates_info.get(t, "")
120
+ lines.append(f" - {t}: {desc}")
121
+ return "\n".join(lines)
@@ -0,0 +1,74 @@
1
+ """
2
+ hyperframes_lint — 项目语法检查工具
3
+
4
+ 功能简述:
5
+ 封装 npx hyperframes lint 命令,验证 composition 语法正确性。
6
+ 检查 data-composition-id、track 重叠、timeline 注册等问题。
7
+
8
+ 主要方法清单:
9
+ - register_tools(mcp): 注册 hyperframes_lint
10
+ """
11
+
12
+ from typing import Optional
13
+
14
+ from ..cli_executor import run_hyperframes, find_workspace, parse_lint_json
15
+
16
+
17
+ def register_tools(mcp) -> None:
18
+ """注册 lint 相关的 MCP 工具"""
19
+
20
+ @mcp.tool(
21
+ name="hyperframes_lint",
22
+ description="检查 HyperFrames 项目的语法和结构完整性。建议在 preview/render 前运行。"
23
+ )
24
+ async def hyperframes_lint(
25
+ project_dir: Optional[str] = None,
26
+ verbose: bool = False,
27
+ json_output: bool = True,
28
+ ) -> str:
29
+ """
30
+ 检查 HyperFrames 项目的语法和结构完整性
31
+
32
+ Args:
33
+ project_dir: 项目目录路径。默认为当前工作空间
34
+ verbose: 是否显示 info 级别的详细信息(默认只显示 errors 和 warnings)
35
+ json_output: 是否输出结构化 JSON 结果(默认 True)
36
+
37
+ Returns:
38
+ lint 检查结果
39
+ """
40
+ args = ["lint"]
41
+
42
+ if verbose:
43
+ args.append("--verbose")
44
+
45
+ if json_output:
46
+ args.append("--json")
47
+
48
+ workspace = find_workspace() if not project_dir else project_dir
49
+ result = await run_hyperframes(args, cwd=workspace)
50
+
51
+ if not result["success"] and not result["stdout"]:
52
+ return f"❌ lint 检查失败\n{result['stderr']}"
53
+
54
+ if json_output and result["stdout"]:
55
+ parsed = parse_lint_json(result["stdout"])
56
+ if "errorCount" in parsed:
57
+ ec = parsed.get("errorCount", 0)
58
+ wc = parsed.get("warningCount", 0)
59
+ ic = parsed.get("infoCount", 0)
60
+ findings = parsed.get("findings", [])
61
+ lines = [f"📋 Lint 结果:{ec} 个错误, {wc} 个警告, {ic} 个信息\n"]
62
+ for f in findings:
63
+ severity = f.get("severity", "info")
64
+ icon = {"error": "❌", "warning": "⚠️", "info": "ℹ️"}.get(severity, "•")
65
+ msg = f.get("message", "")
66
+ loc = f.get("location", "")
67
+ lines.append(f" {icon} [{severity}] {msg}")
68
+ if loc:
69
+ lines[-1] += f" ({loc})"
70
+ if ec > 0:
71
+ lines.append("\n💡 存在错误,建议修复后再 preview/render")
72
+ return "\n".join(lines)
73
+
74
+ return result["stdout"] or result["stderr"]
@@ -0,0 +1,128 @@
1
+ """
2
+ hyperframes_media — 媒体处理工具(TTS / 转录)
3
+
4
+ 功能简述:
5
+ 封装 npx hyperframes tts 和 npx hyperframes transcribe 命令。
6
+ 支持文本转语音、音频/视频转录字幕、字幕导入导出。
7
+
8
+ 主要方法清单:
9
+ - register_tools(mcp): 注册 hyperframes_tts / hyperframes_transcribe / hyperframes_list_voices
10
+ """
11
+
12
+ from typing import Optional
13
+
14
+ from ..cli_executor import run_hyperframes, find_workspace
15
+
16
+
17
+ def register_tools(mcp) -> None:
18
+ """注册媒体处理相关的 MCP 工具"""
19
+
20
+ @mcp.tool(
21
+ name="hyperframes_tts",
22
+ description="文本转语音(Text-to-Speech)。生成配音音频文件。"
23
+ )
24
+ async def hyperframes_tts(
25
+ text: str,
26
+ voice: Optional[str] = None,
27
+ output: Optional[str] = None,
28
+ project_dir: Optional[str] = None,
29
+ ) -> str:
30
+ """
31
+ 文本转语音
32
+
33
+ Args:
34
+ text: 需要朗读的文本内容,或包含文本的文件路径
35
+ voice: 语音角色(如 af_nova, bf_emma)。不指定则用默认角色
36
+ output: 输出音频文件路径,默认 narration.wav
37
+ project_dir: 项目目录路径
38
+
39
+ Returns:
40
+ TTS 执行结果
41
+ """
42
+ args = ["tts"]
43
+
44
+ # 判断 text 是文件路径还是纯文本
45
+ args.append(text)
46
+
47
+ if voice:
48
+ args.extend(["--voice", voice])
49
+
50
+ if output:
51
+ args.extend(["--output", output])
52
+
53
+ workspace = find_workspace() if not project_dir else project_dir
54
+ result = await run_hyperframes(args, cwd=workspace)
55
+
56
+ if result["success"]:
57
+ return f"✅ TTS 生成成功\n{result['stdout']}"
58
+ else:
59
+ return f"❌ TTS 生成失败\n{result['stderr']}"
60
+
61
+ @mcp.tool(
62
+ name="hyperframes_list_voices",
63
+ description="列出所有可用的 TTS 语音角色。"
64
+ )
65
+ async def hyperframes_list_voices(
66
+ project_dir: Optional[str] = None,
67
+ ) -> str:
68
+ """
69
+ 列出所有可用的 TTS 语音角色
70
+
71
+ Args:
72
+ project_dir: 项目目录路径
73
+
74
+ Returns:
75
+ 可用语音角色列表
76
+ """
77
+ result = await run_hyperframes(
78
+ ["tts", "--list"],
79
+ cwd=find_workspace() if not project_dir else project_dir,
80
+ )
81
+
82
+ if result["success"]:
83
+ return result["stdout"]
84
+ else:
85
+ return f"❌ 获取语音列表失败\n{result['stderr']}"
86
+
87
+ @mcp.tool(
88
+ name="hyperframes_transcribe",
89
+ description="音频/视频转录为文字字幕。支持多种输入格式。"
90
+ )
91
+ async def hyperframes_transcribe(
92
+ input_path: str,
93
+ model: Optional[str] = None,
94
+ language: Optional[str] = None,
95
+ output_format: Optional[str] = None,
96
+ project_dir: Optional[str] = None,
97
+ ) -> str:
98
+ """
99
+ 音频/视频转录文字
100
+
101
+ Args:
102
+ input_path: 输入音频/视频文件路径,或现有字幕文件路径(.srt/.vtt/.json)
103
+ model: Whisper 模型大小(如 tiny, base, small, medium, large)。默认 medium.en
104
+ language: 语言代码(如 en, zh, ja)。不指定则自动检测
105
+ output_format: 输出字幕格式(当输入是媒体文件时)。不指定则自动推断
106
+ project_dir: 项目目录路径
107
+
108
+ Returns:
109
+ 转录结果
110
+ """
111
+ args = ["transcribe", input_path]
112
+
113
+ if model:
114
+ args.extend(["--model", model])
115
+
116
+ if language:
117
+ args.extend(["--language", language])
118
+
119
+ if output_format:
120
+ args.extend(["--output-format", output_format])
121
+
122
+ workspace = find_workspace() if not project_dir else project_dir
123
+ result = await run_hyperframes(args, cwd=workspace, timeout=300)
124
+
125
+ if result["success"]:
126
+ return f"✅ 转录成功\n{result['stdout']}"
127
+ else:
128
+ return f"❌ 转录失败\n{result['stderr']}"
@@ -0,0 +1,61 @@
1
+ """
2
+ hyperframes_preview — 视频预览工具
3
+
4
+ 功能简述:
5
+ 封装 npx hyperframes preview 命令,启动本地实时预览服务。
6
+ 支持自定义端口,热重载。
7
+
8
+ 主要方法清单:
9
+ - register_tools(mcp): 注册 hyperframes_preview
10
+ """
11
+
12
+ from typing import Optional
13
+
14
+ from ..cli_executor import run_hyperframes, find_workspace
15
+
16
+
17
+ def register_tools(mcp) -> None:
18
+ """注册预览相关的 MCP 工具"""
19
+
20
+ @mcp.tool(
21
+ name="hyperframes_preview",
22
+ description="启动 HyperFrames 项目的本地实时预览服务。热重载,编辑即更新。"
23
+ )
24
+ async def hyperframes_preview(
25
+ project_dir: Optional[str] = None,
26
+ port: Optional[int] = None,
27
+ ) -> str:
28
+ """
29
+ 启动本地预览服务
30
+
31
+ Args:
32
+ project_dir: 项目目录路径。默认为当前工作空间
33
+ port: 端口号(默认 3002)
34
+
35
+ Returns:
36
+ 预览服务信息,包含访问地址
37
+ """
38
+ args = ["preview"]
39
+
40
+ if port:
41
+ args.extend(["--port", str(port)])
42
+
43
+ workspace = find_workspace() if not project_dir else project_dir
44
+ # preview 是一个持续运行的服务,设置较短超时拿到初始输出即可
45
+ result = await run_hyperframes(args, cwd=workspace, timeout=15)
46
+
47
+ if result["success"]:
48
+ output = result["stdout"]
49
+ # 从 stdout 中提取 URL
50
+ url = ""
51
+ for line in output.split("\n"):
52
+ if "http" in line:
53
+ url = line.strip()
54
+ break
55
+ msg = f"✅ 预览服务已启动\n"
56
+ if url:
57
+ msg += f" 访问地址: {url}\n"
58
+ msg += output
59
+ return msg
60
+ else:
61
+ return f"❌ 预览启动失败\n{result['stderr']}"
@@ -0,0 +1,105 @@
1
+ """
2
+ hyperframes_render — 视频渲染工具
3
+
4
+ 功能简述:
5
+ 封装 npx hyperframes render 命令,支持多种质量/格式/帧率。
6
+ 支持指定 composition、GPU 加速、Docker 可重现构建等高级选项。
7
+
8
+ 主要方法清单:
9
+ - register_tools(mcp): 注册 hyperframes_render
10
+ """
11
+
12
+ from typing import Optional
13
+
14
+ from ..cli_executor import run_hyperframes, find_workspace, RENDER_TIMEOUT
15
+
16
+
17
+ def register_tools(mcp) -> None:
18
+ """注册渲染相关的 MCP 工具"""
19
+
20
+ @mcp.tool(
21
+ name="hyperframes_render",
22
+ description="将 HyperFrames 项目渲染为 MP4/WebM 视频。"
23
+ )
24
+ async def hyperframes_render(
25
+ project_dir: Optional[str] = None,
26
+ output: Optional[str] = None,
27
+ fps: Optional[int] = None,
28
+ quality: Optional[str] = None,
29
+ format: Optional[str] = None,
30
+ composition: Optional[str] = None,
31
+ workers: Optional[int] = None,
32
+ gpu: bool = False,
33
+ docker: bool = False,
34
+ strict: bool = False,
35
+ strict_all: bool = False,
36
+ timeout: int = RENDER_TIMEOUT,
37
+ ) -> str:
38
+ """
39
+ 渲染 HyperFrames 视频项目
40
+
41
+ Args:
42
+ project_dir: 项目目录路径。默认为当前工作空间
43
+ output: 输出视频路径。默认保存在 renders/ 目录
44
+ fps: 帧率,可选 24/30/60。默认 30
45
+ quality: 渲染质量。可选 draft(快速迭代)/ standard(审阅)/ high(最终交付)
46
+ format: 输出格式。mp4 或 webm(webm 支持透明背景)
47
+ composition: 只渲染指定的 composition 文件(相对于项目目录的路径)
48
+ workers: 并行工作进程数,可选 1-8 或 auto。默认 auto
49
+ gpu: 启用 GPU 加速编码(默认关闭)
50
+ docker: 使用 Docker 可重现构建(默认关闭)
51
+ strict: lint 错误时中止渲染(默认关闭)
52
+ strict_all: lint 错误和警告时都中止(默认关闭)
53
+ timeout: 渲染超时秒数,默认 600
54
+
55
+ Returns:
56
+ 渲染结果输出信息
57
+ """
58
+ args = ["render"]
59
+
60
+ if output:
61
+ args.extend(["--output", output])
62
+
63
+ if fps:
64
+ if fps not in (24, 30, 60):
65
+ return f"❌ 无效帧率: {fps}。可选值: 24, 30, 60"
66
+ args.extend(["--fps", str(fps)])
67
+
68
+ if quality:
69
+ if quality not in ("draft", "standard", "high"):
70
+ return "❌ 无效质量值。可选: draft, standard, high"
71
+ args.extend(["--quality", quality])
72
+
73
+ if format:
74
+ if format not in ("mp4", "webm"):
75
+ return "❌ 无效格式。可选: mp4, webm"
76
+ args.extend(["--format", format])
77
+
78
+ if composition:
79
+ args.extend(["--composition", composition])
80
+
81
+ if workers is not None:
82
+ w = str(workers)
83
+ if w not in ("auto", "1", "2", "3", "4", "5", "6", "7", "8"):
84
+ return "❌ 无效 workers 值。可选: auto, 1-8"
85
+ args.extend(["--workers", w])
86
+
87
+ if gpu:
88
+ args.append("--gpu")
89
+
90
+ if docker:
91
+ args.append("--docker")
92
+
93
+ if strict:
94
+ args.append("--strict")
95
+
96
+ if strict_all:
97
+ args.append("--strict-all")
98
+
99
+ workspace = find_workspace() if not project_dir else project_dir
100
+ result = await run_hyperframes(args, cwd=workspace, timeout=timeout)
101
+
102
+ if result["success"]:
103
+ return f"✅ 渲染成功\n{result['stdout']}"
104
+ else:
105
+ return f"❌ 渲染失败\n{result['stderr']}"
@@ -0,0 +1,168 @@
1
+ """
2
+ hyperframes_system — 系统管理工具
3
+
4
+ 功能简述:
5
+ 封装 doctor / info / upgrade / benchmark / compositions 等管理类命令。
6
+ 用于检测环境、获取版本信息、列出 composition、跑基准测试等。
7
+
8
+ 主要方法清单:
9
+ - register_tools(mcp): 注册 hyperframes_doctor / hyperframes_info / 等
10
+ """
11
+
12
+ from typing import Optional
13
+
14
+ from ..cli_executor import run_hyperframes, find_workspace, check_environment
15
+
16
+
17
+ def register_tools(mcp) -> None:
18
+ """注册系统管理相关的 MCP 工具"""
19
+
20
+ @mcp.tool(
21
+ name="hyperframes_doctor",
22
+ description="检测 HyperFrames 运行环境(Node.js, FFmpeg, Chrome 等)。渲染前建议先运行。"
23
+ )
24
+ async def hyperframes_doctor(
25
+ project_dir: Optional[str] = None,
26
+ ) -> str:
27
+ """
28
+ 检测运行环境
29
+
30
+ Args:
31
+ project_dir: 项目目录。不指定则检查全局环境
32
+
33
+ Returns:
34
+ 环境检测结果
35
+ """
36
+ env_check = await check_environment()
37
+ lines = ["🔍 HyperFrames 环境检测\n"]
38
+ lines.append(f" Node.js: {'✅' if env_check['node_ok'] else '❌'} {env_check['node_version']}")
39
+ lines.append(f" npx: {'✅' if env_check['npx_ok'] else '❌'}")
40
+ lines.append(f" FFmpeg: {'✅' if env_check['ffmpeg_ok'] else '❌'} {env_check['ffmpeg_version']}")
41
+
42
+ if not env_check["all_ok"]:
43
+ lines.append("\n⚠️ 环境不完整,请安装缺失依赖:")
44
+ if not env_check["node_ok"]:
45
+ lines.append(" - Node.js >= 22: https://nodejs.org")
46
+ if not env_check["ffmpeg_ok"]:
47
+ lines.append(" - FFmpeg: brew install ffmpeg / apt install ffmpeg")
48
+ if not env_check["npx_ok"]:
49
+ lines.append(" - npx: npm install -g npx")
50
+
51
+ # 也跑一下 hyperframes doctor
52
+ workspace = find_workspace() if not project_dir else project_dir
53
+ hf_result = await run_hyperframes(["doctor"], cwd=workspace, timeout=30)
54
+ if hf_result["stdout"]:
55
+ lines.append(f"\n--- HyperFrames Doctor ---\n{hf_result['stdout']}")
56
+
57
+ return "\n".join(lines)
58
+
59
+ @mcp.tool(
60
+ name="hyperframes_info",
61
+ description="获取 HyperFrames 版本和环境详细信息。"
62
+ )
63
+ async def hyperframes_info(
64
+ project_dir: Optional[str] = None,
65
+ ) -> str:
66
+ """
67
+ 获取版本和环境信息
68
+
69
+ Args:
70
+ project_dir: 项目目录路径
71
+
72
+ Returns:
73
+ 版本和环境信息
74
+ """
75
+ result = await run_hyperframes(
76
+ ["info"],
77
+ cwd=find_workspace() if not project_dir else project_dir,
78
+ )
79
+ if result["success"]:
80
+ return result["stdout"]
81
+ else:
82
+ return f"❌ 获取信息失败\n{result['stderr']}"
83
+
84
+ @mcp.tool(
85
+ name="hyperframes_upgrade",
86
+ description="检查 HyperFrames 是否有更新版本。"
87
+ )
88
+ async def hyperframes_upgrade(
89
+ check_only: bool = True,
90
+ json_output: bool = True,
91
+ ) -> str:
92
+ """
93
+ 检查 HyperFrames 版本更新
94
+
95
+ Args:
96
+ check_only: 仅检查不升级(默认 True)
97
+ json_output: JSON 格式输出(默认 True,适合 AI 解析)
98
+
99
+ Returns:
100
+ 版本更新信息
101
+ """
102
+ args = ["upgrade"]
103
+ if check_only:
104
+ args.append("--check")
105
+ if json_output:
106
+ args.extend(["--check", "--json"])
107
+
108
+ result = await run_hyperframes(args)
109
+
110
+ if result["success"]:
111
+ return result["stdout"]
112
+ else:
113
+ return f"❌ 检查更新失败\n{result['stderr']}"
114
+
115
+ @mcp.tool(
116
+ name="hyperframes_compositions",
117
+ description="列出 HyperFrames 项目中的所有 composition 文件。"
118
+ )
119
+ async def hyperframes_compositions(
120
+ project_dir: Optional[str] = None,
121
+ ) -> str:
122
+ """
123
+ 列出项目中的 composition 文件
124
+
125
+ Args:
126
+ project_dir: 项目目录路径
127
+
128
+ Returns:
129
+ composition 列表
130
+ """
131
+ result = await run_hyperframes(
132
+ ["compositions"],
133
+ cwd=find_workspace() if not project_dir else project_dir,
134
+ )
135
+ if result["success"]:
136
+ return f"📄 Composition 列表:\n{result['stdout']}"
137
+ else:
138
+ return f"❌ 获取 composition 列表失败\n{result['stderr']}"
139
+
140
+ @mcp.tool(
141
+ name="hyperframes_benchmark",
142
+ description="对 HyperFrames 项目运行渲染基准测试。"
143
+ )
144
+ async def hyperframes_benchmark(
145
+ composition: Optional[str] = None,
146
+ project_dir: Optional[str] = None,
147
+ ) -> str:
148
+ """
149
+ 运行渲染性能基准测试
150
+
151
+ Args:
152
+ composition: 指定的 composition 文件路径(相对于项目目录)
153
+ project_dir: 项目目录路径
154
+
155
+ Returns:
156
+ 基准测试结果
157
+ """
158
+ args = ["benchmark"]
159
+ if composition:
160
+ args.append(composition)
161
+
162
+ workspace = find_workspace() if not project_dir else project_dir
163
+ result = await run_hyperframes(args, cwd=workspace, timeout=300)
164
+
165
+ if result["success"]:
166
+ return f"📊 基准测试结果:\n{result['stdout']}"
167
+ else:
168
+ return f"❌ 基准测试失败\n{result['stderr']}"
@@ -0,0 +1,8 @@
1
+ Metadata-Version: 2.4
2
+ Name: timeverse-hyperframes-mcp
3
+ Version: 0.1.0
4
+ Summary: MCP server wrapping HyperFrames CLI — turn HTML/CSS/JS into MP4 videos
5
+ Requires-Python: >=3.11
6
+ Requires-Dist: mcp>=1.0.0
7
+ Requires-Dist: httpx>=0.27.0
8
+ Requires-Dist: pydantic>=2.0.0
@@ -0,0 +1,19 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/timeverse_hyperframes_mcp/__init__.py
4
+ src/timeverse_hyperframes_mcp/__main__.py
5
+ src/timeverse_hyperframes_mcp/cli_executor.py
6
+ src/timeverse_hyperframes_mcp/server.py
7
+ src/timeverse_hyperframes_mcp.egg-info/PKG-INFO
8
+ src/timeverse_hyperframes_mcp.egg-info/SOURCES.txt
9
+ src/timeverse_hyperframes_mcp.egg-info/dependency_links.txt
10
+ src/timeverse_hyperframes_mcp.egg-info/entry_points.txt
11
+ src/timeverse_hyperframes_mcp.egg-info/requires.txt
12
+ src/timeverse_hyperframes_mcp.egg-info/top_level.txt
13
+ src/timeverse_hyperframes_mcp/tools/__init__.py
14
+ src/timeverse_hyperframes_mcp/tools/init.py
15
+ src/timeverse_hyperframes_mcp/tools/lint.py
16
+ src/timeverse_hyperframes_mcp/tools/media.py
17
+ src/timeverse_hyperframes_mcp/tools/preview.py
18
+ src/timeverse_hyperframes_mcp/tools/render.py
19
+ src/timeverse_hyperframes_mcp/tools/system.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ timeverse-hyperframes-mcp = timeverse_hyperframes_mcp.server:main
@@ -0,0 +1,3 @@
1
+ mcp>=1.0.0
2
+ httpx>=0.27.0
3
+ pydantic>=2.0.0