@volcengine/amk-editor 0.0.2-beta.1 → 0.0.2

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
@@ -51,6 +51,9 @@ editor.requestMaterialImport('local', {
51
51
 
52
52
  // 从服务端重新拉取当前工程,并热更新素材与 Track(不写入撤销历史)。
53
53
  await editor.refreshProject();
54
+
55
+ // 查询由编辑器操作创建的异步任务;复用相同的 endpoint 和 getHeaders。
56
+ const exportTask = await editor.getTask('your-task-id');
54
57
  ```
55
58
  页面卸载时销毁:
56
59
  ```ts
@@ -68,9 +71,13 @@ editor.destroy();
68
71
  - 可选配置 `export.qualityEnhancement: true` 以在导出弹窗展示「视频画质增强」;默认不展示。
69
72
  - 可选配置 `header.mount` 为外部 DOM 节点,将顶栏渲染到该节点(而不是编辑器内部),便于宿主做全宽顶栏;`header.show: false` 仍可完全隐藏顶栏。
70
73
  - 可选配置 `header.onTitleUpdateSuccess`:工程名 PATCH 成功后回调 `{ projectId, title }`。保存成功前编辑器继续展示旧名称;保存失败不会修改编辑器标题,也不会触发回调。
74
+ - 可选配置 `header.exportTaskList: false` 隐藏导出任务列表入口;默认开启。关闭后不会展示任务列表按钮,也不会启动导出任务列表查询与轮询。
71
75
  - `requestMaterialImport(type, options?)` 返回是否成功触发已配置入口;`local`、`url`、`system` 分别要求存在本地上传能力、`onUploadUrlMaterial`、`onUploadFromSystem`。外部入口不会复制上传逻辑,仍走素材面板相同的回调、TOS 签名、素材入库与元信息处理。可选的 `options.onMaterialsImported` 只对这一次外部触发有效,编辑器自身的导入按钮不会调用它。
72
76
  - `toolbar.customItems` 的只读态不会自动置灰。需要禁用时在该项 `disabled({ readonly })` 里自行返回 true(例如 `disabled: ({ readonly }) => readonly`)。录音中仍会全局锁定自定义项。内置 ASR 按钮在只读时仍会禁用。
73
77
  - `refreshProject()` 会等待当前保存队列结束,再重新拉取工程、刷新临时播放地址并热更新素材与 Track;远端 Track 不会写入本地撤销历史,也不会被自动保存回服务端。
78
+ - `getTask(taskId, options?)` 查询 `GET /api/v1/tasks/{task_id}`,复用编辑器初始化时的 `endpoint` 与 `getHeaders`;`options.signal` 可在宿主任务卡卸载时取消轮询请求。
79
+ - 配置 `projectId` 后,API Client 会把 `invokeTool`、`invokeSyncTool` 的成功响应以及 `getTask` 的轮询结果,以 schema v2 best-effort 上报到 `POST /api/v1/editing/projects/{project_id}/tasks`。记录包含 `task_id`、`tool_name`、同步/异步模式、状态、原始请求和响应;台账写入失败只输出 warning,不会让已经成功的 AMK 调用失败。轮询上报会省略 `request.input`,避免覆盖首次提交保存的请求参数。
80
+ - mediakit-studio `dev` 当前只提供上述任务台账写接口,尚无任务列表/详情 GET 接口。因此编辑器顶栏的导出记录仍只保留当前页面会话;如需刷新后读取历史导出列表,需要服务端补充按工程查询任务的接口。
74
81
  ## 样式隔离
75
82
  SDK 会随 `import '@volcengine/amk-editor'` 自动注入样式,导航栏、左侧分类、素材网格的布局由 SDK 自己负责。**接入方不必再写补丁 CSS 才能让界面正常显示。**
76
83
  编辑器挂在普通 DOM(`#track-video-editor`)里,不是 Shadow DOM。宿主页面里针对 `section` / `nav` / `aside` 的全局布局重置会穿透进来,把顶栏或左侧分类挤扁。
@@ -10,6 +10,10 @@ export declare class AmkEditor {
10
10
  private layout?;
11
11
  private exportModal?;
12
12
  private exportRequestInFlight?;
13
+ private readonly exportTaskPollingControllers;
14
+ private readonly exportTaskPollingTokens;
15
+ private exportTasks;
16
+ private exportTaskListRequest?;
13
17
  private importActions?;
14
18
  private asrProgressModal?;
15
19
  private confirmModal?;
@@ -50,6 +54,8 @@ export declare class AmkEditor {
50
54
  private readonly thumbnailErrorInFlight;
51
55
  /** 前端抽帧封面缓存(不落盘):key = materialKey,value = dataURL */
52
56
  private readonly posterCache;
57
+ /** 本次会话签名 URL 对应的原始 TOS 身份,供产物落盘时保留重签依据。 */
58
+ private readonly tosIdentityBySignedUrl;
53
59
  /** 同一 URL 的封面抽帧只执行一次,避免初始化与上传回调重复请求。 */
54
60
  private readonly posterCaptureInFlight;
55
61
  /** 销毁编辑器时中断尚未完成的前端抽帧或 AMK 首帧轮询。 */
@@ -69,6 +75,15 @@ export declare class AmkEditor {
69
75
  getI18n(): AmkI18nInstance;
70
76
  /** 通用工具调用:POST /api/v1/tools/{toolName} */
71
77
  invokeTool<T = unknown>(options: AmkInvokeToolParams): Promise<T>;
78
+ /**
79
+ * Queries an asynchronous AMK task through the editor's configured endpoint
80
+ * and headers. Intended for host UI cards that track tasks created by editor
81
+ * operations such as {@link requestExport}.
82
+ */
83
+ getTask<T = unknown>(taskId: string, options?: {
84
+ headers?: Record<string, string>;
85
+ signal?: AbortSignal;
86
+ }): Promise<T>;
72
87
  /**
73
88
  * Opens the existing export modal and resolves after the user confirms or cancels.
74
89
  * Intended for Agent frontend tools (`request_export_task`). Header export still
@@ -122,6 +137,7 @@ export declare class AmkEditor {
122
137
  * URL 是运行时数据:保存工程,但不产生撤销步骤。
123
138
  */
124
139
  private applyTrackMaterialUrls;
140
+ private resolveTosSignedResourceUrls;
125
141
  private getExpiringTosMaterialIds;
126
142
  private scheduleTosSignedUrlRefresh;
127
143
  private refreshExpiringTosUrls;
@@ -149,6 +165,10 @@ export declare class AmkEditor {
149
165
  * 适配只作用于即将提交给导出接口的 editParam 副本,不写回工程或当前预览。
150
166
  */
151
167
  private submitExport;
168
+ private startExportTaskStatusPolling;
169
+ private refreshLatestExportTasks;
170
+ private loadLatestExportTasks;
171
+ private clearExportTaskPolling;
152
172
  private attach;
153
173
  private detach;
154
174
  private clearAsrPollingTimers;
@@ -252,6 +272,8 @@ export declare class AmkEditor {
252
272
  */
253
273
  private ensureMaterialExtractTasks;
254
274
  private createExtractFramesTask;
275
+ /** AMK 转存到私有 TOS 后,任务产物需先重签才能用于浏览器预览。 */
276
+ private signTaskOutputUrls;
255
277
  private startSpritePolling;
256
278
  private startPosterPolling;
257
279
  private buildSpriteFromExtractResult;
@@ -1,6 +1,8 @@
1
1
  import type { AmkEditorGetHeaders } from '../types';
2
2
  export type AmkApiClientOptions = {
3
3
  endpoint: string;
4
+ /** 当前工程 ID,用于统一注入 tools 请求的 callback_args。 */
5
+ projectId?: string;
4
6
  /** 每次请求前动态获取并原样透传给客户业务代理的请求头。 */
5
7
  getHeaders?: AmkEditorGetHeaders;
6
8
  /** 调用 tools 接口时写入请求体的产物存储目标,例如 `tos://bucket`。 */
@@ -16,13 +18,25 @@ export type AmkInvokeToolParams = {
16
18
  };
17
19
  export declare class AmkApiClient {
18
20
  private readonly baseUrl;
21
+ private readonly projectId?;
19
22
  private readonly getHeaders?;
20
23
  private readonly mediaOutputDestination?;
24
+ private readonly taskToolNames;
25
+ private readonly terminalTaskReports;
26
+ private syncTaskSequence;
21
27
  constructor(options: AmkApiClientOptions);
22
28
  getBaseUrl(): string;
23
29
  invokeTool<T = unknown>(options: AmkInvokeToolParams): Promise<T>;
24
30
  invokeSyncTool<T = unknown>(options: AmkInvokeToolParams): Promise<T>;
31
+ private createSyncTaskId;
32
+ private rememberTaskTool;
33
+ private reportTaskObservation;
25
34
  private mergeToolParams;
35
+ /**
36
+ * callback_args 约定以 JSON 字符串传输。保留调用方已有字段,并统一补充
37
+ * project_id,避免各个工具调用点重复组装且漏传。
38
+ */
39
+ private mergeCallbackArgs;
26
40
  /**
27
41
  * 查询异步任务:GET /api/v1/tasks/{task_id}
28
42
  * @see https://docs.volcengine.com/docs/6448/2278532
@@ -31,6 +45,14 @@ export declare class AmkApiClient {
31
45
  headers?: Record<string, string>;
32
46
  signal?: AbortSignal;
33
47
  }): Promise<T>;
48
+ /** 查询当前工程任务台账;服务端按 submitted_at 倒序返回。 */
49
+ listProjectTasks<T = unknown>(options?: {
50
+ toolNames?: string[];
51
+ page?: number;
52
+ pageSize?: number;
53
+ includeTotal?: boolean;
54
+ signal?: AbortSignal;
55
+ }): Promise<T>;
34
56
  requestJson<T = unknown>(path: string, options?: {
35
57
  method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
36
58
  headers?: Record<string, string>;
@@ -0,0 +1,12 @@
1
+ import { type TaskPollingController } from './task-polling';
2
+ export declare const EXPORT_TASK_POLL_INTERVAL_MS = 5000;
3
+ export type ExportTaskPollingStatus = 'polling' | 'success' | 'failed';
4
+ export declare function resolveExportTaskPollingStatus(payload: unknown): ExportTaskPollingStatus;
5
+ export declare function resolveExportTaskProgress(payload: unknown): number | undefined;
6
+ export declare function resolveExportTaskOutputUrl(payload: unknown): string | undefined;
7
+ export declare function startExportTaskPolling(options: {
8
+ taskId: string;
9
+ getTask: (taskId: string) => Promise<unknown>;
10
+ onStatusChange: (status: ExportTaskPollingStatus, payload?: unknown) => void | Promise<void>;
11
+ onError?: (error: unknown) => void;
12
+ }): TaskPollingController;
package/dist/header.d.ts CHANGED
@@ -9,9 +9,13 @@ export interface CreateAmkEditorLayoutOptions {
9
9
  title: string;
10
10
  theme?: 'light' | 'dark';
11
11
  showHeader: boolean;
12
+ /** 是否展示导出任务列表入口,默认开启。 */
13
+ showExportTaskList?: boolean;
12
14
  /** When set, append the header here instead of inside the editor root. */
13
15
  headerMount?: HTMLElement;
14
16
  onExport: () => void;
17
+ /** 导出任务列表每次从关闭变为展开时触发。 */
18
+ onExportTasksOpen?: () => void | Promise<void>;
15
19
  /** 传入则展示返回按钮 */
16
20
  onBack?: () => void;
17
21
  /** 传入则展示关闭按钮 */
@@ -20,11 +24,25 @@ export interface CreateAmkEditorLayoutOptions {
20
24
  t?: AmkI18nInstance['t'];
21
25
  }
22
26
  export type AmkSaveStatus = 'saving' | 'saved';
27
+ export type AmkExportTaskStatus = 'idle' | 'polling' | 'success' | 'failed';
28
+ export type AmkExportTaskListItem = {
29
+ taskId: string;
30
+ name: string;
31
+ format: 'mp4' | 'mp3';
32
+ status: Exclude<AmkExportTaskStatus, 'idle'>;
33
+ /** 服务端返回的任务进度(0-100);没有进度时使用不定长动画。 */
34
+ progress?: number;
35
+ /** 是否已在当前页面触发过浏览器下载。 */
36
+ downloaded?: boolean;
37
+ outputUrl?: string;
38
+ };
23
39
  export interface AmkEditorLayout {
24
40
  root: HTMLDivElement;
25
41
  workspace: HTMLDivElement;
26
42
  setTitle: (title: string) => void;
27
43
  setSaveStatus: (status: AmkSaveStatus) => void;
44
+ setExportTasks: (tasks: AmkExportTaskListItem[]) => void;
45
+ openExportTasks: () => void;
28
46
  destroy: () => void;
29
47
  }
30
48
  export declare function resolveHeaderTitle(options: ResolveHeaderTitleOptions): string;
@@ -16,6 +16,21 @@ export declare const AMK_I18N_KEYS: {
16
16
  readonly saving: "amk.header.saving";
17
17
  readonly saved: "amk.header.saved";
18
18
  readonly exportVideo: "amk.header.exportVideo";
19
+ readonly exportTasks: "amk.header.exportTasks";
20
+ readonly exportTaskTooltip: "amk.header.exportTaskTooltip";
21
+ readonly exportTaskPolling: "amk.header.exportTaskPolling";
22
+ readonly exportTaskSuccess: "amk.header.exportTaskSuccess";
23
+ readonly exportTaskFailed: "amk.header.exportTaskFailed";
24
+ readonly exportTaskEmpty: "amk.header.exportTaskEmpty";
25
+ readonly exportTaskDownloadReady: "amk.header.exportTaskDownloadReady";
26
+ readonly exportTaskDownload: "amk.header.exportTaskDownload";
27
+ readonly exportTaskDownloadAgain: "amk.header.exportTaskDownloadAgain";
28
+ readonly exportTaskDownloading: "amk.header.exportTaskDownloading";
29
+ readonly exportTaskDownloadFailed: "amk.header.exportTaskDownloadFailed";
30
+ readonly exportTaskDownloadCorsHint: "amk.header.exportTaskDownloadCorsHint";
31
+ readonly exportTaskView: "amk.header.exportTaskView";
32
+ readonly exportTaskVideo: "amk.header.exportTaskVideo";
33
+ readonly exportTaskAudio: "amk.header.exportTaskAudio";
19
34
  readonly titleRuleEmpty: "amk.header.titleRuleEmpty";
20
35
  readonly titleRuleMaxLength: "amk.header.titleRuleMaxLength";
21
36
  readonly titleRuleCharset: "amk.header.titleRuleCharset";