daily-video-editor 0.0.5 → 0.1.1

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,138 +1,276 @@
1
- # video-clips
2
-
3
- 视频合成编辑器。打包后宿主只需 Vue,不必再装 Pinia、全局 Element Plus 或 Tailwind。
4
-
5
- ## 接入
6
-
7
- ```ts
8
- import { createApp, ref } from "vue";
9
- import {
10
- createDefaultVideoComposeEditorModel,
11
- VideoComposeEditor,
12
- type VideoComposeEditorExpose,
13
- type VideoComposeEditorModel,
14
- } from "video-clips";
15
- import "video-clips/style.css";
16
-
17
- const model = ref<VideoComposeEditorModel>(
18
- createDefaultVideoComposeEditorModel({
19
- bizType: "source_video",
20
- bizId: "local",
21
- }),
22
- );
23
- const editorRef = ref<VideoComposeEditorExpose | null>(null);
24
-
25
- createApp(App).mount("#app");
26
- ```
27
-
28
- ```vue
29
- <VideoComposeEditor ref="editorRef" v-model="model" />
30
- ```
31
-
32
- `peerDependencies` 只有 `vue`。`pinia`、`element-plus` 随包安装,并在编辑器内部使用:每个时间轴自建一份 Pinia,同页多个编辑器不会抢轨。
33
-
34
- 换稿必须调用 `editorRef.reload(model)`。只改 `v-model` 引用不会回灌时间轴。
35
-
36
- ## 组件 Ref(`VideoComposeEditorExpose`)
37
-
38
- | 方法 | 说明 |
39
- | --- | --- |
40
- | `validate(): string \| null` | 导出前校验。`null` 表示通过,否则为错误文案 |
41
- | `flush(): void` | 立刻把当前轨道、喜欢态、缩放写入 `update:modelValue` |
42
- | `reload(model): Promise<void>` | 用指定工程整页重置时间轴。换稿只走这个方法 |
43
- | `exportComposePayload()` | 先 `flush`,再返回 `{ id, bizType, bizId, tracks }` |
44
- | `getMainVideoClips()` | 主轨视频片段。优先读时间轴,否则用派生列表 |
45
- | `requestUploadClip()` | 触发上传视频:有 `onRequestUploadClip` 则交给宿主,否则走内置上传 |
46
-
47
- ## 公共类型
48
-
49
- 声明在 `dist/index.d.ts`。包根导出:
50
-
51
- - 组件与工厂:`VideoComposeEditor`、`createDefaultVideoComposeEditorModel`
52
- - 工程:`VideoComposeEditorModel`、`ComposeExportPayload`、`ComposeTrack`、`ComposeClip`、`MediaBizType`、`MediaRef`、`ComposeSegmentClipAssets`
53
- - 侧栏种子:`BgmItem`、`TextTemplateItem`、`VideoClipItem`
54
- - 入参与上传:`ComposeEditorProps`、`ComposeUploadAdapter`、`ComposeBgmUploadResult`、`ComposeCatalogUploadPayload`
55
- - Ref:`VideoComposeEditorExpose`
56
- - 轨道片段:`MediaClip`、`SubtitleClip`、`TextClip`、`TrackType`
57
- - 媒体地址:`createComposeMediaResolver`、`isPassthroughMediaUrl`、`mediaCorsMessage`、`ComposeMediaResolver`、`ResolveMediaUrl`
58
-
59
- 字段含义以声明文件为准。
60
-
61
- ## 发包
62
-
63
- `package.json` 保持 `"private": true`。本包默认不发到公共 npm。
64
-
65
- 安装方式:monorepo workspace、`file:` 依赖,或私有 registry。类型入口是 `dist/index.d.ts`(`files` 含整个 `dist`)。要公开发到 npm 时,须先去掉 `private`,再按公开发布流程处理,不走上述私有安装约定。
66
-
67
- 构建:
68
-
69
- ```bash
70
- npm run build
71
- ```
72
-
73
- 库产物:
74
-
75
- - `dist/index.js`
76
- - `dist/index.d.ts`
77
- - `dist/style.css`
78
- - `dist/algorithm/`
79
-
80
- ## 产物部署
81
-
82
- 宿主必须引入样式,否则编辑器没有皮肤:
83
-
84
- ```ts
85
- import "video-clips/style.css";
86
- ```
87
-
88
- 美颜预览 Worker 在 `npm run build` 时内联进 `dist/index.js`。不要单独部署 worker 文件,也不要再准备 `/assets/beautyPreview.worker-*.js`。
89
-
90
- `dist/algorithm/` 仍须挂到宿主静态目录。默认从站点根路径 `/algorithm/` 读取:
91
-
92
- - `/algorithm/face_landmarker.task`
93
- - `/algorithm/mediapipe/`
94
-
95
- 本地 demo 使用 `public/algorithm/`。库构建只拷贝这两项到 `dist/algorithm/`。挂好后可用 `algorithmBaseUrl` 改根路径(须是目录,并能拼出上述两个相对路径)。
96
-
97
- ## 侧栏素材(不进工程 JSON)
98
-
99
- 视频 / 音频 / 音效 / 花字列表由 **Editor 内部数组**维护,**不写入** `v-model`(`model` 只有 tracks、likedMedia、scale 等)。
100
-
101
- 可用 props 作种子;上传成功事件载荷为:
102
-
103
- ```ts
104
- { file: File; item: T; items: T[] }
105
- ```
106
-
107
- 宿主可把 `items` 回写到自己的状态。纯 `onRequestUpload*` 由宿主自管 UX,不走该 emit。
108
-
109
- ## 跨域媒体
110
-
111
- 预览、缩略图和美颜抽帧都要能读取像素。编辑器会:
112
-
113
- - 给 `video` / `audio` 设置 `crossorigin="anonymous"`
114
- - 对跨域地址默认 `fetch`(`mode: "cors"`)并转成 `blob:`
115
- - 同源、`blob:`、`data:` 原样使用
116
-
117
- 源站需要:
118
-
119
- ```
120
- Access-Control-Allow-Origin: <页面源> 或 *
121
- Access-Control-Allow-Methods: GET
122
- ```
123
-
124
- 没有 CORS 头时,默认 fetch 会失败,界面提示配置 `resolveMediaUrl`。宿主把地址换成同源代理或 blob:
125
-
126
- ```ts
127
- async function proxyToBlob(url: string): Promise<string> {
128
- const response = await fetch(`/api/media-proxy?url=${encodeURIComponent(url)}`);
129
- if (!response.ok) throw new Error("媒体代理失败");
130
- return URL.createObjectURL(await response.blob());
131
- }
132
- ```
133
-
134
- ```vue
135
- <VideoComposeEditor v-model="model" :resolve-media-url="proxyToBlob" />
136
- ```
137
-
138
- 本仓库不实现代理服务。
1
+ # 天天视频剪辑
2
+
3
+ Vue 3 多轨视频合成编辑器(npm 包名 `daily-video-editor`)。提供素材栏、预览器、参数侧栏与时间轴。
4
+
5
+ > **当前仍处于迭代阶段。** API、工程 JSON 与 UI 可能随版本调整。后续计划陆续推出:**自定义字体**、**视频画面调色**、**前端合成**等能力。字段含义以 `dist/index.d.ts` 为准。
6
+
7
+ ## 安装
8
+
9
+ 需已安装 **Vue 3.5+**(`peerDependencies`)。
10
+
11
+ ```bash
12
+ npm install daily-video-editor
13
+ ```
14
+
15
+ 也可用:
16
+
17
+ ```bash
18
+ pnpm add daily-video-editor
19
+ # 或
20
+ yarn add daily-video-editor
21
+ ```
22
+
23
+ 安装后在入口引入样式(缺一不可):
24
+
25
+ ```ts
26
+ import "daily-video-editor/style.css";
27
+ ```
28
+
29
+ 本地联调或未发布到 registry 时,可用路径依赖:
30
+
31
+ ```bash
32
+ # 相对路径 / 绝对路径
33
+ npm install ../VIDEO-Clips
34
+ # 或 package.json
35
+ # "daily-video-editor": "file:../VIDEO-Clips"
36
+ ```
37
+
38
+ 使用源码路径依赖前,请在本仓库执行 `npm run build`,确保存在 `dist/`。monorepo 可用 workspace 协议指向本包。
39
+
40
+ ## 快速接入
41
+
42
+ ```ts
43
+ import { createApp, ref } from "vue";
44
+ import {
45
+ createDefaultVideoComposeEditorModel,
46
+ VideoComposeEditor,
47
+ type VideoComposeEditorExpose,
48
+ type VideoComposeEditorModel,
49
+ } from "daily-video-editor";
50
+ import "daily-video-editor/style.css";
51
+
52
+ const model = ref<VideoComposeEditorModel>(
53
+ createDefaultVideoComposeEditorModel({
54
+ bizType: "source_video",
55
+ bizId: "local",
56
+ }),
57
+ );
58
+ const editorRef = ref<VideoComposeEditorExpose | null>(null);
59
+
60
+ createApp(App).mount("#app");
61
+ ```
62
+
63
+ ```vue
64
+ <VideoComposeEditor ref="editorRef" v-model="model" />
65
+ ```
66
+
67
+ **换稿必须调用 `editorRef.reload(model)`。** 只改 `v-model` 引用不会回灌时间轴。
68
+
69
+ `peerDependencies` 只有 `vue`。
70
+
71
+ ---
72
+
73
+ ## 导出数据结构
74
+
75
+ ### `ComposeExportPayload`(成片请求快照)
76
+
77
+ 调用 `exportComposePayload()` 返回。先 `flush`,再取当前工程:
78
+
79
+ | 字段 | 类型 | 说明 |
80
+ | --------- | ------------------ | -------------------------- |
81
+ | `id` | `string` | 合成草稿主键 |
82
+ | `bizType` | `MediaBizType` | 业务类型 |
83
+ | `bizId` | `string \| number` | 业务实体 id |
84
+ | `tracks` | `ComposeTrack[]` | 多轨列表(渲染侧主要消费) |
85
+
86
+ ### `VideoComposeEditorModel`(v-model / 持久化真相源)
87
+
88
+ | 字段 | 类型 | 说明 |
89
+ | -------------------------- | ------------------ | ------------------------------ |
90
+ | `id` | `string` | 合成草稿主键 |
91
+ | `bizType` | `MediaBizType` | 业务类型 |
92
+ | `bizId` | `string \| number` | 业务实体 id |
93
+ | `tracks` | `ComposeTrack[]` | 多轨列表 |
94
+ | `scale?` | `number` | 时间轴显示倍率;成片渲染忽略 |
95
+ | `composeExtractAudioUrls?` | `string[]` | 兼容旧工程抽轨 URL;本地仅透传 |
96
+
97
+ 侧栏视频 / 音频 / 音效 / 字幕 / 花字列表由 **Editor 内部数组**维护,**不写入** `v-model`。
98
+
99
+ ### `ComposeTrack`
100
+
101
+ | 字段 | 类型 | 说明 |
102
+ | ------------------------------------------ | -------------------- | ------------------------------------------------------ |
103
+ | `id` | `string` | 轨道唯一 id |
104
+ | `type` | `TrackType` | 轨道类型(如 `video` / `audio` / `subtitle` / `text`) |
105
+ | `name` | `string` | 展示名 |
106
+ | `isMain?` | `boolean` | 是否主视频轨 |
107
+ | `visible` | `boolean` | 是否可见 |
108
+ | `locked` | `boolean` | 是否锁定 |
109
+ | `muted?` | `boolean` | 音频轨整轨静音 |
110
+ | `clips` | `ComposeClip[]` | 轨道片段 |
111
+ | `order` | `number` | 排序 |
112
+ | `frameAspect?` | `ComposeFrameAspect` | 视频轨画幅 |
113
+ | `nativeFrameWidth?` / `nativeFrameHeight?` | `number` | 原画像素 |
114
+
115
+ ### `ComposeClip`
116
+
117
+ 本期支持:`MediaClip`(`video` \| `audio`)| `ComposeSubtitleClip` | `TextClip`。
118
+
119
+ 共性字段见 `BaseClip`(`id`、`trackId`、`startTime` / `endTime`、`rect`、`visible`、`config` 等)。
120
+
121
+ - **视频 / 音频**:`sourceUrl`、`trimStart` / `trimEnd`、`playbackRate`、`volume` 等;业务扩展在 `config`(美颜、画面变换、抽轨关联等)
122
+ - **字幕**:文案与字体样式,另含 ASS 扩展(`bold` / `italic` / `alignment` / 边距等)
123
+ - **花字(贴图)**:`text`、`fontSize`、`color`;模板资源在 `config.sourceUrl` / `config.templateId`
124
+
125
+ 可用 `createDefaultVideoComposeEditorModel({ bizType, bizId })` 创建空工程。
126
+
127
+ ---
128
+
129
+ ## 组件 Ref 方法(`VideoComposeEditorExpose`)
130
+
131
+ | 方法 | 说明 |
132
+ | ---------------------------------------------- | ----------------------------------------------------------------- |
133
+ | `validate(): string \| null` | 导出前校验。`null` 表示通过,否则为错误文案 |
134
+ | `flush(): void` | 立刻把当前轨道、缩放等写入 `update:modelValue` |
135
+ | `reload(model): Promise<void>` | 用指定工程整页重置时间轴。换稿只走这个方法 |
136
+ | `exportComposePayload(): ComposeExportPayload` | 先 `flush`,再返回 `{ id, bizType, bizId, tracks }` |
137
+ | `getMainVideoClips(): VideoClipItem[]` | 主轨视频片段。优先读时间轴,否则用派生列表 |
138
+ | `requestUploadClip(): void` | 触发上传视频:有 `onRequestUploadClip` 则交给宿主,否则走内置上传 |
139
+ | `getEditingClip(): ComposeClip \| null` | 右栏 inspector 当前类型对应的选中 clip |
140
+ | `getSelectedClips(): ComposeClip[]` | 当前时间轴多选解析后的 clip 列表 |
141
+
142
+ ---
143
+
144
+ ## 插槽(Slots)
145
+
146
+ 未传入时走内置默认 UI;传入后替换对应区域。
147
+
148
+ ### 素材栏操作区
149
+
150
+ 替换各分类「上传 / 添加」入口(有插槽时不再渲染默认按钮):
151
+
152
+ | 插槽名 | 位置 |
153
+ | ------------------ | -------- |
154
+ | `video-actions` | 视频素材 |
155
+ | `audio-actions` | 音频 |
156
+ | `subtitle-actions` | 字幕 |
157
+ | `fancy-actions` | 花字 |
158
+ | `sfx-actions` | 音效 |
159
+
160
+ ### 参数侧栏「应用到全局」之前
161
+
162
+ 供宿主插入自定义控件:
163
+
164
+ | 插槽名 | 对应 inspector |
165
+ | ----------------------- | -------------- |
166
+ | `before-apply-video` | 视频 |
167
+ | `before-apply-audio` | 音频 |
168
+ | `before-apply-subtitle` | 字幕 |
169
+ | `before-apply-text` | 花字 / 贴图 |
170
+
171
+ ### 时间轴(透传 clip-track 具名 slot)
172
+
173
+ | 插槽名 | 位置 / 用途 | 插槽 props |
174
+ | -------------------- | ------------------------------------------- | ----------- |
175
+ | `toolbar-before` | 工具栏整条之前 | — |
176
+ | `toolbar-after` | 工具栏整条之后 | — |
177
+ | `operations-prepend` | 顶部操作按钮区前 | — |
178
+ | `operations-append` | 顶部操作按钮区后 | — |
179
+ | `track-control` | 轨道右侧操作区;追加在内置静音/向前对齐之后 | `{ track }` |
180
+
181
+ 说明:
182
+
183
+ - `readonly` 时工具栏不渲染,`toolbar-*` / `operations-*` 不可见。
184
+ - `track-control` 内宿主内容不会自动跟随 `readonly` 禁用,需宿主自行处理。
185
+
186
+ ```vue
187
+ <VideoComposeEditor v-model="model">
188
+ <template #video-actions>
189
+ <button type="button" @click="openHostUploader">自定义上传</button>
190
+ </template>
191
+ <template #before-apply-video>
192
+ <!-- 宿主扩展控件 -->
193
+ </template>
194
+ <template #operations-append>
195
+ <!-- 工具栏操作区末尾;readonly 时不可见 -->
196
+ </template>
197
+ <template #track-control="{ track }">
198
+ <!-- 追加在静音/对齐之后;需自行处理 readonly 禁用 -->
199
+ </template>
200
+ </VideoComposeEditor>
201
+ ```
202
+
203
+ ---
204
+
205
+ ## Props / 事件(摘要)
206
+
207
+ 常用 Props:`modelValue`、`readonly`、`videoAssets` / `audioAssets` / `sfxAssets` / `subtitleAssets` / `textTemplates`、`uploadAdapter`、`onRequestUploadClip` 等、`resolveMediaUrl`、`algorithmBaseUrl`、`trackTypes`。
208
+
209
+ 常用事件:`update:modelValue`、`ready`、`remove-catalog-clip`、`toggle-like`、`video-uploaded` / `audio-uploaded` / `sfx-uploaded` / `text-template-uploaded`、`selection-changed`。
210
+
211
+ 上传成功事件载荷:`{ file: File; item: T; items: T[] }`。纯 `onRequestUpload*` 由宿主自管 UX,不走该 emit。
212
+
213
+ ---
214
+
215
+ ## 公共类型(包根导出)
216
+
217
+ - 组件与工厂:`VideoComposeEditor`、`createDefaultVideoComposeEditorModel`
218
+ - 工程:`VideoComposeEditorModel`、`ComposeExportPayload`、`ComposeTrack`、`ComposeClip`、`MediaBizType`、`MediaRef`、`ComposeSegmentClipAssets`
219
+ - 侧栏种子:`BgmItem`、`TextTemplateItem`、`VideoClipItem`
220
+ - 入参与上传:`ComposeEditorProps`、`ComposeUploadAdapter`、`ComposeBgmUploadResult`、`ComposeCatalogUploadPayload`
221
+ - Ref:`VideoComposeEditorExpose`
222
+ - 轨道片段:`MediaClip`、`SubtitleClip`、`TextClip`、`TrackType`、`TrackTypeConfig`
223
+ - 媒体地址:`createComposeMediaResolver`、`isPassthroughMediaUrl`、`mediaCorsMessage`、`ComposeMediaResolver`、`ResolveMediaUrl`
224
+
225
+ ---
226
+
227
+ ## 构建与产物
228
+
229
+ ```bash
230
+ npm run build
231
+ ```
232
+
233
+ 库产物:`dist/index.js`、`dist/index.d.ts`、`dist/style.css`、`dist/algorithm/`。
234
+
235
+ 宿主必须引入样式:
236
+
237
+ ```ts
238
+ import "daily-video-editor/style.css";
239
+ ```
240
+
241
+ 美颜预览 Worker 在构建时内联进 `dist/index.js`,无需单独部署。`dist/algorithm/` 须挂到宿主静态目录(默认 `/algorithm/`):
242
+
243
+ - `/algorithm/face_landmarker.task`
244
+ - `/algorithm/mediapipe/`
245
+
246
+ 可用 `algorithmBaseUrl` 改根路径。
247
+
248
+ ---
249
+
250
+ ## 跨域媒体
251
+
252
+ 预览、缩略图和美颜抽帧都要能读取像素。编辑器会给 `video` / `audio` 设 `crossorigin="anonymous"`,对跨域地址默认 CORS `fetch` 并转成 `blob:`。源站需允许 CORS;失败时配置 `resolveMediaUrl` 走同源代理或 blob。本仓库不实现代理服务。
253
+
254
+ ```vue
255
+ <VideoComposeEditor v-model="model" :resolve-media-url="proxyToBlob" />
256
+ ```
257
+
258
+ ---
259
+
260
+ ## 路线图(规划中)
261
+
262
+ | 方向 | 说明 |
263
+ | ------------ | ------------------------------------ |
264
+ | 自定义字体 | 宿主 / 用户字体接入字幕与花字 |
265
+ | 视频画面调色 | 亮度、对比度、色温等画面调整 |
266
+ | 前端合成 | 浏览器端导出成片,减少对后端渲染依赖 |
267
+
268
+ 欢迎在迭代过程中反馈接入问题;正式 API 稳定前请以类型声明与本 README 同步查阅。
269
+
270
+ ---
271
+
272
+ ## 致谢
273
+
274
+ 本项目的时间轴组件基于开源库 [vue-clip-track](https://github.com/caohongz/vue-clip-track) 衍生而来。感谢原作者与贡献者提供的多轨编辑能力——轨道交互、时间轴缩放与片段操作等,为本编辑器打下了坚实基础。
275
+
276
+ 仓库内 `src/clip-track` 已面向合成编辑场景做了定制演进,与上游并非一一对应;欢迎一并了解原项目。
@@ -0,0 +1,2 @@
1
+ declare const _default: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
2
+ export default _default;
@@ -19,7 +19,7 @@ export interface OperationButtonConfig {
19
19
  /** 自定义CSS类名 */
20
20
  className?: string;
21
21
  }
22
- export type OperationButton = "reset" | "undo" | "redo" | "split" | "delete" | CustomButton | OperationButtonConfig;
22
+ export type OperationButton = "reset" | "undo" | "redo" | "split" | "trimLeft" | "trimRight" | "delete" | CustomButton | OperationButtonConfig;
23
23
  export interface ScaleConfigButtonConfig {
24
24
  /** 按钮标识 */
25
25
  key: string;
@@ -138,6 +138,9 @@ export interface LocaleConfig {
138
138
  reset?: string;
139
139
  undo?: string;
140
140
  redo?: string;
141
+ split?: string;
142
+ trimLeft?: string;
143
+ trimRight?: string;
141
144
  delete?: string;
142
145
  play?: string;
143
146
  pause?: string;