@cut-workbench/core 0.3.1 → 0.4.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/dist/chunks/{canvas-size-IzoEg2cq.cjs → canvas-size-DIABzEW2.cjs} +209 -302
- package/dist/chunks/canvas-size-DIABzEW2.cjs.map +1 -0
- package/dist/chunks/{canvas-size-iWL8zZPl.js → canvas-size-Dlnng74w.js} +168 -171
- package/dist/chunks/canvas-size-Dlnng74w.js.map +1 -0
- package/dist/chunks/id-CJsdlGei.js +35 -0
- package/dist/chunks/id-CJsdlGei.js.map +1 -0
- package/dist/chunks/id-DaCxD4-5.cjs +70 -0
- package/dist/chunks/id-DaCxD4-5.cjs.map +1 -0
- package/dist/chunks/rolldown-runtime-B2SfzNBj.cjs +17 -0
- package/dist/chunks/rolldown-runtime-D8jQpDG7.js +12 -0
- package/dist/chunks/{snap-CeYuTN6d.cjs → snap-Cfk15JVg.cjs} +3 -23
- package/dist/chunks/{snap-CeYuTN6d.cjs.map → snap-Cfk15JVg.cjs.map} +1 -1
- package/dist/chunks/{snap-Dc022smD.js → snap-DpkVPVJN.js} +3 -17
- package/dist/chunks/{snap-Dc022smD.js.map → snap-DpkVPVJN.js.map} +1 -1
- package/dist/chunks/srt-D539yJ-n.js +51 -0
- package/dist/chunks/srt-D539yJ-n.js.map +1 -0
- package/dist/chunks/srt-DaL36mXN.cjs +73 -0
- package/dist/chunks/srt-DaL36mXN.cjs.map +1 -0
- package/dist/chunks/thumbnails-DEjnao5r.cjs +81 -0
- package/dist/chunks/thumbnails-DEjnao5r.cjs.map +1 -0
- package/dist/chunks/thumbnails-qH0dX_Zs.js +64 -0
- package/dist/chunks/thumbnails-qH0dX_Zs.js.map +1 -0
- package/dist/chunks/time-CYEd91qN.cjs +196 -0
- package/dist/chunks/time-CYEd91qN.cjs.map +1 -0
- package/dist/chunks/time-ChF1GwCy.js +113 -0
- package/dist/chunks/time-ChF1GwCy.js.map +1 -0
- package/dist/chunks/{waveform-Bhvv2t7-.cjs → waveform-BYwDdKpC.cjs} +150 -31
- package/dist/chunks/waveform-BYwDdKpC.cjs.map +1 -0
- package/dist/chunks/{waveform-CWU8Fa-n.js → waveform-uyGNE01H.js} +111 -22
- package/dist/chunks/waveform-uyGNE01H.js.map +1 -0
- package/dist/editor/create-editor.d.ts +8 -106
- package/dist/editor/editor-store.d.ts +4 -0
- package/dist/editor/handle-types.d.ts +256 -0
- package/dist/engine/index.cjs +1185 -455
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.ts +3 -0
- package/dist/engine/index.js +1169 -446
- package/dist/engine/index.js.map +1 -1
- package/dist/engine/webav/export-runner.d.ts +61 -0
- package/dist/engine/webav/exporter.d.ts +3 -1
- package/dist/engine/webav/import-files.d.ts +58 -0
- package/dist/engine/webav/import-pipeline.d.ts +23 -1
- package/dist/engine/webav/types.d.ts +15 -0
- package/dist/errors.d.ts +12 -0
- package/dist/export/types.d.ts +49 -0
- package/dist/index.cjs +83 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.js +47 -43
- package/dist/index.js.map +1 -1
- package/dist/lib/error.d.ts +6 -0
- package/dist/media/thumbnails.d.ts +8 -0
- package/dist/ports/host-bridge.d.ts +7 -0
- package/dist/project/file-storage.d.ts +23 -0
- package/dist/project/schema.d.ts +16 -4
- package/dist/timeline/index.cjs +24 -19
- package/dist/timeline/index.d.ts +1 -0
- package/dist/timeline/index.js +4 -3
- package/dist/timeline/normalize.d.ts +28 -0
- package/dist/timeline/ops.d.ts +0 -4
- package/dist/timeline/snap.d.ts +0 -2
- package/dist/types.d.ts +14 -2
- package/package.json +3 -2
- package/dist/chunks/canvas-size-IzoEg2cq.cjs.map +0 -1
- package/dist/chunks/canvas-size-iWL8zZPl.js.map +0 -1
- package/dist/chunks/waveform-Bhvv2t7-.cjs.map +0 -1
- package/dist/chunks/waveform-CWU8Fa-n.js.map +0 -1
|
@@ -1,145 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* cut-core 自有常量。
|
|
5
|
-
*
|
|
6
|
-
* 只放「逻辑层必须知道」的数值:默认时长、默认音量、工程 schema 版本、
|
|
7
|
-
* 历史栈深度。UI 相关的量(缩放档位、面板高度、吸附像素阈值)留在宿主侧,
|
|
8
|
-
* 避免组件库被时间轴界面的调参牵着走。
|
|
9
|
-
*/
|
|
10
|
-
/** 图片 / 文字素材默认时长(微秒) */
|
|
11
|
-
var DEFAULT_STILL_DURATION_US = 5e6;
|
|
12
|
-
/** 默认音量,避免多轨直接相加削波 */
|
|
13
|
-
var DEFAULT_CLIP_VOLUME = .8;
|
|
14
|
-
/** 工程 schema 版本 */
|
|
15
|
-
var PROJECT_SCHEMA_VERSION = 1;
|
|
16
|
-
/** 撤销栈最大深度 */
|
|
17
|
-
var MAX_HISTORY_STEPS = 50;
|
|
18
|
-
/**
|
|
19
|
-
* 连续同质操作的合并时间窗口(毫秒)。
|
|
20
|
-
*
|
|
21
|
-
* 拖动滑块 / 画布内拖拽素材时会连续触发大量更新;窗口内相同 mergeKey 的记录
|
|
22
|
-
* 会被合并成一步撤销。取值兼顾「连续拖动算一次」与「停顿后再改算新一步」。
|
|
23
|
-
*/
|
|
24
|
-
var HISTORY_MERGE_WINDOW_MS = 800;
|
|
25
|
-
// src/lib/id.ts
|
|
26
|
-
/**
|
|
27
|
-
* 生成短 id。scope 仅用于可读性(例如 `clip_xxx`),不影响唯一性。
|
|
28
|
-
*/
|
|
29
|
-
function createId(scope) {
|
|
30
|
-
const id = (0, nanoid.nanoid)(10);
|
|
31
|
-
return scope ? `${scope}_${id}` : id;
|
|
32
|
-
}
|
|
33
|
-
// src/timeline/time.ts
|
|
34
|
-
var US_PER_SECOND = 1e6;
|
|
35
|
-
var US_PER_MS = 1e3;
|
|
36
|
-
/** 秒 → 微秒 */
|
|
37
|
-
function secToUs(sec) {
|
|
38
|
-
return Math.round(sec * US_PER_SECOND);
|
|
39
|
-
}
|
|
40
|
-
/** 微秒 → 秒 */
|
|
41
|
-
function usToSec(us) {
|
|
42
|
-
return us / US_PER_SECOND;
|
|
43
|
-
}
|
|
44
|
-
/** 毫秒 → 微秒 */
|
|
45
|
-
function msToUs(ms) {
|
|
46
|
-
return Math.round(ms * US_PER_MS);
|
|
47
|
-
}
|
|
48
|
-
/** 微秒 → 毫秒 */
|
|
49
|
-
function usToMs(us) {
|
|
50
|
-
return Math.round(us / US_PER_MS);
|
|
51
|
-
}
|
|
52
|
-
/** 数字 → 微秒(用于从 DOM/WebAV 回调拿到的裸数字) */
|
|
53
|
-
function asUs(n) {
|
|
54
|
-
return Math.round(n);
|
|
55
|
-
}
|
|
56
|
-
/** 数字 → 像素 */
|
|
57
|
-
function asPx(n) {
|
|
58
|
-
return n;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* 微秒 → 像素。
|
|
62
|
-
* @param us 时间(微秒)
|
|
63
|
-
* @param pxPerSecond 每秒对应多少像素
|
|
64
|
-
*/
|
|
65
|
-
function usToPx(us, pxPerSecond) {
|
|
66
|
-
return us / US_PER_SECOND * pxPerSecond;
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* 像素 → 微秒。
|
|
70
|
-
* @param px 像素
|
|
71
|
-
* @param pxPerSecond 每秒对应多少像素
|
|
72
|
-
*/
|
|
73
|
-
function pxToUs(px, pxPerSecond) {
|
|
74
|
-
return Math.round(px / pxPerSecond * US_PER_SECOND);
|
|
75
|
-
}
|
|
76
|
-
/** 微秒 → `HH:MM:SS.mmm` */
|
|
77
|
-
function formatTimecode(us, showMs = true) {
|
|
78
|
-
const totalMs = Math.floor(Math.max(0, us) / 1e3);
|
|
79
|
-
const ms = totalMs % 1e3;
|
|
80
|
-
const totalSec = Math.floor(totalMs / 1e3);
|
|
81
|
-
const sec = totalSec % 60;
|
|
82
|
-
const min = Math.floor(totalSec / 60) % 60;
|
|
83
|
-
const hour = Math.floor(totalSec / 3600);
|
|
84
|
-
const pad = (n, len = 2) => String(n).padStart(len, "0");
|
|
85
|
-
const base = `${pad(hour)}:${pad(min)}:${pad(sec)}`;
|
|
86
|
-
return showMs ? `${base}.${pad(ms, 3)}` : base;
|
|
87
|
-
}
|
|
88
|
-
/** 微秒 → `MM:SS` 或 `HH:MM:SS`,列表展示用 */
|
|
89
|
-
function formatDuration(us) {
|
|
90
|
-
if (!Number.isFinite(us)) return "∞";
|
|
91
|
-
const totalSec = Math.max(0, Math.round(us / US_PER_SECOND));
|
|
92
|
-
const sec = totalSec % 60;
|
|
93
|
-
const min = Math.floor(totalSec / 60) % 60;
|
|
94
|
-
const hour = Math.floor(totalSec / 3600);
|
|
95
|
-
const pad = (n) => String(n).padStart(2, "0");
|
|
96
|
-
return hour > 0 ? `${hour}:${pad(min)}:${pad(sec)}` : `${pad(min)}:${pad(sec)}`;
|
|
97
|
-
}
|
|
98
|
-
var TICK_STEPS_US = [
|
|
99
|
-
1e5,
|
|
100
|
-
2e5,
|
|
101
|
-
5e5,
|
|
102
|
-
1e6,
|
|
103
|
-
2e6,
|
|
104
|
-
5e6,
|
|
105
|
-
1e7,
|
|
106
|
-
15e6,
|
|
107
|
-
3e7,
|
|
108
|
-
6e7,
|
|
109
|
-
12e7,
|
|
110
|
-
3e8,
|
|
111
|
-
6e8
|
|
112
|
-
];
|
|
113
|
-
/**
|
|
114
|
-
* 根据缩放级别生成刻度尺。
|
|
115
|
-
*
|
|
116
|
-
* @param pxPerSecond 每秒像素
|
|
117
|
-
* @param viewportWidthPx 可视宽度(像素)
|
|
118
|
-
* @param scrollLeftPx 横向滚动偏移(像素)
|
|
119
|
-
* @returns 主刻度(带文字)与次刻度
|
|
120
|
-
*/
|
|
121
|
-
function buildTicks(pxPerSecond, viewportWidthPx, scrollLeftPx = 0) {
|
|
122
|
-
const startUs = pxToUs(scrollLeftPx, pxPerSecond);
|
|
123
|
-
const endUs = pxToUs(scrollLeftPx + viewportWidthPx, pxPerSecond);
|
|
124
|
-
const minLabelSpacingPx = 72;
|
|
125
|
-
const step = TICK_STEPS_US.find((s) => usToPx(s, pxPerSecond) >= minLabelSpacingPx) ?? TICK_STEPS_US[TICK_STEPS_US.length - 1];
|
|
126
|
-
const minorStep = step / 5;
|
|
127
|
-
const first = Math.floor(startUs / step) * step;
|
|
128
|
-
const ticks = [];
|
|
129
|
-
for (let us = first; us <= endUs + step; us += minorStep) {
|
|
130
|
-
if (us < 0) continue;
|
|
131
|
-
ticks.push({
|
|
132
|
-
us,
|
|
133
|
-
px: usToPx(us, pxPerSecond),
|
|
134
|
-
major: us % step === 0
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
return ticks;
|
|
138
|
-
}
|
|
139
|
-
/** 保证值落在 [min, max] */
|
|
140
|
-
function clamp(value, min, max) {
|
|
141
|
-
return Math.min(max, Math.max(min, value));
|
|
142
|
-
}
|
|
1
|
+
const require_id = require("./id-DaCxD4-5.cjs");
|
|
2
|
+
const require_time = require("./time-CYEd91qN.cjs");
|
|
143
3
|
// src/timeline/model.ts
|
|
144
4
|
/**
|
|
145
5
|
* 时间轴纯数据模型与工厂函数。
|
|
@@ -149,7 +9,7 @@ function clamp(value, min, max) {
|
|
|
149
9
|
*/
|
|
150
10
|
function createTrack(kind, name) {
|
|
151
11
|
return {
|
|
152
|
-
id: createId("track"),
|
|
12
|
+
id: require_id.createId("track"),
|
|
153
13
|
name,
|
|
154
14
|
kind,
|
|
155
15
|
locked: false,
|
|
@@ -159,7 +19,7 @@ function createTrack(kind, name) {
|
|
|
159
19
|
}
|
|
160
20
|
function createEmptyProject(name = "未命名工程") {
|
|
161
21
|
return {
|
|
162
|
-
id: createId("project"),
|
|
22
|
+
id: require_id.createId("project"),
|
|
163
23
|
name,
|
|
164
24
|
width: 1280,
|
|
165
25
|
height: 720,
|
|
@@ -179,14 +39,14 @@ function createClip(input, project) {
|
|
|
179
39
|
h = Math.round(assetHeight * scale);
|
|
180
40
|
}
|
|
181
41
|
return {
|
|
182
|
-
id: createId("clip"),
|
|
42
|
+
id: require_id.createId("clip"),
|
|
183
43
|
trackId: input.trackId,
|
|
184
44
|
assetId: input.assetId,
|
|
185
|
-
startUs: asUs(input.startUs),
|
|
186
|
-
durationUs: asUs(input.durationUs),
|
|
187
|
-
inPointUs: asUs(input.inPointUs ?? 0),
|
|
45
|
+
startUs: require_time.asUs(input.startUs),
|
|
46
|
+
durationUs: require_time.asUs(input.durationUs),
|
|
47
|
+
inPointUs: require_time.asUs(input.inPointUs ?? 0),
|
|
188
48
|
playbackRate: 1,
|
|
189
|
-
volume: DEFAULT_CLIP_VOLUME,
|
|
49
|
+
volume: require_id.DEFAULT_CLIP_VOLUME,
|
|
190
50
|
muted: false,
|
|
191
51
|
opacity: 1,
|
|
192
52
|
flip: null,
|
|
@@ -197,13 +57,13 @@ function createClip(input, project) {
|
|
|
197
57
|
h,
|
|
198
58
|
angle: 0
|
|
199
59
|
},
|
|
200
|
-
fadeInUs: asUs(0),
|
|
201
|
-
fadeOutUs: asUs(0)
|
|
60
|
+
fadeInUs: require_time.asUs(0),
|
|
61
|
+
fadeOutUs: require_time.asUs(0)
|
|
202
62
|
};
|
|
203
63
|
}
|
|
204
64
|
/** 静态素材(图片 / 文字 / 字幕)需要有限时长 */
|
|
205
65
|
function clampStillDuration(us) {
|
|
206
|
-
return us > 0 && Number.isFinite(us) ? us : DEFAULT_STILL_DURATION_US;
|
|
66
|
+
return us > 0 && Number.isFinite(us) ? us : require_id.DEFAULT_STILL_DURATION_US;
|
|
207
67
|
}
|
|
208
68
|
function getClipEnd(clip) {
|
|
209
69
|
return clip.startUs + clip.durationUs;
|
|
@@ -232,39 +92,176 @@ function getTrackEnd(project, trackId) {
|
|
|
232
92
|
function getSourceSpanUs(clip) {
|
|
233
93
|
return Math.round(clip.durationUs * clip.playbackRate);
|
|
234
94
|
}
|
|
235
|
-
// src/timeline/
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
95
|
+
// src/timeline/normalize.ts
|
|
96
|
+
var DEFAULT_TEXT_STYLE = {
|
|
97
|
+
fontSize: 64,
|
|
98
|
+
color: "#ffffff",
|
|
99
|
+
fontFamily: "sans-serif",
|
|
100
|
+
fontWeight: 600,
|
|
101
|
+
fontStyle: "normal",
|
|
102
|
+
strokeColor: "#000000",
|
|
103
|
+
strokeWidth: 0,
|
|
104
|
+
shadowColor: "rgba(0,0,0,0.6)",
|
|
105
|
+
shadowBlur: 8,
|
|
106
|
+
align: "center",
|
|
107
|
+
background: "transparent"
|
|
108
|
+
};
|
|
109
|
+
var DEFAULT_SUBTITLE_STYLE = {
|
|
110
|
+
color: "#ffffff",
|
|
111
|
+
textBgColor: null,
|
|
112
|
+
fontFamily: "sans-serif",
|
|
113
|
+
fontSize: 30,
|
|
114
|
+
strokeStyle: "#000000",
|
|
115
|
+
lineWidth: null,
|
|
116
|
+
bottomOffset: 30
|
|
117
|
+
};
|
|
118
|
+
function isRecord(value) {
|
|
119
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
120
|
+
}
|
|
121
|
+
/** 有限数值,否则用兜底值 */
|
|
122
|
+
function num(value, fallback) {
|
|
123
|
+
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
124
|
+
}
|
|
125
|
+
function str(value, fallback) {
|
|
126
|
+
return typeof value === "string" && value.length > 0 ? value : fallback;
|
|
127
|
+
}
|
|
128
|
+
/** 补全 clip 的几何变换(缺 transform / 缺子字段都会兜底) */
|
|
129
|
+
function normalizeTransform(raw, projectWidth, projectHeight) {
|
|
130
|
+
const source = isRecord(raw) ? raw : {};
|
|
131
|
+
const w = Math.max(1, num(source.w, projectWidth));
|
|
132
|
+
const h = Math.max(1, num(source.h, projectHeight));
|
|
133
|
+
return {
|
|
134
|
+
x: num(source.x, Math.round((projectWidth - w) / 2)),
|
|
135
|
+
y: num(source.y, Math.round((projectHeight - h) / 2)),
|
|
136
|
+
w,
|
|
137
|
+
h,
|
|
138
|
+
angle: num(source.angle, 0)
|
|
248
139
|
};
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
140
|
+
}
|
|
141
|
+
function normalizeFlip(raw) {
|
|
142
|
+
return raw === "horizontal" || raw === "vertical" ? raw : null;
|
|
143
|
+
}
|
|
144
|
+
/** 补全单个 clip;`id` 缺失时生成一个,保证后续操作可用 */
|
|
145
|
+
function normalizeClip(raw, projectWidth, projectHeight) {
|
|
146
|
+
if (!isRecord(raw)) return null;
|
|
147
|
+
const trackId = typeof raw.trackId === "string" ? raw.trackId : "";
|
|
148
|
+
const assetId = typeof raw.assetId === "string" ? raw.assetId : "";
|
|
149
|
+
if (trackId === "" || assetId === "") return null;
|
|
150
|
+
const durationUs = Math.max(0, num(raw.durationUs, 0));
|
|
151
|
+
const normalized = {
|
|
152
|
+
id: str(raw.id, require_id.createId("clip")),
|
|
153
|
+
trackId,
|
|
154
|
+
assetId,
|
|
155
|
+
startUs: require_time.asUs(Math.max(0, num(raw.startUs, 0))),
|
|
156
|
+
durationUs: require_time.asUs(durationUs),
|
|
157
|
+
inPointUs: require_time.asUs(Math.max(0, num(raw.inPointUs, 0))),
|
|
158
|
+
playbackRate: require_time.clamp(num(raw.playbackRate, 1), .1, 10),
|
|
159
|
+
volume: require_time.clamp(num(raw.volume, require_id.DEFAULT_CLIP_VOLUME), 0, 4),
|
|
160
|
+
muted: raw.muted === true,
|
|
161
|
+
opacity: require_time.clamp(num(raw.opacity, 1), 0, 1),
|
|
162
|
+
flip: normalizeFlip(raw.flip),
|
|
163
|
+
transform: normalizeTransform(raw.transform, projectWidth, projectHeight),
|
|
164
|
+
fadeInUs: require_time.asUs(Math.max(0, num(raw.fadeInUs, 0))),
|
|
165
|
+
fadeOutUs: require_time.asUs(Math.max(0, num(raw.fadeOutUs, 0)))
|
|
166
|
+
};
|
|
167
|
+
if (raw.aspectLocked === true) normalized.aspectLocked = true;
|
|
168
|
+
if (typeof raw.text === "string") normalized.text = raw.text;
|
|
169
|
+
if (isRecord(raw.textStyle)) normalized.textStyle = {
|
|
170
|
+
...DEFAULT_TEXT_STYLE,
|
|
171
|
+
...raw.textStyle
|
|
172
|
+
};
|
|
173
|
+
if (typeof raw.srt === "string") normalized.srt = raw.srt;
|
|
174
|
+
if (isRecord(raw.subtitleStyle)) normalized.subtitleStyle = {
|
|
175
|
+
...DEFAULT_SUBTITLE_STYLE,
|
|
176
|
+
...raw.subtitleStyle
|
|
256
177
|
};
|
|
257
|
-
|
|
258
|
-
return [left, right];
|
|
178
|
+
return normalized;
|
|
259
179
|
}
|
|
260
|
-
|
|
261
|
-
|
|
180
|
+
function normalizeTrack(raw, index) {
|
|
181
|
+
if (!isRecord(raw)) return null;
|
|
182
|
+
const kind = raw.kind === "audio" ? "audio" : "visual";
|
|
262
183
|
return {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
184
|
+
id: str(raw.id, require_id.createId("track")),
|
|
185
|
+
name: str(raw.name, kind === "audio" ? `音频 ${index + 1}` : `视频 ${index + 1}`),
|
|
186
|
+
kind,
|
|
187
|
+
locked: raw.locked === true,
|
|
188
|
+
muted: raw.muted === true,
|
|
189
|
+
hidden: raw.hidden === true
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
/** 补全工程;轨道为空时补一对默认轨道,否则 clip 无处可放 */
|
|
193
|
+
function normalizeProject(raw) {
|
|
194
|
+
if (!isRecord(raw)) return null;
|
|
195
|
+
const width = Math.max(2, Math.round(num(raw.width, 1280)));
|
|
196
|
+
const height = Math.max(2, Math.round(num(raw.height, 720)));
|
|
197
|
+
const tracks = (Array.isArray(raw.tracks) ? raw.tracks : []).map((track, index) => normalizeTrack(track, index)).filter((track) => track != null);
|
|
198
|
+
const effectiveTracks = tracks.length > 0 ? tracks : [{
|
|
199
|
+
id: require_id.createId("track"),
|
|
200
|
+
name: "视频 1",
|
|
201
|
+
kind: "visual",
|
|
202
|
+
locked: false,
|
|
203
|
+
muted: false,
|
|
204
|
+
hidden: false
|
|
205
|
+
}, {
|
|
206
|
+
id: require_id.createId("track"),
|
|
207
|
+
name: "音频 1",
|
|
208
|
+
kind: "audio",
|
|
209
|
+
locked: false,
|
|
210
|
+
muted: false,
|
|
211
|
+
hidden: false
|
|
212
|
+
}];
|
|
213
|
+
const trackIds = new Set(effectiveTracks.map((t) => t.id));
|
|
214
|
+
const clips = (Array.isArray(raw.clips) ? raw.clips : []).map((clip) => normalizeClip(clip, width, height)).filter((clip) => clip != null).filter((clip) => trackIds.has(clip.trackId));
|
|
215
|
+
return {
|
|
216
|
+
id: str(raw.id, require_id.createId("project")),
|
|
217
|
+
name: str(raw.name, "未命名工程"),
|
|
218
|
+
width,
|
|
219
|
+
height,
|
|
220
|
+
tracks: effectiveTracks,
|
|
221
|
+
clips,
|
|
222
|
+
updatedAt: num(raw.updatedAt, Date.now())
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
var KINDS = /* @__PURE__ */ new Set([
|
|
226
|
+
"video",
|
|
227
|
+
"audio",
|
|
228
|
+
"image",
|
|
229
|
+
"text",
|
|
230
|
+
"subtitle"
|
|
231
|
+
]);
|
|
232
|
+
/** 补全素材元数据;`kind` 非法的条目直接丢弃(无法决定如何渲染) */
|
|
233
|
+
function normalizeAsset(raw) {
|
|
234
|
+
if (!isRecord(raw)) return null;
|
|
235
|
+
const kind = KINDS.has(raw.kind) ? raw.kind : null;
|
|
236
|
+
if (kind == null) return null;
|
|
237
|
+
const asset = {
|
|
238
|
+
id: typeof raw.id === "string" && raw.id !== "" ? raw.id : require_id.createId("asset"),
|
|
239
|
+
name: str(raw.name, kind === "video" ? "未命名视频" : "未命名素材"),
|
|
240
|
+
kind,
|
|
241
|
+
mimeType: str(raw.mimeType, "application/octet-stream"),
|
|
242
|
+
size: Math.max(0, num(raw.size, 0)),
|
|
243
|
+
durationUs: require_time.asUs(Math.max(0, num(raw.durationUs, 0))),
|
|
244
|
+
width: Math.max(0, num(raw.width, 0)),
|
|
245
|
+
height: Math.max(0, num(raw.height, 0)),
|
|
246
|
+
hasAudio: raw.hasAudio === true,
|
|
247
|
+
createdAt: num(raw.createdAt, Date.now())
|
|
248
|
+
};
|
|
249
|
+
if (typeof raw.text === "string") asset.text = raw.text;
|
|
250
|
+
if (isRecord(raw.textStyle)) asset.textStyle = {
|
|
251
|
+
...DEFAULT_TEXT_STYLE,
|
|
252
|
+
...raw.textStyle
|
|
253
|
+
};
|
|
254
|
+
if (typeof raw.srt === "string") asset.srt = raw.srt;
|
|
255
|
+
if (isRecord(raw.subtitleStyle)) asset.subtitleStyle = {
|
|
256
|
+
...DEFAULT_SUBTITLE_STYLE,
|
|
257
|
+
...raw.subtitleStyle
|
|
266
258
|
};
|
|
259
|
+
if (Array.isArray(raw.waveform) && raw.waveform.every((v) => typeof v === "number")) asset.waveform = raw.waveform;
|
|
260
|
+
if (typeof raw.sourcePath === "string") asset.sourcePath = raw.sourcePath;
|
|
261
|
+
if ((kind === "image" || kind === "text" || kind === "subtitle") && asset.durationUs <= 0) asset.durationUs = require_time.asUs(require_id.DEFAULT_STILL_DURATION_US);
|
|
262
|
+
return asset;
|
|
267
263
|
}
|
|
264
|
+
// src/timeline/ops.ts
|
|
268
265
|
/**
|
|
269
266
|
* 裁剪 clip 的边缘。
|
|
270
267
|
*
|
|
@@ -282,15 +279,15 @@ function trimClipData(clip, edge, deltaUs, minDurationUs = 1e5) {
|
|
|
282
279
|
const nextInPoint = Math.max(0, clip.inPointUs + sourceDelta);
|
|
283
280
|
return {
|
|
284
281
|
...clip,
|
|
285
|
-
startUs: asUs(nextStart),
|
|
286
|
-
inPointUs: asUs(nextInPoint),
|
|
287
|
-
durationUs: asUs(end - nextStart)
|
|
282
|
+
startUs: require_time.asUs(nextStart),
|
|
283
|
+
inPointUs: require_time.asUs(nextInPoint),
|
|
284
|
+
durationUs: require_time.asUs(end - nextStart)
|
|
288
285
|
};
|
|
289
286
|
}
|
|
290
287
|
const nextDuration = Math.max(minDurationUs, clip.durationUs + deltaUs);
|
|
291
288
|
return {
|
|
292
289
|
...clip,
|
|
293
|
-
durationUs: asUs(nextDuration)
|
|
290
|
+
durationUs: require_time.asUs(nextDuration)
|
|
294
291
|
};
|
|
295
292
|
}
|
|
296
293
|
/** 删除指定 id 的 clip */
|
|
@@ -306,7 +303,7 @@ function duplicateClipsData(clips, ids, offsetUs, makeId) {
|
|
|
306
303
|
clip: {
|
|
307
304
|
...c,
|
|
308
305
|
id: makeId(),
|
|
309
|
-
startUs: asUs(c.startUs + offsetUs),
|
|
306
|
+
startUs: require_time.asUs(c.startUs + offsetUs),
|
|
310
307
|
transform: { ...c.transform }
|
|
311
308
|
}
|
|
312
309
|
}));
|
|
@@ -324,7 +321,7 @@ function compactTrackData(clips, trackId) {
|
|
|
324
321
|
const next = updated.get(c.id);
|
|
325
322
|
return next == null ? c : {
|
|
326
323
|
...c,
|
|
327
|
-
startUs: asUs(next)
|
|
324
|
+
startUs: require_time.asUs(next)
|
|
328
325
|
};
|
|
329
326
|
});
|
|
330
327
|
}
|
|
@@ -640,28 +637,16 @@ Object.defineProperty(exports, "ASPECT_PRESETS", {
|
|
|
640
637
|
return ASPECT_PRESETS;
|
|
641
638
|
}
|
|
642
639
|
});
|
|
643
|
-
Object.defineProperty(exports, "
|
|
644
|
-
enumerable: true,
|
|
645
|
-
get: function() {
|
|
646
|
-
return DEFAULT_CLIP_VOLUME;
|
|
647
|
-
}
|
|
648
|
-
});
|
|
649
|
-
Object.defineProperty(exports, "DEFAULT_STILL_DURATION_US", {
|
|
650
|
-
enumerable: true,
|
|
651
|
-
get: function() {
|
|
652
|
-
return DEFAULT_STILL_DURATION_US;
|
|
653
|
-
}
|
|
654
|
-
});
|
|
655
|
-
Object.defineProperty(exports, "HISTORY_MERGE_WINDOW_MS", {
|
|
640
|
+
Object.defineProperty(exports, "DEFAULT_SUBTITLE_STYLE", {
|
|
656
641
|
enumerable: true,
|
|
657
642
|
get: function() {
|
|
658
|
-
return
|
|
643
|
+
return DEFAULT_SUBTITLE_STYLE;
|
|
659
644
|
}
|
|
660
645
|
});
|
|
661
|
-
Object.defineProperty(exports, "
|
|
646
|
+
Object.defineProperty(exports, "DEFAULT_TEXT_STYLE", {
|
|
662
647
|
enumerable: true,
|
|
663
648
|
get: function() {
|
|
664
|
-
return
|
|
649
|
+
return DEFAULT_TEXT_STYLE;
|
|
665
650
|
}
|
|
666
651
|
});
|
|
667
652
|
Object.defineProperty(exports, "MIN_TRANSFORM_SIZE", {
|
|
@@ -670,54 +655,12 @@ Object.defineProperty(exports, "MIN_TRANSFORM_SIZE", {
|
|
|
670
655
|
return MIN_TRANSFORM_SIZE;
|
|
671
656
|
}
|
|
672
657
|
});
|
|
673
|
-
Object.defineProperty(exports, "PROJECT_SCHEMA_VERSION", {
|
|
674
|
-
enumerable: true,
|
|
675
|
-
get: function() {
|
|
676
|
-
return PROJECT_SCHEMA_VERSION;
|
|
677
|
-
}
|
|
678
|
-
});
|
|
679
658
|
Object.defineProperty(exports, "RESIZE_HANDLES", {
|
|
680
659
|
enumerable: true,
|
|
681
660
|
get: function() {
|
|
682
661
|
return RESIZE_HANDLES;
|
|
683
662
|
}
|
|
684
663
|
});
|
|
685
|
-
Object.defineProperty(exports, "US_PER_MS", {
|
|
686
|
-
enumerable: true,
|
|
687
|
-
get: function() {
|
|
688
|
-
return US_PER_MS;
|
|
689
|
-
}
|
|
690
|
-
});
|
|
691
|
-
Object.defineProperty(exports, "US_PER_SECOND", {
|
|
692
|
-
enumerable: true,
|
|
693
|
-
get: function() {
|
|
694
|
-
return US_PER_SECOND;
|
|
695
|
-
}
|
|
696
|
-
});
|
|
697
|
-
Object.defineProperty(exports, "asPx", {
|
|
698
|
-
enumerable: true,
|
|
699
|
-
get: function() {
|
|
700
|
-
return asPx;
|
|
701
|
-
}
|
|
702
|
-
});
|
|
703
|
-
Object.defineProperty(exports, "asUs", {
|
|
704
|
-
enumerable: true,
|
|
705
|
-
get: function() {
|
|
706
|
-
return asUs;
|
|
707
|
-
}
|
|
708
|
-
});
|
|
709
|
-
Object.defineProperty(exports, "buildTicks", {
|
|
710
|
-
enumerable: true,
|
|
711
|
-
get: function() {
|
|
712
|
-
return buildTicks;
|
|
713
|
-
}
|
|
714
|
-
});
|
|
715
|
-
Object.defineProperty(exports, "clamp", {
|
|
716
|
-
enumerable: true,
|
|
717
|
-
get: function() {
|
|
718
|
-
return clamp;
|
|
719
|
-
}
|
|
720
|
-
});
|
|
721
664
|
Object.defineProperty(exports, "clampStillDuration", {
|
|
722
665
|
enumerable: true,
|
|
723
666
|
get: function() {
|
|
@@ -742,12 +685,6 @@ Object.defineProperty(exports, "createEmptyProject", {
|
|
|
742
685
|
return createEmptyProject;
|
|
743
686
|
}
|
|
744
687
|
});
|
|
745
|
-
Object.defineProperty(exports, "createId", {
|
|
746
|
-
enumerable: true,
|
|
747
|
-
get: function() {
|
|
748
|
-
return createId;
|
|
749
|
-
}
|
|
750
|
-
});
|
|
751
688
|
Object.defineProperty(exports, "createTrack", {
|
|
752
689
|
enumerable: true,
|
|
753
690
|
get: function() {
|
|
@@ -772,18 +709,6 @@ Object.defineProperty(exports, "findOverlaps", {
|
|
|
772
709
|
return findOverlaps;
|
|
773
710
|
}
|
|
774
711
|
});
|
|
775
|
-
Object.defineProperty(exports, "formatDuration", {
|
|
776
|
-
enumerable: true,
|
|
777
|
-
get: function() {
|
|
778
|
-
return formatDuration;
|
|
779
|
-
}
|
|
780
|
-
});
|
|
781
|
-
Object.defineProperty(exports, "formatTimecode", {
|
|
782
|
-
enumerable: true,
|
|
783
|
-
get: function() {
|
|
784
|
-
return formatTimecode;
|
|
785
|
-
}
|
|
786
|
-
});
|
|
787
712
|
Object.defineProperty(exports, "fromLocalPoint", {
|
|
788
713
|
enumerable: true,
|
|
789
714
|
get: function() {
|
|
@@ -850,22 +775,28 @@ Object.defineProperty(exports, "isTrackAudible", {
|
|
|
850
775
|
return isTrackAudible;
|
|
851
776
|
}
|
|
852
777
|
});
|
|
853
|
-
Object.defineProperty(exports, "
|
|
778
|
+
Object.defineProperty(exports, "normalizeAngle", {
|
|
779
|
+
enumerable: true,
|
|
780
|
+
get: function() {
|
|
781
|
+
return normalizeAngle;
|
|
782
|
+
}
|
|
783
|
+
});
|
|
784
|
+
Object.defineProperty(exports, "normalizeAsset", {
|
|
854
785
|
enumerable: true,
|
|
855
786
|
get: function() {
|
|
856
|
-
return
|
|
787
|
+
return normalizeAsset;
|
|
857
788
|
}
|
|
858
789
|
});
|
|
859
|
-
Object.defineProperty(exports, "
|
|
790
|
+
Object.defineProperty(exports, "normalizeClip", {
|
|
860
791
|
enumerable: true,
|
|
861
792
|
get: function() {
|
|
862
|
-
return
|
|
793
|
+
return normalizeClip;
|
|
863
794
|
}
|
|
864
795
|
});
|
|
865
|
-
Object.defineProperty(exports, "
|
|
796
|
+
Object.defineProperty(exports, "normalizeProject", {
|
|
866
797
|
enumerable: true,
|
|
867
798
|
get: function() {
|
|
868
|
-
return
|
|
799
|
+
return normalizeProject;
|
|
869
800
|
}
|
|
870
801
|
});
|
|
871
802
|
Object.defineProperty(exports, "normalizeSize", {
|
|
@@ -874,16 +805,22 @@ Object.defineProperty(exports, "normalizeSize", {
|
|
|
874
805
|
return normalizeSize;
|
|
875
806
|
}
|
|
876
807
|
});
|
|
877
|
-
Object.defineProperty(exports, "
|
|
808
|
+
Object.defineProperty(exports, "normalizeTrack", {
|
|
878
809
|
enumerable: true,
|
|
879
810
|
get: function() {
|
|
880
|
-
return
|
|
811
|
+
return normalizeTrack;
|
|
881
812
|
}
|
|
882
813
|
});
|
|
883
|
-
Object.defineProperty(exports, "
|
|
814
|
+
Object.defineProperty(exports, "normalizeTransform", {
|
|
884
815
|
enumerable: true,
|
|
885
816
|
get: function() {
|
|
886
|
-
return
|
|
817
|
+
return normalizeTransform;
|
|
818
|
+
}
|
|
819
|
+
});
|
|
820
|
+
Object.defineProperty(exports, "pointInTransform", {
|
|
821
|
+
enumerable: true,
|
|
822
|
+
get: function() {
|
|
823
|
+
return pointInTransform;
|
|
887
824
|
}
|
|
888
825
|
});
|
|
889
826
|
Object.defineProperty(exports, "rangesOverlap", {
|
|
@@ -940,18 +877,6 @@ Object.defineProperty(exports, "sameTransform", {
|
|
|
940
877
|
return sameTransform;
|
|
941
878
|
}
|
|
942
879
|
});
|
|
943
|
-
Object.defineProperty(exports, "secToUs", {
|
|
944
|
-
enumerable: true,
|
|
945
|
-
get: function() {
|
|
946
|
-
return secToUs;
|
|
947
|
-
}
|
|
948
|
-
});
|
|
949
|
-
Object.defineProperty(exports, "splitClipData", {
|
|
950
|
-
enumerable: true,
|
|
951
|
-
get: function() {
|
|
952
|
-
return splitClipData;
|
|
953
|
-
}
|
|
954
|
-
});
|
|
955
880
|
Object.defineProperty(exports, "toLocalPoint", {
|
|
956
881
|
enumerable: true,
|
|
957
882
|
get: function() {
|
|
@@ -964,23 +889,5 @@ Object.defineProperty(exports, "trimClipData", {
|
|
|
964
889
|
return trimClipData;
|
|
965
890
|
}
|
|
966
891
|
});
|
|
967
|
-
Object.defineProperty(exports, "usToMs", {
|
|
968
|
-
enumerable: true,
|
|
969
|
-
get: function() {
|
|
970
|
-
return usToMs;
|
|
971
|
-
}
|
|
972
|
-
});
|
|
973
|
-
Object.defineProperty(exports, "usToPx", {
|
|
974
|
-
enumerable: true,
|
|
975
|
-
get: function() {
|
|
976
|
-
return usToPx;
|
|
977
|
-
}
|
|
978
|
-
});
|
|
979
|
-
Object.defineProperty(exports, "usToSec", {
|
|
980
|
-
enumerable: true,
|
|
981
|
-
get: function() {
|
|
982
|
-
return usToSec;
|
|
983
|
-
}
|
|
984
|
-
});
|
|
985
892
|
|
|
986
|
-
//# sourceMappingURL=canvas-size-
|
|
893
|
+
//# sourceMappingURL=canvas-size-DIABzEW2.cjs.map
|