@meframe/server 0.0.5 → 0.0.6
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/dist/cjs/ServerExporterBase.js +55 -0
- package/dist/cjs/ServerExporterBase.js.map +1 -1
- package/dist/cjs/postprocess/ffmpeg-audio-mix.js +275 -0
- package/dist/cjs/postprocess/ffmpeg-audio-mix.js.map +1 -0
- package/dist/cjs/utils/multipart-upload.js +77 -0
- package/dist/cjs/utils/multipart-upload.js.map +1 -0
- package/dist/esm/ServerExporterBase.d.ts.map +1 -1
- package/dist/esm/ServerExporterBase.js +55 -0
- package/dist/esm/ServerExporterBase.js.map +1 -1
- package/dist/esm/postprocess/ffmpeg-audio-mix.d.ts +46 -0
- package/dist/esm/postprocess/ffmpeg-audio-mix.d.ts.map +1 -0
- package/dist/esm/postprocess/ffmpeg-audio-mix.js +268 -0
- package/dist/esm/postprocess/ffmpeg-audio-mix.js.map +1 -0
- package/dist/esm/types.d.ts +54 -0
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/utils/multipart-upload.d.ts +15 -0
- package/dist/esm/utils/multipart-upload.d.ts.map +1 -0
- package/dist/esm/utils/multipart-upload.js +71 -0
- package/dist/esm/utils/multipart-upload.js.map +1 -0
- package/docs/INTEGRATION.md +79 -0
- package/package.json +1 -1
package/docs/INTEGRATION.md
CHANGED
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
|
|
19
19
|
其他(draft 获取方式、存储 SDK、配置系统、队列/超时/重试)都由上层应用自行决定。
|
|
20
20
|
|
|
21
|
+
> 可选但强烈建议(生产环境常见需求):
|
|
22
|
+
>
|
|
23
|
+
> - **FFmpeg(用于音频后处理兜底)**:当浏览器运行时不支持 AAC 编码时,`@meframe/core` 会跳过音频导出;此时可由 `@meframe/server` 触发 FFmpeg 后处理,把音频混合并 remux 回 MP4。
|
|
24
|
+
|
|
21
25
|
### 1. 安装依赖
|
|
22
26
|
|
|
23
27
|
```bash
|
|
@@ -56,6 +60,16 @@ WebCodecs 等 API 需要 secure/trustworthy origin。`exportToStore({ pageUrl })
|
|
|
56
60
|
|
|
57
61
|
> 核心原则:`CompositionModelData.resources[*].uri`、`workerPath` 指向的文件,都必须能在 Chromium 里直接 `fetch()`/加载到。
|
|
58
62
|
|
|
63
|
+
#### 2.4 音频(AAC)能力说明(强烈建议阅读)
|
|
64
|
+
|
|
65
|
+
当前 `mp4` 输出的音频轨 **只能是 AAC**(对应 WebCodecs `AudioEncoder` 的 `codec: 'mp4a.40.2'`)。
|
|
66
|
+
|
|
67
|
+
- 在某些 Linux Chrome/Chromium 运行时(尤其是容器/精简发行版),**可能存在 `AudioEncoder` 可用但 AAC encode 不支持** 的情况。
|
|
68
|
+
- 这会导致 `@meframe/core` 在导出阶段 emit 一条包含 `Audio skipped:` 的 progress message,并继续导出 **video-only MP4**。
|
|
69
|
+
- 如果你的业务 **必须输出带音频的 MP4**,建议启用 `@meframe/server` 的 **FFmpeg 音频后处理兜底**(见下文 5.x)。
|
|
70
|
+
|
|
71
|
+
> 重要:这是运行时能力差异,不是业务代码“参数写错”。在不支持 AAC encode 的环境里,单纯升/降 Chrome 版本通常不可靠;生产上更稳的是启用 FFmpeg 兜底。
|
|
72
|
+
|
|
59
73
|
### 3. 用 `@meframe/adapter-medeo`:Draft → `CompositionModelData`
|
|
60
74
|
|
|
61
75
|
`@meframe/server` 不关心你的业务数据长什么样,它只吃 `CompositionModelData`。
|
|
@@ -345,6 +359,41 @@ export async function exportMedeoDraftToMp4(input: {
|
|
|
345
359
|
partSizeBytes: 16 * 1024 * 1024,
|
|
346
360
|
contentType: 'video/mp4',
|
|
347
361
|
},
|
|
362
|
+
// 可选:FFmpeg 音频后处理兜底(建议生产开启,尤其是 Linux 运行时)
|
|
363
|
+
//
|
|
364
|
+
// 触发条件:
|
|
365
|
+
// - 浏览器不支持 AAC encode → @meframe/core 会 emit `Audio skipped: ...`
|
|
366
|
+
// - @meframe/server 捕获到该 message 后,在 MP4 已上传完成的基础上运行 FFmpeg
|
|
367
|
+
//
|
|
368
|
+
// 返回值/时序:
|
|
369
|
+
// - 默认会等待后处理完成后才 resolve 并返回最终 key
|
|
370
|
+
// - 如果后处理失败:
|
|
371
|
+
// - onFailure='fallback'(默认):返回原始 video-only MP4 的 key
|
|
372
|
+
// - onFailure='throw':直接 fail 整个任务
|
|
373
|
+
//
|
|
374
|
+
// 依赖:
|
|
375
|
+
// - 运行环境需要可执行的 ffmpeg/ffprobe(默认从 PATH 解析)
|
|
376
|
+
postProcess: {
|
|
377
|
+
ffmpegAudioMix: {
|
|
378
|
+
enabled: true,
|
|
379
|
+
// 可选:覆盖输出 key(默认覆盖原 key)
|
|
380
|
+
// outputKey: outputKey.replace(/\.mp4$/, '.with-audio.mp4'),
|
|
381
|
+
// 可选:失败策略(默认 fallback)
|
|
382
|
+
// onFailure: 'fallback',
|
|
383
|
+
// 可选:ffmpeg/ffprobe 路径
|
|
384
|
+
// ffmpegPath: 'ffmpeg',
|
|
385
|
+
// ffprobePath: 'ffprobe',
|
|
386
|
+
// 必填:提供一种方式让 FFmpeg 能“读回”刚上传的 video-only MP4
|
|
387
|
+
// - 推荐:返回一个可直连的 GET URL(例如 S3 presigned GET)
|
|
388
|
+
// - 或者:如果你的存储可以落盘,返回本地 filePath
|
|
389
|
+
resolveUploadedInput: async ({ key }) => {
|
|
390
|
+
// 示例(伪代码):生成一个供 FFmpeg 使用的 presigned GET URL
|
|
391
|
+
// const url = await presignGetObjectUrl({ key, expiresInSeconds: 3600 });
|
|
392
|
+
// return { kind: 'url', url };
|
|
393
|
+
throw new Error(`resolveUploadedInput is not implemented for key: ${key}`);
|
|
394
|
+
},
|
|
395
|
+
},
|
|
396
|
+
},
|
|
348
397
|
onProgress: (evt) => {
|
|
349
398
|
// evt: { jobId, progress, stage, timeUs? }
|
|
350
399
|
// 这里建议你把进度转发到任务系统/日志/指标
|
|
@@ -366,6 +415,23 @@ export async function exportMedeoDraftToMp4(input: {
|
|
|
366
415
|
}
|
|
367
416
|
```
|
|
368
417
|
|
|
418
|
+
#### 5.1 `resolveUploadedInput` 的设计建议(生产强相关)
|
|
419
|
+
|
|
420
|
+
`ffmpegAudioMix.resolveUploadedInput()` 的目标是:**让 FFmpeg/FFprobe 能读取到已经上传完成的 video-only MP4**。
|
|
421
|
+
|
|
422
|
+
推荐两种实现:
|
|
423
|
+
|
|
424
|
+
- **URL 方式(推荐)**:返回 `{ kind: 'url', url, headers? }`
|
|
425
|
+
- 典型实现:对象存储的 presigned GET URL(必要时附带 headers)
|
|
426
|
+
- 优点:不依赖本地磁盘、适合多机/容器部署
|
|
427
|
+
- **文件方式**:返回 `{ kind: 'file', filePath }`
|
|
428
|
+
- 适合你本来就会把导出结果落盘的场景
|
|
429
|
+
|
|
430
|
+
注意:
|
|
431
|
+
|
|
432
|
+
- 这是 Node 侧的读取路径,与 runner 的 multipart PUT 上传是两条独立链路
|
|
433
|
+
- 对 URL 方式,确保运行环境网络可达,且必要时带上鉴权 headers
|
|
434
|
+
|
|
369
435
|
### 6. 取消与超时(建议)
|
|
370
436
|
|
|
371
437
|
`exportToStore` 支持 `AbortSignal`(best-effort):
|
|
@@ -400,3 +466,16 @@ multipart 上传必须满足:
|
|
|
400
466
|
- 每个 part 都完整、连续覆盖;runner 已做 range 覆盖校验
|
|
401
467
|
- `ETag` 必须正确回传给 Node 并用于 complete
|
|
402
468
|
- 对象存储端的 `CompleteMultipartUpload` parts 顺序必须正确(按 partNumber)
|
|
469
|
+
|
|
470
|
+
#### 7.4 “导出成功但没声音”(Linux 上常见)
|
|
471
|
+
|
|
472
|
+
如果你看到进度里出现类似 message:
|
|
473
|
+
|
|
474
|
+
- `Audio skipped: WebCodecs AAC (mp4a.40.2) AudioEncoder is not supported in this browser/runtime.`
|
|
475
|
+
|
|
476
|
+
那么这是运行时不支持 AAC encode 导致的正常行为,结果会是 **video-only MP4**。
|
|
477
|
+
|
|
478
|
+
解决建议:
|
|
479
|
+
|
|
480
|
+
- **推荐**:启用 `postProcess.ffmpegAudioMix`,用 FFmpeg 生成 AAC 并 remux(见 5.x)
|
|
481
|
+
- 如果你不想引入 FFmpeg:只能更换运行时/镜像/发行版,确保 WebCodecs AAC encode 可用(不建议依赖“碰巧某个版本可用”)
|
package/package.json
CHANGED