@motionharness/bridge-davinci 0.0.23 → 0.0.25

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.
package/README.md CHANGED
@@ -1,9 +1,11 @@
1
- # Motion Harness 桥接组件(Motion Harness Bridge Component)
1
+ # MotionHarness 桥接组件(MotionHarness Bridge Component)
2
2
 
3
- 素材池原素材(`MediaPoolItem`)通过 `sourceId + mediaPoolItemId` 关联 Motion Harness 工程。时间线片段只是操作入口:菜单从所选片段取得原素材,侧栏从实际输入视频核对已有素材关联。同一原素材的复制、裁切及多轨道引用打开同一工程、一起更新。时间线承载普通视频,动效源码仍在 Motion Harness 中编辑。主 CLI 提供 `mh bridge davinci`,Agent 同时使用达芬奇官方 MCP 处理实拍剪辑、音轨和原生变速。组件不启动另一套 MCP 服务。安装组件时一并安装固定菜单、简洁小窗和侧栏 OFX;给时间线片段自动附加 OFX 尚未提供。
3
+ 素材池原素材(`MediaPoolItem`)通过 `sourceId + mediaPoolItemId` 关联 MotionHarness 工程。时间线片段只是操作入口:菜单从所选片段取得原素材,侧栏从实际输入视频核对已有素材关联。同一原素材的复制、裁切及多轨道引用打开同一工程、一起更新。时间线承载普通视频,动效源码仍在 MotionHarness 中编辑。主 CLI 提供 `mh bridge davinci`,Agent 同时使用达芬奇官方 MCP 处理实拍剪辑、音轨和原生变速。组件不启动另一套 MCP 服务。安装组件时一并安装固定菜单、简洁小窗和侧栏 OFX;给时间线片段自动附加 OFX 尚未提供。
4
4
 
5
5
  ## 支持范围
6
6
 
7
+ 桥接不设置达芬奇最低版本,也不按版本号、构建号或脚本进程的 CPU 架构拦截操作。旧版本只要能完成所需接口调用即可使用;缺少接口或调用失败时返回实际错误。`doctor` 与连接状态中的版本号仅用于排查问题。当前完整安装包仍只提供 macOS 入口组件。
8
+
7
9
  Studio 可发送和更新普通视频,支持透明合成;更新时核对源规格、片段状态与内容版本。Resolve 使用渲染完成的视频文件,不依赖 Studio 会话持续运行。
8
10
 
9
11
  当前 macOS 安装包包含桥接、固定菜单、简洁状态窗口和侧栏 OFX。侧栏读取效果自身的源视频路径,并核对当前工程的素材池身份及关联元数据,不依赖时间线选择。更新采用每个关联独立的固定视频路径;历史版本独立保存。旧关联首次更新会迁移到固定路径,旧效果若仍缓存旧路径会停止操作:保存并重新打开工程,或重新附加效果后再试,也可继续使用固定菜单。
@@ -35,13 +37,13 @@ mh bridge davinci uninstall
35
37
 
36
38
  ## 侧栏入口
37
39
 
38
- 运行 `mh bridge davinci install` 会一并安装菜单、小窗和 OFX。OFX 默认安装到 `/Library/OFX/Plugins`;系统目录需要权限时会请求 macOS 管理员授权,取消或失败会报告未完成,不能当作完整安装成功。安装后保存工程并重启 Resolve,给普通视频附加 Motion Harness 桥接组件。侧栏提供“编辑 Motion Harness 工程”“更新此素材”“查看状态”和“更多…”。更新直接核对并固定目标,复用已有更新流程,影响该素材在当前工程中的全部引用。立即显示状态提示,重复点击复用正在进行的请求;不需要先打开管理窗口。效果中保存的 ID 和当前时间线选择都不能替代源路径、素材池身份及元数据的交叉核对,无法唯一确定时停止。
40
+ 运行 `mh bridge davinci install` 会一并安装菜单、小窗和 OFX。OFX 默认安装到 `/Library/OFX/Plugins`;系统目录需要权限时会请求 macOS 管理员授权,取消或失败会报告未完成,不能当作完整安装成功。安装后保存工程并重启 Resolve,给普通视频附加 MotionHarness 桥接组件。侧栏提供“编辑 MotionHarness 工程”“更新此素材”“查看状态”和“更多…”。更新直接核对并固定目标,复用已有更新流程,影响该素材在当前工程中的全部引用。立即显示状态提示,重复点击复用正在进行的请求;不需要先打开管理窗口。效果中保存的 ID 和当前时间线选择都不能替代源路径、素材池身份及元数据的交叉核对,无法唯一确定时停止。
39
41
 
40
42
  自动附加、自动恢复被移除的效果和“不可单独删除”不在当前范围;用户按图文步骤自行添加侧栏,缺少视觉入口时仍可从固定菜单编辑、更新片段。新旧入口协议在升级期间并存,旧二进制仍可能给出过期路径提示,需重新启动 Resolve 才会加载新的原生入口。
41
43
 
42
44
  ## Studio 流程
43
45
 
44
- 日常操作直接使用侧栏的编辑、更新和状态按钮。没有添加侧栏 OFX 时,选中普通视频后仍可从「工作区 → 脚本 → Utility → Motion Harness 桥接组件」使用“编辑工程”和“更新到达芬奇”。独立的“管理所选片段”菜单已移除;升级仅清理未被用户修改的自有旧菜单。
46
+ 日常操作直接使用侧栏的编辑、更新和状态按钮。没有添加侧栏 OFX 时,选中普通视频后仍可从「工作区 → 脚本 → Utility → MotionHarness 桥接组件」使用“编辑工程”和“更新到达芬奇”。独立的“管理所选片段”菜单已移除;升级仅清理未被用户修改的自有旧菜单。
45
47
 
46
48
  组件安装后,Studio 导出面板并列显示“发送到达芬奇”。未安装时隐藏该按钮,旁边的说明提供安装命令。先打开目标 Resolve 时间线,再选择导出格式发送。已关联的源在同一位置提供“更新到达芬奇”。发送前先显示工程、时间线、空闲视频轨和播放头位置;更新前显示实际目标与本次核对的引用数量。确认后按该目标在后台完成渲染、完整解码验证和导入;动效内容或目标剪辑改变会报冲突,不覆盖用户操作。
47
49
 
@@ -54,7 +56,7 @@ MP4/H.264 用于不透明视频。MOV/ProRes 4444 或 4444 XQ 支持 straight al
54
56
  ## Agent 从 Resolve 开始
55
57
 
56
58
  1. 用达芬奇官方 MCP 读取明确的工程和时间线,完成实拍剪辑,并取得插入目标。
57
- 2. 用主 CLI 创建或修改可编辑 Motion Harness 工程,匹配输出尺寸、帧率和时长。
59
+ 2. 用主 CLI 创建或修改可编辑 MotionHarness 工程,匹配输出尺寸、帧率和时长。
58
60
  3. 可先调用 `mh bridge davinci action prepare --project <源目录> --json '{"operation":"send","idempotencyKey":"..."}'` 获取固定目标及版本条件,将返回的 `request` 原样交给 `send`,并保留同一 `--project`。无需人工确认的 Agent 流程也可直接调用 `mh bridge davinci send --project <源目录> --json '<请求>'`。请求至少包含 `idempotencyKey`,可包含 `export`(与 `mh render` 相同的格式/编码/透明度等选项)以及 `scope`、`timelineId`、`track`、`recordFrame`。
59
61
  4. 用 `mh bridge davinci task --json '{"taskId":"..."}'` 查询完成结果。也可传 `idempotencyKey` 恢复丢失的任务 ID。
60
62
  5. 用 Resolve MCP 对普通视频做原生剪辑。修改动效源后,调用 `update`,指定 `bindingId`、可选 `expectedRevision` 和新的 `idempotencyKey`。
@@ -67,7 +69,7 @@ MP4/H.264 用于不透明视频。MOV/ProRes 4444 或 4444 XQ 支持 straight al
67
69
 
68
70
  ## 入口与历史版本
69
71
 
70
- macOS 原生包安装“编辑工程”和“更新到达芬奇”两个菜单脚本,入口为 Resolve「工作区 → 脚本 → Utility → Motion Harness 桥接组件」。主 CLI `edit` 可按选中片段的稳定关联打开源工程。
72
+ macOS 原生包安装“编辑工程”和“更新到达芬奇”两个菜单脚本,入口为 Resolve「工作区 → 脚本 → Utility → MotionHarness 桥接组件」。主 CLI `edit` 可按选中片段的稳定关联打开源工程。
71
73
 
72
74
  侧栏“更多…”按效果自身的源路径固定素材身份,后来切换选择不会把操作转给另一段素材。窗口直接提供该关联确实应用过的历史版本、重新定位源目录和丢失元数据时的关联修复。点击“创建独立副本…”后才扫描引用并选择具体片段;日常打开管理窗口不列举全部时间线实例。目录面板只在明确点击相应操作后出现。恢复版本前说明影响该素材的全部引用,独立副本则明确只改变一个时间线实例。结果不明时先核对原任务,再明确选择继续原任务;原任务可能包含多个目标,不会被管理窗口缩成当前一段。
73
75
 
@@ -104,7 +106,7 @@ pnpm --filter @motionharness/bridge-davinci test
104
106
 
105
107
  用 `pnpm --filter @motionharness/bridge-davinci package` 在根目录 `.tmp/` 制作独立安装包,不发布。构建生成自包含的 `dist/runner.mjs` 和文件摘要清单。公开包只带 runner、受支持的 Resolve 脚本和入口资源,不包含验证日志、机器路径、编辑器或另一套渲染器。临时验收文件统一放在仓库根 `.tmp/`;自动测试与真实 Resolve 验收分别记录。
106
108
 
107
- macOS 原生构建使用 `node packages/bridge/davinci/native/build.mjs`,生成通用 arm64/x86_64 的 `HotionHarnessStatus.app`、`HotionHarness.ofx.bundle` 和权限准备程序 `HotionHarnessInstall`。需要 Apple 命令行构建工具和 Resolve OpenFX 开发 SDK;`HOTION_OFX_SDK` 可指定 SDK 目录。二进制只输出到 `.tmp/`,不写入源码目录。
109
+ macOS 原生构建使用 `node packages/bridge/davinci/native/build.mjs`,生成通用 arm64/x86_64 的 `MotionHarnessBridge.app`、`HotionHarness.ofx.bundle` 和权限准备程序 `MotionHarnessInstall`。需要 Apple 命令行构建工具和 Resolve OpenFX 开发 SDK;`HOTION_OFX_SDK` 可指定 SDK 目录。二进制只输出到 `.tmp/`,不写入源码目录。
108
110
 
109
111
  默认 `package` 自动构建这些原生资源,也可设置 `MH_BRIDGE_NATIVE_BUILD=<完整构建目录>` 复用构建。缺少任一原生组件会停止打包。旧 `--experimental-ofx` 参数兼容保留,但不再改变包内容。开发机需要 SDK 和编译工具,用户安装发布包无需这些构建依赖。
110
112
 
@@ -112,12 +114,12 @@ macOS 原生构建使用 `node packages/bridge/davinci/native/build.mjs`,生
112
114
 
113
115
  每个关联使用 `artifacts/media/<bindingId>/<文件名>` 作为播放文件,`artifacts/<artifactId>/` 保存独立的历史版本。渲染和完整视频校验成功后,先记录任务的目标、旧版本和新版本,再由原生脚本核对绑定的原素材身份、关联和媒体规格,在同一目录原子替换播放文件,并通过 `RelinkClips` 刷新。不会覆盖历史文件或使用硬链接。渲染失败保留旧画面;发布后结果不明时保留原任务,不自动重新提交。通过管理窗口或 `recover` 核对已应用版本,只有原目标仍匹配才允许继续。
114
116
 
115
- 固定路径不保证所有未知宿主版本和代理组合的行为。组件沿用已验证宿主范围,已关联代理或无法核对身份、版本及文件完整性的原素材仍拒绝更新。时间线结构检查只用于插入、独立实例副本和最终导出等操作。普通视频暂停时可能保留旧帧,播放或移动播放头后才显示新画面;定格画面也可能保留旧版本。定格不因此阻止更新。状态小窗及管理窗口以一行次要文字提示“预览未刷新请播放;定格可能保留旧画面。”任务完成代表视频文件与关联已更新,不保证宿主预览已经重绘。管理窗口保留恢复版本、重新定位、修复关联等低频功能。
117
+ 固定路径不保证所有代理组合的行为。已关联代理或无法核对身份、内容版本及文件完整性的原素材仍拒绝更新。时间线结构检查只用于插入、独立实例副本和最终导出等操作。普通视频暂停时可能保留旧帧,播放或移动播放头后才显示新画面;定格画面也可能保留旧版本。定格不因此阻止更新。状态小窗及管理窗口以一行次要文字提示“预览未刷新请播放;定格可能保留旧画面。”任务完成代表视频文件与关联已更新,不保证宿主预览已经重绘。管理窗口保留恢复版本、重新定位、修复关联等低频功能。
116
118
 
117
119
  ### 名称与语言兼容
118
120
 
119
121
  侧栏显示本地连接状态,缺少 CLI、配置或状态窗口时会在首次点击立即提示。通过 npm 安装时保存固定 CLI 启动入口,每次操作自动定位当前原生程序,CLI 升级或平台包位置变化后无需重装 OFX。点击“修复连接”可刷新已有启动配置并检查达芬奇连接,不重装 OFX、不重启达芬奇,也不改素材关联。组件文件缺失或配置被用户修改时,提示运行 `mh bridge davinci install` 修复。
120
122
 
121
- 组件在中文界面显示为 **Motion Harness 桥接组件**,英文显示为 **Motion Harness Bridge Component**。原生侧栏与小窗口跟随 macOS 首选中英文,固定菜单在安装或修复时使用同一语言;Studio 的图文帮助跟随 Studio 当前语言。`MH_UI_LOCALE=zh-CN` 或 `MH_UI_LOCALE=en` 可显式指定原生入口语言。更改系统语言后,重新安装组件并重启 Resolve 即可刷新菜单及侧栏名称。
123
+ 组件在中文界面显示为 **MotionHarness 桥接组件**,英文显示为 **MotionHarness Bridge Component**。原生侧栏与小窗口跟随 macOS 首选中英文,固定菜单在安装或修复时使用同一语言;Studio 的图文帮助跟随 Studio 当前语言。`MH_UI_LOCALE=zh-CN` 或 `MH_UI_LOCALE=en` 可显式指定原生入口语言。更改系统语言后,重新安装组件并重启 Resolve 即可刷新菜单及侧栏名称。
122
124
 
123
125
  旧版本误拼写对应的 OFX 插件 ID、参数键、二进制文件名、通知标识和 `Application Support/Hotion Harness` 配置路径继续保留,以兼容已有工程、入口和安装记录。`legacy-inspector-v1.lua` 是旧入口逐字节识别所需的原始模板,不用于生成新的界面。升级只移除已登记且未修改的旧菜单,保留用户定制内容。
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "name": "@motionharness/bridge-davinci",
4
- "version": "0.0.23",
4
+ "version": "0.0.25",
5
5
  "protocol": 1,
6
- "cliVersion": "0.0.23",
6
+ "cliVersion": "0.0.25",
7
7
  "files": [
8
8
  {
9
9
  "path": "dist/inspector_runtime.py",
10
- "sha256": "c02486992b71d8ecb506f9ede4c4d6bfcf32fcea4fcc00da6011e25b28b2dd0d"
10
+ "sha256": "1c63b610585ecdcda3b433a8e1f0681b19095c1ee13cd459baaddccb2ec67423"
11
11
  },
12
12
  {
13
13
  "path": "dist/instance_runtime.py",
14
- "sha256": "cdffb0aedf244a61991c378feed419f406dbf2f0fa635d33d24aa0b3381fb1ec"
14
+ "sha256": "339a0d466e0d818da81609181e0722a3199736b2cc3c9dcdfab599948459f069"
15
15
  },
16
16
  {
17
17
  "path": "dist/intrinsic_runtime.py",
@@ -19,15 +19,15 @@
19
19
  },
20
20
  {
21
21
  "path": "dist/legacy_conversion.py",
22
- "sha256": "3c595b7f5a34611d20f59bdd8181414b5191aadd27fee02667dfdd6c59f6d464"
22
+ "sha256": "b0c58b17f978bc742dc18290f673345dcc9b4e9c10d6e10274ee1a026d6daf20"
23
23
  },
24
24
  {
25
25
  "path": "dist/resolve_rpc.py",
26
- "sha256": "f10440c19783605f0aec00b206a6520d7a3dafd6f28ddf307cae6b7e08802691"
26
+ "sha256": "36555812e890d12407097051828c6a6539ad81fa79805100cf08960c7af0f607"
27
27
  },
28
28
  {
29
29
  "path": "dist/runner.mjs",
30
- "sha256": "8a7c2c89b465ed32ce0e3e275edf8e4e8b0b2c5cd61b01dbf7690daaf2e235d5"
30
+ "sha256": "0743b7f2543514c902a9eeeafabd3617ca4b12223fe089efe0e8c014be2030b4"
31
31
  },
32
32
  {
33
33
  "path": "dist/runtime_io.py",
@@ -47,66 +47,71 @@
47
47
  },
48
48
  {
49
49
  "path": "README.md",
50
- "sha256": "a60beff9902034f0d59739ae714659feb00c7e4e2bb747c8b36d1ed25bec6451"
50
+ "sha256": "8f459a50a40360b0c6f99767dd44ee42dd8d4c67deeb8f32a31a6d111a55ce31"
51
51
  },
52
52
  {
53
53
  "path": "resources/HotionHarness.ofx.bundle/Contents/Info.plist",
54
- "sha256": "a5316a00995683460edc87123ad958425cd1be36a2dc64edd26b1063b6acefed",
54
+ "sha256": "27315c51f5fdd00196b3bd7723c96b10fa12d3dfe18a825715cfe1559820bb9b",
55
55
  "executable": false
56
56
  },
57
57
  {
58
58
  "path": "resources/HotionHarness.ofx.bundle/Contents/MacOS/HotionHarness.ofx",
59
- "sha256": "750369116eac4aec476a903685690bb488088f881f82d7b3ec0596e9b38a1aa2",
59
+ "sha256": "7bc3526ebc45c75c7c354c9df4468ba59df3cac57d0b361f44e7d9489d5d702f",
60
60
  "executable": true
61
61
  },
62
62
  {
63
- "path": "resources/HotionHarnessInstall",
64
- "sha256": "39213a6e45578f0bb9f0c49bd6dd12c5402cf687b8eba2c6044cc4e1a20c5969",
65
- "executable": true
63
+ "path": "resources/legacy-forwarder.lua",
64
+ "sha256": "179dcaad0538a663e58d3a3fe56b34be6e9d3d2dbac9aea5bfa094363cb54366",
65
+ "executable": false
66
66
  },
67
67
  {
68
- "path": "resources/HotionHarnessStatus.app/Contents/Info.plist",
69
- "sha256": "ec9e19f3f74cbc09c076382a1fe49c2553a8592887680449d8645ed4adca3fd9",
68
+ "path": "resources/legacy-inspector-v1.lua",
69
+ "sha256": "808965d5fabc6b9b457ef4b08fa4635e47d1efebc74e0e3d036e73ca2ef75ac5",
70
70
  "executable": false
71
71
  },
72
72
  {
73
- "path": "resources/HotionHarnessStatus.app/Contents/MacOS/HotionHarnessStatus",
74
- "sha256": "8894fd5809549ab4281adc525d447d0c847c8720dd5705e4df4be40098cacd08",
75
- "executable": true
73
+ "path": "resources/menu-entry.py",
74
+ "sha256": "311675623e03bcbaed56bc64dd59ab5c714ff09673f5c857e537e846e3e95d8e",
75
+ "executable": false
76
76
  },
77
77
  {
78
- "path": "resources/HotionHarnessStatus.app/Contents/Resources/en.lproj/InfoPlist.strings",
79
- "sha256": "a2ace2734255bc9751b7ea734d7cf19b1d1386604b8cb838f0e529839846f419",
78
+ "path": "resources/MotionHarnessBridge.app/Contents/Info.plist",
79
+ "sha256": "f142b48473d4878381d18b7247d1e41c376d91733287614a575c8371dcc9af51",
80
80
  "executable": false
81
81
  },
82
82
  {
83
- "path": "resources/HotionHarnessStatus.app/Contents/Resources/zh-Hans.lproj/InfoPlist.strings",
84
- "sha256": "834876e910caa01c120735fc3cb927db473014cc336e4977aae8d390591e1be2",
85
- "executable": false
83
+ "path": "resources/MotionHarnessBridge.app/Contents/MacOS/MotionHarnessBridge",
84
+ "sha256": "7b3e969244827d9ad1f565fc8962862fecf9cc98fb3efc2010a7963493815ccf",
85
+ "executable": true
86
86
  },
87
87
  {
88
- "path": "resources/legacy-forwarder.lua",
89
- "sha256": "342b396ac9fd68dbb9e8cd166c2e99b8d0740c7dc01cac3a5064d6fd092b8900",
88
+ "path": "resources/MotionHarnessBridge.app/Contents/Resources/en.lproj/InfoPlist.strings",
89
+ "sha256": "db871b4c6750a7f7734017bc28b14186d8dae5203d123aec68e933c18bb4882e",
90
90
  "executable": false
91
91
  },
92
92
  {
93
- "path": "resources/legacy-inspector-v1.lua",
94
- "sha256": "808965d5fabc6b9b457ef4b08fa4635e47d1efebc74e0e3d036e73ca2ef75ac5",
93
+ "path": "resources/MotionHarnessBridge.app/Contents/Resources/zh-Hans.lproj/InfoPlist.strings",
94
+ "sha256": "bfd7759e34d4ba11563fa27816257b38b6b4b881073bde1c91e659f9483a55f8",
95
95
  "executable": false
96
96
  },
97
97
  {
98
- "path": "resources/menu-entry.py",
99
- "sha256": "15f8dafb4d3c4a8020007b20764d4e3c1700f9585be107769efefd8ba4877e94",
100
- "executable": false
98
+ "path": "resources/MotionHarnessInstall",
99
+ "sha256": "97789436532ec7ea46ed297194e6fcc37ccba250874d57839a964ad446be3b11",
100
+ "executable": true
101
101
  },
102
102
  {
103
103
  "path": "resources/sidebar-help/en.html",
104
- "sha256": "838c7af75c332e6427d78c97a67d4cd44f142633e97dc5200c2a079145d0d4cd",
104
+ "sha256": "c44eb1c5468091018ecfcb11e6b9cfbfb62e3ec29abb807d207fd76ef1f2b59b",
105
+ "executable": false
106
+ },
107
+ {
108
+ "path": "resources/sidebar-help/guide.css",
109
+ "sha256": "8a79036b37678a20178c055133481edd099002ff47d63e9cfe8ca1c7322cf0ba",
105
110
  "executable": false
106
111
  },
107
112
  {
108
113
  "path": "resources/sidebar-help/index.html",
109
- "sha256": "ad201ec81af3728ec4a3d0219ca55b5d00fdba2bacb694dcaf47652d368eb8a4",
114
+ "sha256": "5d6f07f6a652eabc1370f3f9bbc210cc94dde2f947f619efa0e922a84369e1c5",
110
115
  "executable": false
111
116
  },
112
117
  {
@@ -1,4 +1,4 @@
1
- """Conservative readback for the experimental, image-routing-only MH macro.
1
+ """Conservative readback for the experimental, image-routing-only MotionHarness macro.
2
2
 
3
3
  No module import connects to Resolve. Native acceptance is deliberately separate
4
4
  from this graph identity check; normal sync retains its previous support boundary.
@@ -60,14 +60,14 @@ def graph(comp, identity):
60
60
  # tools-only list. Accept exactly that one documented child in either form.
61
61
  actual = {tool_name(t): tool_id(t) for t in tools}
62
62
  if len(tools) != len(actual) or actual not in (expected, {**expected, 'MHBridgePipe': 'PipeRouter'}):
63
- raise ValueError('not the isolated MH entry composition')
63
+ raise ValueError('not the isolated MotionHarness entry composition')
64
64
  by_name = {tool_name(t): t for t in tools}
65
65
  macro = by_name['MHBridge']
66
66
  children = list((macro.GetChildrenList(False) or {}).values())
67
67
  if len(children) != 1 or tool_id(children[0]) != 'PipeRouter' or tool_name(children[0]) != 'MHBridgePipe':
68
68
  raise ValueError('the macro contains an unknown image operation')
69
69
  if not connected_to(macro, 'MediaIn1') or not (connected_to(by_name['MediaOut1'], 'MHBridge') or connected_to(by_name['MediaOut1'], 'MHBridgePipe')):
70
- raise ValueError('the native image route differs from the MH template')
70
+ raise ValueError('the native image route differs from the MotionHarness template')
71
71
  own = settings(macro)
72
72
  for group, key, source in (('Inputs', 'MainInput1', 'Input'), ('Outputs', 'MainOutput1', 'Output')):
73
73
  link = own.get(group, {}).get(key, {})
@@ -84,7 +84,7 @@ def graph(comp, identity):
84
84
 
85
85
 
86
86
  def read_entry(item):
87
- """An edited/foreign graph is unknown, even if it retains an MH display name."""
87
+ """An edited/foreign graph is unknown, even if it retains a MotionHarness display name."""
88
88
  try:
89
89
  if item.GetFusionCompCount() != 1: return None
90
90
  comp = item.GetFusionCompByIndex(1)
@@ -362,7 +362,7 @@ class _Transaction:
362
362
  properties = self.old_media.GetClipProperty()
363
363
  percentage = original["target"]["speed"].get("Percentage")
364
364
  spec = self.params["outputSpec"]
365
- self.require(original["timeline"].get("validatedHost") and original["timeline"]["fps"] == {"num": 30, "den": 1}
365
+ self.require(original["timeline"]["fps"] == {"num": 30, "den": 1}
366
366
  and not original["timeline"].get("dropFrame") and float(properties.get("FPS", 0)) == 30
367
367
  and spec.get("fps") == {"num": 30, "den": 1}, "UNSUPPORTED_FPS", "独立实例原生操作当前仅验收了素材与时间线均为 30 fps。")
368
368
  self.require(target.get("kind") == "video" and not target["unsupported"] and not target.get("trackLocked")
@@ -276,7 +276,7 @@ def _plan(resolve, project, scope, params, api):
276
276
  continue
277
277
  reasons = []
278
278
  if not entry:
279
- reasons.append(("legacy-identity-unrecognized", "不是完整识别的 Motion Harness 旧生成器,保持原结构。"))
279
+ reasons.append(("legacy-identity-unrecognized", "不是完整识别的 MotionHarness 旧生成器,保持原结构。"))
280
280
  candidate = {"itemId": item["id"], "name": item["name"], "track": item["track"], "startFrame": item["startFrame"], "endFrame": item["endFrame"]}
281
281
  if entry:
282
282
  identity = entry["identity"]
@@ -288,8 +288,6 @@ def _plan(resolve, project, scope, params, api):
288
288
  candidate.update(sourceIn=start, sourceOut=end)
289
289
  if any(identity.get(key) != value for key, value in scope.items()):
290
290
  reasons.append(("legacy-scope-conflict", "生成器身份不属于当前数据库和工程。"))
291
- if not api["validated_host"](resolve):
292
- reasons.append(("legacy-host-unverified", "当前宿主版本或平台未验证生成器帧边界。"))
293
291
  props = media["properties"]
294
292
  if (not all(isinstance(item.get(key), dict) for key in ("properties", "speed", "fades", "markers", "version"))
295
293
  or not isinstance(item.get("enabled"), bool) or not isinstance(item.get("timelineBlanking"), bool)):
@@ -415,7 +413,7 @@ def convert(resolve, project, scope, params, api):
415
413
  if name:
416
414
  require(name not in names, "TARGET_OCCUPIED", "隔离副本名称已经存在,请选择新名称;未调用 DuplicateTimeline。")
417
415
  else:
418
- base = plan["name"] + " · Motion Harness 转换"
416
+ base = plan["name"] + " · MotionHarness 转换"
419
417
  name, suffix = base, 2
420
418
  while name in names:
421
419
  name = base + " " + str(suffix)
@@ -589,7 +587,7 @@ def convert(resolve, project, scope, params, api):
589
587
  and os.path.realpath(props["File Path"]) == os.path.realpath(replacement["filePath"])
590
588
  and file_digest(props["File Path"]) == replacement["sha256"] and not media.GetTimeline(),
591
589
  "APPLY_OUTCOME_UNKNOWN", "新视频的文件内容、规格或媒体解释不一致。")
592
- uses = [api["item_snapshot"](final_objects[mapping["newItemId"]], copied.GetUniqueId(), candidates[mapping["oldItemId"]]["track"], True)
590
+ uses = [api["item_snapshot"](final_objects[mapping["newItemId"]], copied.GetUniqueId(), candidates[mapping["oldItemId"]]["track"])
593
591
  for mapping in record["mappings"] if mapping["oldBindingId"] == old_binding]
594
592
  value = {"scope": scope, "projectName": project.GetName(), "mediaPoolItemId": media.GetUniqueId(), "path": props["File Path"],
595
593
  "metadata": media.GetThirdPartyMetadata(), "uses": uses, "usageScanComplete": False,