@volcengine/amk-editor 0.0.6 → 0.0.7-beta.7

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,5 +1,55 @@
1
1
  # @volcengine/amk-editor
2
2
  火山引擎 AI MediaKit 官方 Web 视频编辑器 SDK。
3
+
4
+ BytePlus 包的接入说明见 [README.byteplus.md](./README.byteplus.md)。
5
+
6
+ ## 字幕识别后端
7
+
8
+ 现有工具栏的字幕识别入口支持通过初始化配置切换后端:
9
+
10
+ ```ts
11
+ const editor = new AmkEditor({
12
+ container, projectId, endpoint,
13
+ toolbar: {
14
+ asr: { provider: 'maas' }, // 可选;火山默认 'asr-subtitles'
15
+ },
16
+ });
17
+ ```
18
+
19
+ - `asr-subtitles`:火山默认,沿用原来的字幕识别工具及参数。
20
+ - `maas`:视频先调用 `extract-audio`(`format: 'mp3'`),再调用 `call-maas-proxy`(`api: 'doubao.asr'`)。HTTP(S) MP3/WAV/OGG 音频直接识别;其他或无法从 URL 确认格式的音频先调用 `transcode-audio` 转为 MP3。
21
+ - 新链路不传 `media_output_destination`,中间音频使用临时 HTTP(S) 地址供模型读取,不写入工程素材库;所有请求仍经过配置的 `endpoint` / `getHeaders`。
22
+ - 返回 `utterances` 的毫秒时间戳会转换为原字幕逻辑使用的秒,并继续按素材裁剪范围、变速和时间线位置映射。`toolbar.builtInVisibility.asrSubtitle` 仍控制原入口显隐。
23
+ - 取消/关闭识别弹窗或销毁编辑器会停止本地等待、阻止后续阶段及字幕写入;已提交的远端任务不会因此撤销,仍可能产生费用。
24
+
25
+ 业务代理需允许 `extract-audio`、`transcode-audio`、`call-maas-proxy` 和任务查询。使用 MaaS 前需开通对应语音识别能力并完成 AMK 跨服务授权;源 URL 必须在任务执行期间可被服务端访问。BytePlus 默认使用 `maas`,不支持选择 `asr-subtitles`,海外接口和账号能力需单独联调。
26
+
27
+ 接口参考:[MaaS 模型代理](https://docs.volcengine.com/docs/Intelligentprocessing/call-maas-proxy-api?lang=zh)、[音频提取](https://docs.volcengine.com/docs/Intelligentprocessing/SubmitAudioExtractionTaskAPI?lang=zh)。
28
+
29
+ ## 素材 Source 与播放地址
30
+
31
+ 素材入库时,AMK 返回的 `tos://bucket/key`、`vod://space/id` 保留在 `source` 中;稳定的 `source_material_id` 也可用于补齐该资源身份。`url` 始终使用可播放的 HTTP(S) 地址,播放地址刷新不会覆盖资源 `source`。普通 HTTP(S) 素材沿用原来的 URL 处理逻辑。
32
+
33
+ 拖入时间线后,元素 `Source` 直接沿用素材 `source`,保存工程保留该值。导出使用工程中已保存的 `Source`,不再通过 `source_material_id` 或存储空间配置转换 TOS/VOD 协议;已有 HTTP(S) 轨道仍按原逻辑刷新播放地址,不自动迁移旧工程。
34
+
35
+ ## 素材上传并发
36
+
37
+ 通过 `material.uploadConcurrency` 设置同一编辑器的本地文件与临时 URL 转存并发上限:
38
+
39
+ ```ts
40
+ material: {
41
+ uploadConcurrency: 3,
42
+ // 可选;未提供自定义回调时,按现有规则使用内置上传。
43
+ onUploadFile: async file => uploadToYourService(file),
44
+ }
45
+ ```
46
+
47
+ 选择 10 个文件时先启动 3 个,每项上传、元信息补齐和入库完成或失败后再启动下一项;后台抽帧不占名额。连续选择多批文件也共用上限,已成功项立即显示,单项失败不阻塞后续文件。仅接受正整数(1 为串行),未配置保持原不限并发行为。销毁编辑器后排队任务不再启动,已开始的自定义请求不会被强制取消。
48
+
49
+ 该配置作用于 `onUploadFile`、SDK 内置本地上传,以及服务端标记为临时存储的 URL 素材转存;临时转存会按单 URL 调用 `onUploadUrlMaterial([url])`,未配置并发数时默认最多同时处理 5 条。普通 URL 导入仍按整批调用 `onUploadUrlMaterial(urls)`;临时素材转存调用 `onUploadUrlMaterial([url], { materials: [material] })`,业务可用原素材 `type`/`name` 识别无后缀地址;旧版 `onUploadMaterial(files)` 与系统素材导入的内部并发仍由宿主控制。本配置不是每秒 QPS 限速,也不改变单个文件内部的分片并发。
50
+
51
+ 配置并发上限后,本地上传与临时转存共用同一队列。临时素材跳过客户侧播放信息刷新,但可立即使用临时 HTTP(S) 地址抽帧并展示结果。抽帧任务状态和结果先缓存在内存,替换 PUT 成功后再按当前客户存储身份批量写回;转存失败时保留缓存等待后续重试。SDK 只扫描初始化已加载的素材和 `refreshMaterials()` 的结果,不会为等待临时素材重复请求素材列表。后续陈旧读取保留已提交绑定和抽帧结果,避免重复上传或抽帧。转存后的素材刷新不重建当前时间线预览节点。
52
+
3
53
  ## 获取当前合成画面
4
54
  ```ts
5
55
  await amkEditor.whenReady();
@@ -20,6 +70,7 @@ const editor = new AmkEditor({
20
70
  container,
21
71
  projectId: 'your-project-id',
22
72
  endpoint: 'https://your-backend.example.com',
73
+ source: 'your-app-name',
23
74
  // 可选:每次请求前动态获取,SDK 不解析或改写返回的 Header。
24
75
  getHeaders: async () => ({
25
76
  Authorization: `Bearer ${await getLatestToken()}`,
@@ -60,6 +111,13 @@ editor.requestMaterialImport('local', {
60
111
  // 从服务端重新拉取当前工程,并热更新素材与 Track(不写入撤销历史)。
61
112
  await editor.refreshProject();
62
113
 
114
+ // 只重新拉取全部素材(自动分页),刷新播放地址并更新素材面板;不刷新轨道或工程名。
115
+ const materials = await editor.refreshMaterials();
116
+
117
+ // 只读取工程接口并更新工程信息;当前同步名称/Header,并保留其他元信息。
118
+ const projectInfo = await editor.refreshProjectInfo();
119
+ console.log(projectInfo.name, projectInfo.description);
120
+
63
121
  // 从外部保存工程标题;保存成功后同步顶栏,并触发 header.onTitleUpdateSuccess。
64
122
  await editor.updateTitle('新的工程标题');
65
123
 
@@ -70,13 +128,60 @@ const exportTask = await editor.getTask('your-task-id');
70
128
  ```ts
71
129
  editor.destroy();
72
130
  ```
131
+
132
+ ### 内置 VOD 本地上传
133
+
134
+ SDK 可通过 `tt-uploader` 将本地视频、音频和图片直传火山引擎点播。长期
135
+ AK/SK 保留在宿主服务端,浏览器通过统一回调获取短期 Token;SDK 自动按
136
+ Vid 获取播放地址:
137
+
138
+ ```ts
139
+ const editor = new AmkEditor({
140
+ container,
141
+ projectId: 'your-project-id',
142
+ endpoint: 'https://your-backend.example.com',
143
+ source: 'your-app-name',
144
+ storage: {
145
+ media_output_destination: 'vod://your-space',
146
+ getUploadSTS: () => fetch('/api/vod/upload-token', {
147
+ method: 'POST',
148
+ }).then(response => response.json()),
149
+ },
150
+ });
151
+ ```
152
+
153
+ 服务端需返回带 `Vod:ApplyUploadInfo`、`Vod:CommitUploadInfo`、
154
+ `Vod:UpdateMediaPublishStatus` 和 `Vod:GetPlayInfo` 权限的短期 STS,不应下发长期 AK/SK。
155
+ 签发接口须由业务服务端鉴权、限流;发布权限不应向未授权访客开放。
156
+ SDK 使用该 STS 直传点播,仅在上传成功后发布 Vid,然后获取播放地址;
157
+ 普通播放地址刷新不再发布媒资,一批 VOD 素材刷新共用一次 STS,并按 Vid 去重查询。
158
+ 不再需要服务端播放地址代理。视频、音频和图片都通过点播 media
159
+ 通道取得 Vid;仅返回 Mid 的上传结果会报错,
160
+ 不会写入 AMK 工程。SDK 将 `vod://<spaceName>/<Vid>` 保存为稳定的
161
+ `source_material_id`,并在素材接口的 `source`、`url`、可识别的 poster/sprite 字段中
162
+ 写入稳定 VOD 身份;HTTP(S) 播放地址仅在编辑器运行时使用,初始化和预览失败时自动重新获取。
163
+ 导出结果若返回 `vod://<spaceName>/<Vid>`,任务列表同样通过点播 OpenAPI 换取
164
+ HTTP(S) 地址,再显示「预览」和「下载」;TOS 导出结果仍按原有 STS 签名逻辑处理。
165
+ 提交多轨剪辑任务时仅在请求副本中转换媒体轨道 `Source`:点播素材使用
166
+ `vod://<spaceName>/<Vid>`,TOS 素材使用 `tos://<bucket>/<key>`。
167
+ 优先使用素材中已有的完整 `source_material_id`;旧工程轨道中的
168
+ `vid://<Vid>` 若没有完整素材身份,使用
169
+ `storage.media_output_destination` 配置的 VOD 空间补成 `vod://` 地址;缺少空间时在提交前报错。
170
+ 普通 URL 素材仍使用刷新后的 HTTP(S) 地址;工程持久化及页面预览中的
171
+ `Source` 不随此转换改写。
172
+
73
173
  ## 接入说明
74
- - `projectId`、`endpoint` 必填。`endpoint` 指向你的业务代理。
174
+ - `container`、`projectId`、`endpoint` 必填。`container` 是编辑器挂载元素;`projectId` 用于加载和保存工程;`endpoint` 是工程、素材和任务请求的业务代理地址,支持 HTTP(S) 地址或以 `/` 开头的路径。`source` 是可选的接入方标识,用于区分埋点来源和问题归因;未配置时 SDK 会提示 warning,并使用默认值 `sdk`。
175
+ - 构造时会在挂载页面和发起请求前汇总校验错误,错误文案会说明字段用途和修复方式。`storage.media_output_destination` 仅支持 `vod://<space>` 或 `tos://<bucket>[/prefix]`,并且必须和函数 `storage.getUploadSTS` 同时配置;只配置其中任意一个都会初始化失败。两者均不配置时不启用内置存储上传,可继续使用自定义上传回调;自定义上传也未配置时不展示本地上传入口。凭证内容及远端桶权限仍需在实际请求时验证,错误信息不会回显配置值。
75
176
  - `theme` 默认 `light`。未传或传入其他值时按浅色渲染;只有显式 `theme: 'dark'` 才走暗色。
76
177
  - 产物是面向浏览器的单文件 ESM。依赖里的 AMD `define(["./core"])`、`define(["dayjs"])` 和 Node `require('crypto')` 兜底已在构建时剔除或中和,避免 Next.js / webpack / Rspack 误解析依赖或报告动态 require 警告;浏览器加密仍使用 Web Crypto。
77
178
  - `getHeaders` 可选,每次请求前都会重新调用;SDK 不解析、不缓存、不改写返回值,仅将其合并到发往 `endpoint` 的工程、素材、tools、tasks、导出等请求中。闭包内 Token 更新会自动用于下一次请求。
78
179
  - SDK 发往 `endpoint` 的全部 AMK 服务请求都会固定携带 `X-Amk-Task-Source: vibe-editing`,用于任务来源和用量归因;该字段不会被 `getHeaders` 或单次请求 Header 覆盖。跨域代理需在 CORS 配置中允许此请求头。成片 CDN 下载、TOS 直传等非 AMK 服务请求不携带该字段。
79
- - 本地上传通过 `onUploadFile(file)` 实现单文件上传;SDK 负责多文件并发、逐项入库和部分失败收口。旧 `onUploadMaterial(files)` 仍兼容,但只能整批完成后入库。URL 导入仍由 `onUploadUrlMaterial` 完成。返回素材必须带业务主键 `source_material_id`,不必填写 `material_id`。
180
+ - 同一批 AMK 服务请求还会固定携带 `X-Amk-Sdk-Version`,值为当前 AMK Editor 构建版本;宿主 Header 不能覆盖。跨域代理需允许此请求头。预设资源请求保留已有的 `sdk_version` 查询参数。
181
+ - 本地上传优先使用业务自定义回调:`onUploadFile(file)` > 旧版 `onUploadMaterial(files)` > SDK 内置 VOD / TOS 上传。也就是说,同时配置 `storage` 和自定义上传时一定走自定义链路;只有两个自定义回调均未配置时,SDK 才按 `media_output_destination` 协议使用内置上传。`onUploadFile` 模式下 SDK 负责多文件并发、逐项入库和部分失败收口;旧 `onUploadMaterial` 只能整批完成后入库。URL 导入仍由 `onUploadUrlMaterial` 完成。返回素材必须带业务主键 `source_material_id`,不必填写 `material_id`。
182
+ - 配置 `vod://<space>` 与 `storage.getUploadSTS` 可启用内置点播直传;配置 `tos://<bucket>[/prefix]` 与 `storage.getUploadSTS` 可启用内置 TOS 直传。两种 storage 目标都不会覆盖业务自定义上传回调。
183
+ - `storage.media_output_destination` 的服务端转存行为按发行版区分:火山版会将该字段传给支持产物转存的 AMK tools;BytePlus AMK 当前不支持 TOS/VOD 产物转存,因此 BytePlus 构建不会向 AMK 接口发送该字段(包括调用参数中显式传入的同名字段),避免请求失败。此限制不影响浏览器本地上传:`vod://` 目标在火山包中使用 `tt-uploader`,在 BytePlus 包中使用 `@byteplus/uploader`;BytePlus TOS 内置上传仍待后续接入。自定义上传回调始终优先于内置上传。
184
+ - 配置 `tos://` 格式的 `storage.media_output_destination` 时必须同时配置 `storage.getUploadSTS`。只有两者都存在时,SDK 才接管 `source_material_id` 为 `tos://bucket/key` 的资产库素材并生成临时播放地址;该字段不是有效 TOS 地址时兜底读取 `source`,不改写业务 `source_material_id`。VOD 刷新同样优先解析 `source_material_id`,无有效 VOD 地址时读取 `source`,且仍校验空间匹配。同批非 TOS 素材继续使用业务 URL。两者都未配置时,`tos://` 只作为业务稳定 ID:已有 HTTP(S) 长期 URL 会原样使用且不触发刷新;缺少播放地址时调用 `onRefreshPlayInfo` 补齐,刷新后仍无地址则拒绝入库。
80
185
  - 播放地址、封面、雪碧图可能有时效。通过 `onRefreshPlayInfo` 返回新的访问地址;补丁按 `material_id`、`source_material_id`、无标识时数组顺序依次匹配,未返回的字段保持原值。
81
186
  - 可选实现 `onMaterialsImported`:素材成功入库后回调已合并 `material_id` 的列表;可用于把新素材挂到对话草稿。失败或取消不会触发。
82
187
  - 可选实现 `onPersistExtractUrls`:把抽帧得到的临时地址转存为业务长期地址,并随 `materialPatch` 写回自定义存储字段。
@@ -88,6 +193,10 @@ editor.destroy();
88
193
  - `updateTitle(title)` 复用顶栏标题保存链路:先 PATCH 工程名,成功后更新编辑器标题/工程快照并触发 `header.onTitleUpdateSuccess`;校验失败或保存失败会 reject,且不会触发成功回调。
89
194
  - `toolbar.customItems` 的只读态不会自动置灰。需要禁用时在该项 `disabled({ readonly })` 里自行返回 true(例如 `disabled: ({ readonly }) => readonly`)。录音中仍会全局锁定自定义项。内置 ASR 按钮在只读时仍会禁用。
90
195
  - `refreshProject()` 会等待当前保存队列结束,再重新拉取工程、刷新临时播放地址并热更新素材与 Track;远端 Track 不会写入本地撤销历史,也不会被自动保存回服务端。
196
+ - `refreshMaterials(): Promise<MaterialItem[]>` 只读取当前工程 `/materials` 全部分页,并复用已配置的播放地址刷新、封面展示和后台抽帧处理;结果替换素材面板,空列表会清空面板。不调用工程或 editor 查询,不重新设置 Track/Canvas。
197
+ - `refreshProjectInfo(): Promise<AmkProjectInfo>` 只 GET 当前工程接口,返回并保存完整元信息(包含 `project_id`、`name`、`description` 及服务端扩展字段),可通过 `getProject().projectInfo` 读取;目前名称同步到 `projectName` 和 Header,后续其他工程字段也由该入口处理。不会刷新素材或轨道,不会 PATCH 工程或触发 `onTitleUpdateSuccess`。
198
+ - `refreshEditParam()` 只拉取 editor 文档并更新轨道、画布。`refreshProject()` 一次获取工程信息、素材和 editor 三部分,更新完整工程;局部刷新方法各自只负责对应部分。
199
+ - 两个刷新方法都会等待初始化及已有保存完成,与 `refreshProject()` / `refreshEditParam()` 共用串行刷新队列;同一方法的并发调用合并。读取或播放地址刷新失败时保留原状态并 reject,后续可重试。
91
200
  - `whenReady()` 完成后会每 5 秒拉取一次 Editing 工程;服务端 `editor.revision` 高于当前版本,或素材数量 / 素材 ID 集合发生变化时,都会复用 `refreshProject()` 的无撤销热更新链路。素材 ID 优先使用 `material_id`,缺失时回退 `source_material_id`,仅返回顺序变化不会触发刷新。页面进入后台时暂停轮询,重新可见后立即检查一次,`destroy()` 会停止后续轮询。相同 ID 的素材字段更新或纯标题变更仍需宿主主动调用 `refreshProject()`。
92
201
  - 轮询会额外检查相同素材后补的封面和雪碧图:当前页面对应字段为空且服务端已返回有效链接时,仅刷新素材面板展示,不重建 Track,也不调用素材或 editor 保存;当前页面已有链接时保持不变。其他相同 ID 的素材字段变化仍不会触发热更新。
93
202
  - 素材同步兼容尚未产生轨道的空工程:服务端 `editor.document` 为 `{}`、缺少 `Track` 时按空轨道处理,不会阻断新素材写入面板;显式返回非数组 `Track` 仍视为非法工程数据。
@@ -1,5 +1,5 @@
1
1
  import './veveditor.css';
2
- import type { AmkMaterialImportType, AmkMaterialImportRequestOptions, AmkEditorOptions, AmkExportRequestResult, AmkProjectSnapshot, MaterialItem, VeVeditorInstance } from './types';
2
+ import type { AmkMaterialImportType, AmkMaterialImportRequestOptions, AmkEditorOptions, AmkExportRequestResult, AmkProjectSnapshot, AmkProjectInfo, MaterialItem, VeVeditorInstance } from './types';
3
3
  import { type AmkI18nInstance } from './i18n';
4
4
  import { type AmkInvokeToolParams } from './api/client';
5
5
  export declare class AmkEditor {
@@ -16,6 +16,7 @@ export declare class AmkEditor {
16
16
  private exportTaskListLoaded;
17
17
  private exportTaskListRequest?;
18
18
  private readonly message;
19
+ private readonly notifiedToolErrors;
19
20
  private importActions?;
20
21
  /** 完整 VeVeditor 挂载前承载外部素材导入入口的隐藏节点。 */
21
22
  private bootstrapImportHost?;
@@ -27,6 +28,7 @@ export declare class AmkEditor {
27
28
  private readonly bootstrapAbortController;
28
29
  private destroyed;
29
30
  private projectName?;
31
+ private projectInfo?;
30
32
  private editorRevision;
31
33
  private projectHydrated;
32
34
  private lastKnownTrack;
@@ -51,11 +53,15 @@ export declare class AmkEditor {
51
53
  /** 完整工程与轻量 editor 刷新共用队列,保证后发请求最后应用。 */
52
54
  private runtimeRefreshQueue;
53
55
  private projectRefreshInFlight?;
56
+ private materialsRefreshInFlight?;
57
+ private materialsRefreshTransferRequested;
58
+ private projectInfoRefreshInFlight?;
54
59
  private editParamRefreshInFlight?;
55
60
  private pendingSaveCount;
56
61
  private readonly asrPollingControllers;
57
62
  /** 当前前台 ASR 会话;取消、关闭或销毁后直接丢弃,不写入工程 JSON。 */
58
63
  private activeAsrElementId?;
64
+ private asrSession?;
59
65
  /** 提交 ASR 前的同步锁,防止连点在任务创建前重复提交 */
60
66
  private readonly asrStartingElementIds;
61
67
  /** sprite 抽帧任务轮询:key = material_id / source */
@@ -63,6 +69,13 @@ export declare class AmkEditor {
63
69
  private readonly posterPollingControllers;
64
70
  /** 同一素材的抽帧检查共享一条 Promise,避免初始化与热刷新重复建任务。 */
65
71
  private readonly materialExtractInFlight;
72
+ /** 每个素材在本次会话只检查一次抽帧;新导入的素材仍会获得自己的首次检查。 */
73
+ private readonly materialExtractChecked;
74
+ /** 同一素材的过期图片只刷新一次地址;并发失败共享同一请求。 */
75
+ private readonly thumbnailErrorHandled;
76
+ /** 图片确实加载失败时,每个素材的封面/雪碧图各只补抽一次。 */
77
+ private readonly thumbnailReextractHandled;
78
+ private readonly thumbnailErrorInFlight;
66
79
  /** TOS 上传完成前的素材面板占位:key = source_material_id。 */
67
80
  private readonly tosUploadPlaceholders;
68
81
  /** URL 上传完成前的素材面板占位:按本次导入批次暂存占位卡片 id。 */
@@ -76,12 +89,10 @@ export declare class AmkEditor {
76
89
  private materialPatchBatchTimer?;
77
90
  /** 批次串行提交,避免先发批次晚返回后覆盖更新批次。 */
78
91
  private materialPatchFlushQueue;
79
- /** 同一素材的 sprite 失败只处理一次,避免多个缩略图同时 403 重复建任务。 */
80
- private readonly thumbnailErrorInFlight;
81
92
  /** 前端抽帧封面缓存(不落盘):key = materialKey,value = dataURL */
82
93
  private readonly posterCache;
83
- /** 本次会话签名 URL 对应的原始 TOS 身份,供产物落盘时保留重签依据。 */
84
- private readonly tosIdentityBySignedUrl;
94
+ /** 本次会话展示 URL 对应的原始 TOS/VOD 身份,供产物落盘后续签。 */
95
+ private readonly taskOutputIdentityByDisplayUrl;
85
96
  /** 同一 URL 的封面抽帧只执行一次,避免初始化与上传回调重复请求。 */
86
97
  private readonly posterCaptureInFlight;
87
98
  /** 销毁编辑器时中断尚未完成的前端抽帧或 AMK 首帧轮询。 */
@@ -90,14 +101,25 @@ export declare class AmkEditor {
90
101
  private presetLibrary;
91
102
  /** 所有 TOS 素材共用一个刷新定时器,避免按素材创建大量 timer。 */
92
103
  private tosSignedUrlRefreshTimer?;
104
+ /** 同一组未变化的 TOS 签名 URL 只自动重签一次,避免失败后固定间隔空转。 */
105
+ private readonly tosSignedUrlRefreshAttempted;
93
106
  private tosSignedUrlRefreshInFlight?;
94
107
  /** 同一轮播放地址刷新合并 materialId,并串行执行各批次,避免并发覆盖轨道和 revision。 */
95
108
  private readonly pendingPlayInfoRefreshes;
96
109
  private playInfoRefreshBatchScheduled;
97
110
  private playInfoRefreshQueue;
98
111
  private readonly handleVisibilityChange;
112
+ private readonly handleMaterialUploadStatusChange;
99
113
  private readonly handleTrackChanged;
100
114
  private readonly handleEditParamChanged;
115
+ private readonly uploadQueue;
116
+ private activeUploadBatches;
117
+ private temporaryMaterialTransferPromise?;
118
+ private temporaryMaterialScanRequested;
119
+ private readonly committedTemporaryMaterialReplacements;
120
+ private readonly pendingTemporaryMaterialReplacements;
121
+ private readonly temporaryMaterialExtractPatches;
122
+ private readonly deferredTemporaryMaterialExtracts;
101
123
  constructor(options: AmkEditorOptions);
102
124
  /** 等待工程拉取 / canvas 校正 / 挂载完成 */
103
125
  whenReady(): Promise<this>;
@@ -105,6 +127,7 @@ export declare class AmkEditor {
105
127
  getI18n(): AmkI18nInstance;
106
128
  /** 通用工具调用:POST /api/v1/tools/{toolName} */
107
129
  invokeTool<T = unknown>(options: AmkInvokeToolParams): Promise<T>;
130
+ private wasToolErrorNotified;
108
131
  /**
109
132
  * Queries an asynchronous AMK task through the editor's configured endpoint
110
133
  * and headers. Intended for host UI cards that track tasks created by editor
@@ -148,6 +171,22 @@ export declare class AmkEditor {
148
171
  * 适合素材引用面板等必须包含最新导出产物的场景。
149
172
  */
150
173
  fetchProjectMaterials(): Promise<MaterialItem[]>;
174
+ /** 重新拉取全部素材并更新素材面板;不重新拉取或替换 Track、工程名。 */
175
+ refreshMaterials(): Promise<MaterialItem[]>;
176
+ private refreshMaterialsInternal;
177
+ private enqueueTemporaryMaterialTransfers;
178
+ private runTemporaryMaterialTransfers;
179
+ private reconcileTemporaryMaterials;
180
+ private findTemporaryMaterialUploadInputs;
181
+ private applyCommittedMaterialReplacements;
182
+ private applyCommittedMaterialBindings;
183
+ private applyTemporaryMaterialExtractPatches;
184
+ private reconcileTemporaryMaterialExtractPatches;
185
+ private flushDeferredTemporaryMaterialExtracts;
186
+ private resolveTemporaryMaterialReplacements;
187
+ private uploadTemporaryMaterials;
188
+ /** 拉取完整工程元信息并应用相关字段;不刷新素材或 Track,也不回写工程。 */
189
+ refreshProjectInfo(): Promise<AmkProjectInfo>;
151
190
  /**
152
191
  * 重新拉取服务端工程,并把最新素材与 Track 热更新到当前编辑器。
153
192
  * 用于 Agent 完成远端编辑后刷新右侧预览;不会产生撤销记录,也不会把回灌事件再次保存到服务端。
@@ -164,8 +203,9 @@ export declare class AmkEditor {
164
203
  /**
165
204
  * 刷新素材播放信息(按需触发,如播放前 / 初始化)。
166
205
  * - TOS 直传素材会先使用临时 STS 重签私有对象 URL
206
+ * - VOD 直传素材按 Vid 换取最新播放地址
167
207
  * - 配置 `material.onRefreshPlayInfo` 后,宿主可继续覆盖播放字段
168
- * - 两者都未配置时直接返回当前素材,不发请求
208
+ * - 三者都未配置时直接返回当前素材,不发请求
169
209
  * @param materialIdOrIds 单个 material_id、material_id 列表;省略则刷新当前全部有 material_id 的素材
170
210
  */
171
211
  refreshPlayInfo(materialIdOrIds?: string | string[]): Promise<MaterialItem | MaterialItem[] | undefined>;
@@ -189,7 +229,7 @@ export declare class AmkEditor {
189
229
  * 再后台持久化;失败只保留旧地址,不影响预览与 whenReady 收敛。
190
230
  */
191
231
  private refreshRemainingMaterialsOnInit;
192
- /** TOS 私有桶签名刷新优先,宿主刷新回调随后可继续覆盖播放信息。 */
232
+ /** 临时素材保留现有 HTTP 地址;其余素材依次经过 TOS、VOD 与宿主播放信息刷新。 */
193
233
  private refreshMaterialTargets;
194
234
  /**
195
235
  * 将重签后的素材 URL 按 material_id 同步到轨道节点并重建媒体节点。
@@ -197,6 +237,7 @@ export declare class AmkEditor {
197
237
  */
198
238
  private applyTrackMaterialUrls;
199
239
  private resolveTosSignedResourceUrls;
240
+ private isTosSignedUrlRefreshAttempted;
200
241
  private getExpiringTosMaterialIds;
201
242
  private scheduleTosSignedUrlRefresh;
202
243
  private refreshExpiringTosUrls;
@@ -278,6 +319,10 @@ export declare class AmkEditor {
278
319
  private uploadFileWithPlaceholder;
279
320
  private uploadCustomFile;
280
321
  private uploadTosFile;
322
+ private uploadVodFile;
323
+ private hasVodStorage;
324
+ private hasTosStorage;
325
+ private getVodConfig;
281
326
  private extractToolResult;
282
327
  private requirePositiveNumber;
283
328
  private waitForToolTask;
@@ -285,7 +330,7 @@ export declare class AmkEditor {
285
330
  private resolveMetadataProbeUrl;
286
331
  private isPositiveNumber;
287
332
  /**
288
- * 自定义本地 / URL / 资产库导入的统一元信息兜底。
333
+ * 单文件、批量、URL 与资产库导入的统一元信息兜底。
289
334
  * 只探测当前缺失的必需字段,业务已经返回的合法值保持不变。
290
335
  */
291
336
  private ensureImportedMaterialMetadata;
@@ -293,10 +338,10 @@ export declare class AmkEditor {
293
338
  /** 将业务资产库的原始条目归一化为 SDK 素材;TOS 地址随后由 SDK 自行签发。 */
294
339
  private normalizeSystemMaterial;
295
340
  /**
296
- * 资产库选择的 TOS 条目:同步签发播放 URL 并补齐基础元信息。
297
- * 入参应为已 normalize 的素材;poster/sprite 在正式素材入库后后台处理。
341
+ * 资产库条目按项准备:启用 SDK TOS 存储时仅为 tos:// 条目签名;
342
+ * 未启用时保留业务长期 URL,缺少播放地址的条目交给业务刷新回调补齐。
298
343
  */
299
- private prepareSystemTosMaterials;
344
+ private prepareSystemMaterials;
300
345
  private ingestTosImportedMaterials;
301
346
  /**
302
347
  * 本地 / URL 上传入库后的统一收口:
@@ -313,6 +358,8 @@ export declare class AmkEditor {
313
358
  * 才写入素材面板(业务不用传 material_id;不覆盖本地 source / kid / 预览字段)。
314
359
  */
315
360
  private persistUploadedMaterials;
361
+ /** 所有上传方式共用的入库边界:仅补探测缺失元信息,再创建远端素材。 */
362
+ private createImportedMaterials;
316
363
  private rememberPreMountImportedMaterials;
317
364
  private isHttpUrl;
318
365
  private resolveDisplayPoster;
@@ -349,8 +396,8 @@ export declare class AmkEditor {
349
396
  */
350
397
  private schedulePersistExtractUrlsAndSwap;
351
398
  /**
352
- * 统一入口:初始化 / 本地上传 / URL 上传拿到素材后,按 sprite/poster 判断是否抽帧。
353
- * - sprite / poster 缺失或 auth_key 过期:重新抽帧
399
+ * 统一入口:初始化 / 新素材入库后,每个素材在本次会话只检查一次抽帧。
400
+ * - sprite / poster 缺失时创建任务;图片加载失败不再触发重抽
354
401
  * - http 结果:先临时链上屏/PUT;若配置 onPersistExtractUrls 则后台转存换链
355
402
  * - 封面:浏览器可并行解一帧作会话预览(DataURL 不落盘);正式封面始终走 AMK 接口 URL 落库
356
403
  * - enableThumbnailDecode=true:跳过 sprite 接口,轨道缩略图走前端解码
@@ -360,22 +407,21 @@ export declare class AmkEditor {
360
407
  private ensureTrackMaterialExtractTasks;
361
408
  private ensureMaterialExtractTasksInBackground;
362
409
  private createExtractFramesTask;
363
- /** AMK 转存到私有 TOS 后,任务产物需先重签才能用于浏览器预览。 */
410
+ /** 导出结果是资源身份时,先换取浏览器可访问的播放地址。 */
411
+ private resolveExportOutputUrl;
412
+ /** 任务产物的 TOS/VOD 身份先换成浏览器可访问的 HTTP URL。 */
364
413
  private signTaskOutputUrls;
365
414
  private startSpritePolling;
366
415
  private startPosterPolling;
367
416
  private buildSpriteFromExtractResult;
368
417
  private extractFirstSnapshotUrl;
369
- /**
370
- * 时间轴 sprite / 素材库 poster 真实请求失败后的兜底:不解析 URL 的签名格式,直接以 Image.onerror 为准。
371
- * 先让业务通过 onRefreshPlayInfo 更新素材;刷新后仍没有新地址,再重新抽帧。
372
- */
418
+ /** 图片真实加载失败时先换一次过期签名,仍不可用则每类图片最多补抽一次。 */
373
419
  private handleThumbnailError;
374
- /** 兼容时间轴元素与素材库 sketch 项,定位失败资源所属素材。 */
375
420
  private resolveMaterialFromThumbnailError;
376
421
  private findMaterialByKey;
377
422
  private applyMaterialToPanel;
378
423
  private enqueueMaterialPatch;
424
+ private patchMaterialExtraction;
379
425
  private patchMaterialRemote;
380
426
  private flushPendingMaterialPatches;
381
427
  private clearSpriteTimer;
@@ -1,6 +1,12 @@
1
1
  import type { AmkApiClient } from './client';
2
- import type { AmkProjectSnapshot, MaterialItem } from '../types';
2
+ import type { AmkProjectSnapshot, AmkProjectInfo, MaterialItem } from '../types';
3
3
  type EditingApiClient = Pick<AmkApiClient, 'requestJson'>;
4
+ export interface AmkMaterialReplacement {
5
+ material_id: string;
6
+ source_material_id: string;
7
+ source: string;
8
+ url?: string;
9
+ }
4
10
  export type LoadedAmkProject = AmkProjectSnapshot & {
5
11
  editorRevision: number;
6
12
  };
@@ -15,6 +21,10 @@ export type SavedAmkEditor = {
15
21
  export declare function fetchAmkProjectMaterials(client: EditingApiClient, projectId: string, options?: {
16
22
  signal?: AbortSignal;
17
23
  }): Promise<MaterialItem[]>;
24
+ /** 只读取工程元信息,不请求素材列表和 editor 文档。 */
25
+ export declare function fetchAmkProjectInfo(client: EditingApiClient, projectId: string, options?: {
26
+ signal?: AbortSignal;
27
+ }): Promise<AmkProjectInfo>;
18
28
  export declare function fetchAmkProject(client: EditingApiClient, projectId: string, options?: {
19
29
  signal?: AbortSignal;
20
30
  }): Promise<LoadedAmkProject>;
@@ -34,6 +44,8 @@ export declare function createAmkMaterials(client: EditingApiClient, projectId:
34
44
  * PUT 语义:已存在覆盖,不存在新增;适合本地上传/URL上传完成后写回。
35
45
  */
36
46
  export declare function upsertAmkMaterials(client: EditingApiClient, projectId: string, materials: MaterialItem[]): Promise<void>;
47
+ /** Rebinds existing materials to durable customer storage without changing material_id. */
48
+ export declare function replaceAmkMaterials(client: EditingApiClient, projectId: string, materials: AmkMaterialReplacement[]): Promise<void>;
37
49
  /**
38
50
  * 删除 AMK 工程素材。Editing API DELETE body 为 source_material_ids,
39
51
  * 值为业务 source_material_id;这里统一按 100 条分批。
@@ -0,0 +1,17 @@
1
+ import type { AmkInvokeToolParams } from './api/client';
2
+ export type AmkAsrProvider = 'asr-subtitles' | 'maas';
3
+ export declare function resolveAsrProvider(provider?: AmkAsrProvider): AmkAsrProvider;
4
+ /** 中间音频不转存,以获得下游模型可直接读取的临时 HTTP(S) URL。 */
5
+ export declare function submitMaasAsr(options: {
6
+ mediaType: 'video' | 'audio';
7
+ mediaUrl: string;
8
+ signal?: AbortSignal;
9
+ invoke: (params: AmkInvokeToolParams) => Promise<any>;
10
+ query: (taskId: string) => Promise<any>;
11
+ }): Promise<string>;
12
+ /** 旧字幕接口使用秒;MaaS 的分句时间是毫秒,在入口统一为秒。 */
13
+ export declare function extractMaasUtterances(payload: any): {
14
+ text: any;
15
+ start_time: number;
16
+ end_time: number;
17
+ }[] | undefined;
@@ -0,0 +1,9 @@
1
+ type JsonRecord = Record<string, unknown>;
2
+ /**
3
+ * TEMP: BP 导出接口尚不支持元素 Source 的 vod:// / tos:// 地址。
4
+ * 服务端工程不保存 UserData,优先使用刚刷新的素材 URL;运行时副本可回退 UserData.url。
5
+ * 只遍历 Track 元素,不处理 Extra;返回副本供提交,绝不改动工程。
6
+ * 服务端支持协议地址后,删除本文件及 amk-editor.ts 中的调用即可。
7
+ */
8
+ export declare function replaceBytePlusExportElementSources(editParam: JsonRecord, materialUrlById?: ReadonlyMap<string, string>): JsonRecord;
9
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { AmkEditorOptions } from './types';
2
+ /** 仅校验初始化时可确定的配置错误,不请求凭证或远端服务。 */
3
+ export declare function validateAmkEditorOptions(options: AmkEditorOptions): string[];
@@ -0,0 +1,16 @@
1
+ export declare const distribution: "volcengine" | "byteplus";
2
+ export declare const distributionDefaults: {
3
+ locale: string;
4
+ region: string;
5
+ videoHost: string;
6
+ };
7
+ /**
8
+ * 发行版对应的服务端能力开关。
9
+ *
10
+ * BytePlus AMK 当前不支持通过 media_output_destination 配置产物转存。
11
+ * 该限制只作用于 AMK 接口请求,不影响 SDK 使用 @byteplus/uploader
12
+ * 完成 BytePlus VOD 直传与播放地址解析;BytePlus TOS 仍可后续独立接入。
13
+ */
14
+ export declare const distributionCapabilities: {
15
+ readonly forwardsMediaOutputDestination: boolean;
16
+ };
@@ -30,6 +30,7 @@ export declare const AMK_I18N_KEYS: {
30
30
  readonly exportTaskEmptyDescription: "amk.header.exportTaskEmptyDescription";
31
31
  readonly exportTaskLoading: "amk.header.exportTaskLoading";
32
32
  readonly exportTaskDownloadReady: "amk.header.exportTaskDownloadReady";
33
+ readonly exportTaskUrlUnavailable: "amk.header.exportTaskUrlUnavailable";
33
34
  readonly exportTaskDownload: "amk.header.exportTaskDownload";
34
35
  readonly exportTaskDownloadAgain: "amk.header.exportTaskDownloadAgain";
35
36
  readonly exportTaskDownloading: "amk.header.exportTaskDownloading";
@@ -1,6 +1,8 @@
1
+ import { type UploadQueue } from './upload-queue';
1
2
  import type { AmkMaterialImportType, AmkMaterialImportRequestOptions, MaterialItem, SystemMaterialItem } from './types';
2
3
  import type { AmkI18nInstance } from './i18n';
3
4
  interface MountImportActionsOptions {
5
+ uploadQueue?: UploadQueue;
4
6
  /** AMKEditor 自己的浮层容器;按钮仍挂在 VeVeditor 提供的工具栏插槽中。 */
5
7
  modalContainer: HTMLElement;
6
8
  uploadAccept?: string;
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  export declare const version: string;
2
+ export type { AmkAsrProvider } from './asr-provider';
2
3
  export { AmkEditor, createAmkEditor } from './amk-editor';
3
4
  export { AmkApiClient, createAmkApiClient } from './api/client';
4
5
  export type { AmkApiClientOptions, AmkInvokeToolParams } from './api/client';
5
6
  export type { PresetLibrary, PresetLibraryItem, PresetLibraryResourceKey, } from './api/preset-library';
6
7
  export { AMK_I18N_KEYS, createAmkI18n, tAmk, getGlobalAmkI18n, setGlobalAmkI18n, } from './i18n';
7
8
  export type { AmkI18nInstance, AmkI18nOptions, Locale, LocaleMessages, Messages, } from './i18n';
8
- export type { AmkEditorOptions, AmkEditorStorageConfig, AmkEditorUploadSTSCredentials, AmkEditorConfig, AmkEditorDecodeOptions, AmkEditorExportConfig, AmkEditorGetHeaders, AmkEditorHeaderConfig, AmkEditorHeaderTitleUpdateSuccess, AmkEditorInternalConfig, AmkMaterialImportType, AmkMaterialImportRequestOptions, AmkExportRequestResult, AmkExportTaskCreatedEvent, AmkProjectSnapshot, ExportVideoParams, MaterialConfig, MaterialItem, PersistExtractUrlsResult, RecommendedExtractStorageFields, SystemMaterialItem, Theme, VeVeditorInstance, } from './types';
9
+ export type { AmkEditorOptions, AmkEditorStorageConfig, AmkEditorUploadSTSCredentials, AmkEditorVodPlayInfo, AmkEditorVodUploadToken, AmkEditorConfig, AmkEditorDecodeOptions, AmkEditorExportConfig, AmkEditorGetHeaders, AmkEditorHeaderConfig, AmkEditorHeaderTitleUpdateSuccess, AmkEditorInternalConfig, AmkMaterialImportType, AmkMaterialImportRequestOptions, AmkExportRequestResult, AmkExportTaskCreatedEvent, AmkProjectSnapshot, AmkProjectInfo, ExportVideoParams, MaterialConfig, MaterialItem, PersistExtractUrlsResult, RecommendedExtractStorageFields, SystemMaterialItem, Theme, VeVeditorInstance, } from './types';