@adminide-stack/yantra-mobile 12.0.121 → 12.0.123-alpha.0
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/lib/features/apps/appArt.js +1 -1
- package/lib/features/apps/appArt.js.map +1 -1
- package/lib/features/apps/mobileAppCatalog.js +15 -11
- package/lib/features/apps/mobileAppCatalog.js.map +1 -1
- package/lib/features/canvas/CanvasAgentChatPane.js +82 -20
- package/lib/features/canvas/CanvasAgentChatPane.js.map +1 -1
- package/lib/features/canvas/CanvasBoardsGrid.js +291 -100
- package/lib/features/canvas/CanvasBoardsGrid.js.map +1 -1
- package/lib/features/canvas/CanvasEditToolsPanel.js +105 -12
- package/lib/features/canvas/CanvasEditToolsPanel.js.map +1 -1
- package/lib/features/canvas/CanvasExperience.js +266 -68
- package/lib/features/canvas/CanvasExperience.js.map +1 -1
- package/lib/features/canvas/CanvasGeneratePanel.js +204 -66
- package/lib/features/canvas/CanvasGeneratePanel.js.map +1 -1
- package/lib/features/canvas/CanvasLibrarySheet.js +31 -13
- package/lib/features/canvas/CanvasLibrarySheet.js.map +1 -1
- package/lib/features/canvas/CanvasModelPicker.js +176 -0
- package/lib/features/canvas/CanvasModelPicker.js.map +1 -0
- package/lib/features/canvas/CanvasTasksPanel.js +325 -29
- package/lib/features/canvas/CanvasTasksPanel.js.map +1 -1
- package/lib/features/canvas/CanvasTemplatesPanel.js +5 -4
- package/lib/features/canvas/CanvasTemplatesPanel.js.map +1 -1
- package/lib/features/canvas/CanvasToolDock.js +137 -61
- package/lib/features/canvas/CanvasToolDock.js.map +1 -1
- package/lib/features/canvas/FrameExtractorExperience.js +33 -2
- package/lib/features/canvas/FrameExtractorExperience.js.map +1 -1
- package/lib/features/canvas/GeneratorReferenceSlots.js +197 -0
- package/lib/features/canvas/GeneratorReferenceSlots.js.map +1 -0
- package/lib/features/canvas/NativeCanvasViewer.js +89 -11
- package/lib/features/canvas/NativeCanvasViewer.js.map +1 -1
- package/lib/features/canvas/PromoContextFields.js +55 -2
- package/lib/features/canvas/PromoContextFields.js.map +1 -1
- package/lib/features/canvas/SetStudioExperience.js +323 -13
- package/lib/features/canvas/SetStudioExperience.js.map +1 -1
- package/lib/features/canvas/VideoEditExperience.js +1 -53
- package/lib/features/canvas/VideoEditExperience.js.map +1 -1
- package/lib/features/canvas/VideoEditorExperience.js +697 -506
- package/lib/features/canvas/VideoEditorExperience.js.map +1 -1
- package/lib/features/canvas/VideoGeneratorExperience.js +22 -5
- package/lib/features/canvas/VideoGeneratorExperience.js.map +1 -1
- package/lib/features/canvas/canvasAgentChat.js +125 -11
- package/lib/features/canvas/canvasAgentChat.js.map +1 -1
- package/lib/features/canvas/canvasCore.js +117 -12
- package/lib/features/canvas/canvasCore.js.map +1 -1
- package/lib/features/canvas/canvasEditOps.js +148 -111
- package/lib/features/canvas/canvasEditOps.js.map +1 -1
- package/lib/features/canvas/canvasTaskSync.js +235 -0
- package/lib/features/canvas/canvasTaskSync.js.map +1 -0
- package/lib/features/canvas/canvasTasks.js +98 -11
- package/lib/features/canvas/canvasTasks.js.map +1 -1
- package/lib/features/canvas/createTiles.js +247 -0
- package/lib/features/canvas/createTiles.js.map +1 -0
- package/lib/features/canvas/deepLinks.js +83 -0
- package/lib/features/canvas/deepLinks.js.map +1 -0
- package/lib/features/canvas/frameExtract.js +13 -1
- package/lib/features/canvas/frameExtract.js.map +1 -1
- package/lib/features/canvas/generationModels.js +36 -8
- package/lib/features/canvas/generationModels.js.map +1 -1
- package/lib/features/canvas/generatorCommands.js +106 -0
- package/lib/features/canvas/generatorCommands.js.map +1 -0
- package/lib/features/canvas/generatorReferences.js +82 -0
- package/lib/features/canvas/generatorReferences.js.map +1 -0
- package/lib/features/canvas/homeWork.js +74 -0
- package/lib/features/canvas/homeWork.js.map +1 -0
- package/lib/features/canvas/linksRpc.js +130 -0
- package/lib/features/canvas/linksRpc.js.map +1 -0
- package/lib/features/canvas/mediaRecheck.js +176 -0
- package/lib/features/canvas/mediaRecheck.js.map +1 -0
- package/lib/features/canvas/mediaUrls.js +258 -0
- package/lib/features/canvas/mediaUrls.js.map +1 -0
- package/lib/features/canvas/nativeViewerRegistry.js.map +1 -1
- package/lib/features/canvas/promoProjectImport.js +80 -13
- package/lib/features/canvas/promoProjectImport.js.map +1 -1
- package/lib/features/canvas/promoVideo.js +106 -15
- package/lib/features/canvas/promoVideo.js.map +1 -1
- package/lib/features/canvas/reframe.js +228 -0
- package/lib/features/canvas/reframe.js.map +1 -0
- package/lib/features/canvas/serverTasks.js +697 -0
- package/lib/features/canvas/serverTasks.js.map +1 -0
- package/lib/features/canvas/set/SetViewportWebView.js +207 -28
- package/lib/features/canvas/set/SetViewportWebView.js.map +1 -1
- package/lib/features/canvas/set/agent/prompt.js +66 -0
- package/lib/features/canvas/set/agent/prompt.js.map +1 -0
- package/lib/features/canvas/set/agent/setOps.js +203 -0
- package/lib/features/canvas/set/agent/setOps.js.map +1 -0
- package/lib/features/canvas/set/agent/setTurn.js +128 -0
- package/lib/features/canvas/set/agent/setTurn.js.map +1 -0
- package/lib/features/canvas/set/agent/snapshot.js +43 -0
- package/lib/features/canvas/set/agent/snapshot.js.map +1 -0
- package/lib/features/canvas/set/agent/tools.js +580 -0
- package/lib/features/canvas/set/agent/tools.js.map +1 -0
- package/lib/features/canvas/set/setProject.js +43 -4
- package/lib/features/canvas/set/setProject.js.map +1 -1
- package/lib/features/canvas/set/supplyLibrary.js +397 -0
- package/lib/features/canvas/set/supplyLibrary.js.map +1 -0
- package/lib/features/canvas/storageLibrary.js +113 -52
- package/lib/features/canvas/storageLibrary.js.map +1 -1
- package/lib/features/canvas/studioCatalog.js +15 -2
- package/lib/features/canvas/studioCatalog.js.map +1 -1
- package/lib/features/canvas/studioLooks.js +1 -8
- package/lib/features/canvas/studioLooks.js.map +1 -1
- package/lib/features/canvas/useBoardMediaRefresh.js +66 -0
- package/lib/features/canvas/useBoardMediaRefresh.js.map +1 -0
- package/lib/features/canvas/useMediaSource.js +84 -0
- package/lib/features/canvas/useMediaSource.js.map +1 -0
- package/lib/features/canvas/video3d.js +11 -10
- package/lib/features/canvas/video3d.js.map +1 -1
- package/lib/features/canvas/videoEditor/BlurBoxOverlay.js +46 -0
- package/lib/features/canvas/videoEditor/BlurBoxOverlay.js.map +1 -0
- package/lib/features/canvas/videoEditor/ExportTaskCard.js +134 -0
- package/lib/features/canvas/videoEditor/ExportTaskCard.js.map +1 -0
- package/lib/features/canvas/videoEditor/agent/AgentCutPane.js +45 -7
- package/lib/features/canvas/videoEditor/agent/AgentCutPane.js.map +1 -1
- package/lib/features/canvas/videoEditor/agent/agentLoop.js +4 -2
- package/lib/features/canvas/videoEditor/agent/agentLoop.js.map +1 -1
- package/lib/features/canvas/videoEditor/agent/attachments.js +304 -0
- package/lib/features/canvas/videoEditor/agent/attachments.js.map +1 -0
- package/lib/features/canvas/videoEditor/agent/brainClient.js +3 -2
- package/lib/features/canvas/videoEditor/agent/brainClient.js.map +1 -1
- package/lib/features/canvas/videoEditor/agent/cutTools.js +207 -7
- package/lib/features/canvas/videoEditor/agent/cutTools.js.map +1 -1
- package/lib/features/canvas/videoEditor/blurBox.js +34 -0
- package/lib/features/canvas/videoEditor/blurBox.js.map +1 -0
- package/lib/features/canvas/videoEditor/compileTimeline.js +668 -0
- package/lib/features/canvas/videoEditor/compileTimeline.js.map +1 -0
- package/lib/features/canvas/videoEditor/editorModel.js +56 -22
- package/lib/features/canvas/videoEditor/editorModel.js.map +1 -1
- package/lib/features/canvas/videoEditor/exportPipeline.js +77 -0
- package/lib/features/canvas/videoEditor/exportPipeline.js.map +1 -0
- package/lib/features/canvas/videoEditor/exportRenderer.js +19 -12
- package/lib/features/canvas/videoEditor/exportRenderer.js.map +1 -1
- package/lib/features/canvas/videoEditor/exportTask.js +216 -0
- package/lib/features/canvas/videoEditor/exportTask.js.map +1 -0
- package/lib/features/canvas/videoEditor/formWidgets.js +142 -0
- package/lib/features/canvas/videoEditor/formWidgets.js.map +1 -0
- package/lib/features/canvas/videoEditor/produce/ProduceVideoSheet.js +195 -0
- package/lib/features/canvas/videoEditor/produce/ProduceVideoSheet.js.map +1 -0
- package/lib/features/canvas/videoEditor/produce/produceScenes.js +158 -0
- package/lib/features/canvas/videoEditor/produce/produceScenes.js.map +1 -0
- package/lib/features/canvas/videoEditor/remoteMediaClient.js +17 -5
- package/lib/features/canvas/videoEditor/remoteMediaClient.js.map +1 -1
- package/lib/features/canvas/videoEditor/renderTimeline.js +207 -0
- package/lib/features/canvas/videoEditor/renderTimeline.js.map +1 -0
- package/lib/features/canvas/videoEditor/renewLinks.js +64 -0
- package/lib/features/canvas/videoEditor/renewLinks.js.map +1 -0
- package/lib/features/canvas/videoEditor/sceneLayers.js +101 -0
- package/lib/features/canvas/videoEditor/sceneLayers.js.map +1 -0
- package/lib/features/canvas/videoEditor/tools/ToolsDrawer.js +283 -0
- package/lib/features/canvas/videoEditor/tools/ToolsDrawer.js.map +1 -0
- package/lib/features/canvas/videoEditor/tools/catalog.js +576 -0
- package/lib/features/canvas/videoEditor/tools/catalog.js.map +1 -0
- package/lib/features/canvas/videoEditor/videoProjectsStore.js +27 -3
- package/lib/features/canvas/videoEditor/videoProjectsStore.js.map +1 -1
- package/lib/features/webbuilder/WebBuilderExperience.js +29 -1
- package/lib/features/webbuilder/WebBuilderExperience.js.map +1 -1
- package/lib/features/webbuilder/buildFragments.js +8 -4
- package/lib/features/webbuilder/buildFragments.js.map +1 -1
- package/lib/features/webbuilder/codezenHandoff.js +108 -0
- package/lib/features/webbuilder/codezenHandoff.js.map +1 -0
- package/lib/features/webbuilder/workflow.js.map +1 -1
- package/lib/hooks/useChatApi.js +1 -2
- package/lib/hooks/useChatApi.js.map +1 -1
- package/lib/screens/CanvasBoard/index.js +12 -1
- package/lib/screens/CanvasBoard/index.js.map +1 -1
- package/lib/screens/Home/HomeScreen.js.map +1 -1
- package/lib/screens/Home/components/HomeSuggestions.js +3 -3
- package/lib/screens/Home/components/HomeSuggestions.js.map +1 -1
- package/lib/screens/WebBuilder/index.js +4 -2
- package/lib/screens/WebBuilder/index.js.map +1 -1
- package/lib/screens/WebBuilderNative/index.js +29 -2
- package/lib/screens/WebBuilderNative/index.js.map +1 -1
- package/lib/screens/WebBuilderNative/useWebBuilderHost.js +30 -6
- package/lib/screens/WebBuilderNative/useWebBuilderHost.js.map +1 -1
- package/package.json +4 -4
- /package/lib/assets/apps/{paper2poster.webp → poster.webp} +0 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
const VIDEO_EDIT_CONNECTOR = "yantra-video-editing";
|
|
21
|
+
const RENDER_SUBMIT_ACTION = "YANTRA_VIDEO_EDIT_RENDER_TIMELINE_SUBMIT";
|
|
22
|
+
const RENDER_STATUS_ACTION = "YANTRA_VIDEO_EDIT_RENDER_TIMELINE_STATUS";
|
|
23
|
+
const RENDER_POLL_EVERY_MS = 1e4;
|
|
24
|
+
const RENDER_POLL_MAX_MS = 65 * 6e4;
|
|
25
|
+
const LEASE_GRACE_MS = 2 * 6e4;
|
|
26
|
+
const MAX_POLL_ERRORS = 4;
|
|
27
|
+
const str = (v) => typeof v === "string" ? v : "";
|
|
28
|
+
const positiveMs = (v) => {
|
|
29
|
+
const n = Number(v);
|
|
30
|
+
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
31
|
+
};
|
|
32
|
+
const payload = (raw) => raw.data && typeof raw.data === "object" ? raw.data : raw;
|
|
33
|
+
function parseRenderHandle(d) {
|
|
34
|
+
const [sandboxId, runId, outputUrl] = [str(d.sandbox_id), str(d.run_id), str(d.output_url)];
|
|
35
|
+
if (!sandboxId || !runId || !outputUrl) return void 0;
|
|
36
|
+
const projectedMs = positiveMs(d.projected_ms);
|
|
37
|
+
const leaseMs = positiveMs(d.lease_ms);
|
|
38
|
+
const notice = str(d.notice).trim();
|
|
39
|
+
return __spreadValues(__spreadValues(__spreadValues({
|
|
40
|
+
sandboxId,
|
|
41
|
+
runId,
|
|
42
|
+
outputUrl
|
|
43
|
+
}, projectedMs ? {
|
|
44
|
+
projectedMs
|
|
45
|
+
} : {}), leaseMs ? {
|
|
46
|
+
leaseMs
|
|
47
|
+
} : {}), notice ? {
|
|
48
|
+
notice
|
|
49
|
+
} : {});
|
|
50
|
+
}
|
|
51
|
+
function parseRenderPoll(d) {
|
|
52
|
+
const state = d.state === "succeeded" || d.state === "failed" ? d.state : "running";
|
|
53
|
+
const total = Number(d.total);
|
|
54
|
+
const step = Number.isFinite(total) && total > 0 ? {
|
|
55
|
+
index: Number(d.step) || 0,
|
|
56
|
+
total,
|
|
57
|
+
label: str(d.label)
|
|
58
|
+
} : void 0;
|
|
59
|
+
return __spreadValues(__spreadValues(__spreadValues(__spreadValues({
|
|
60
|
+
state
|
|
61
|
+
}, step ? {
|
|
62
|
+
step
|
|
63
|
+
} : {}), str(d.label) ? {
|
|
64
|
+
label: str(d.label)
|
|
65
|
+
} : {}), str(d.output_url) ? {
|
|
66
|
+
url: str(d.output_url)
|
|
67
|
+
} : {}), str(d.error) ? {
|
|
68
|
+
error: str(d.error)
|
|
69
|
+
} : {});
|
|
70
|
+
}
|
|
71
|
+
async function submitRenderTimeline(run, timeline) {
|
|
72
|
+
const raw = await run(VIDEO_EDIT_CONNECTOR, RENDER_SUBMIT_ACTION, {
|
|
73
|
+
timeline: {
|
|
74
|
+
steps: timeline.steps,
|
|
75
|
+
finalRef: timeline.finalRef
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
if (raw.successful === false) throw new Error(str(raw.error) || "Could not start the render");
|
|
79
|
+
const handle = parseRenderHandle(payload(raw));
|
|
80
|
+
if (!handle) throw new Error("Could not start the render (no handle returned)");
|
|
81
|
+
return handle;
|
|
82
|
+
}
|
|
83
|
+
async function pollRenderTimeline(run, handle) {
|
|
84
|
+
const raw = await run(VIDEO_EDIT_CONNECTOR, RENDER_STATUS_ACTION, {
|
|
85
|
+
sandbox_id: handle.sandboxId,
|
|
86
|
+
run_id: handle.runId
|
|
87
|
+
});
|
|
88
|
+
if (raw.successful === false) throw new Error(str(raw.error) || "Render status poll failed");
|
|
89
|
+
return parseRenderPoll(payload(raw));
|
|
90
|
+
}
|
|
91
|
+
function renderDeadline(startedAt, handle) {
|
|
92
|
+
return startedAt + ((handle == null ? void 0 : handle.leaseMs) ? handle.leaseMs + LEASE_GRACE_MS : RENDER_POLL_MAX_MS);
|
|
93
|
+
}
|
|
94
|
+
function renderTimeLeft(projectedMs, elapsedMs) {
|
|
95
|
+
const left = projectedMs - elapsedMs;
|
|
96
|
+
if (left <= 0) return "Taking longer than estimated";
|
|
97
|
+
if (left < 6e4) return "Less than a minute left";
|
|
98
|
+
return `About ${Math.max(1, Math.round(left / 6e4))} min left`;
|
|
99
|
+
}
|
|
100
|
+
function renderProgressPct(step, projectedMs, elapsedMs) {
|
|
101
|
+
const byStep = step && step.total > 0 ? Math.min(100, (step.index - 1) / step.total * 100) : 0;
|
|
102
|
+
const byTime = projectedMs ? Math.min(95, elapsedMs / projectedMs * 100) : 0;
|
|
103
|
+
return Math.max(0, byStep, byTime);
|
|
104
|
+
}
|
|
105
|
+
function isLocalOnlyUrl(url) {
|
|
106
|
+
return /^(file|ph|assets-library|content|data|blob):/i.test(url);
|
|
107
|
+
}
|
|
108
|
+
async function materializeTimelineInputs(compiled, {
|
|
109
|
+
upload,
|
|
110
|
+
refresh,
|
|
111
|
+
onProgress
|
|
112
|
+
} = {}) {
|
|
113
|
+
var _a;
|
|
114
|
+
const cache = /* @__PURE__ */ new Map();
|
|
115
|
+
const lift = async (url) => {
|
|
116
|
+
if (!url) return url;
|
|
117
|
+
const cached = cache.get(url);
|
|
118
|
+
if (cached) return cached;
|
|
119
|
+
let next = url;
|
|
120
|
+
if (isLocalOnlyUrl(url)) {
|
|
121
|
+
if (!upload) throw new Error("A clip is on this phone and no uploader is available");
|
|
122
|
+
onProgress == null ? void 0 : onProgress(`Uploading media ${cache.size + 1}\u2026`);
|
|
123
|
+
next = await upload(url);
|
|
124
|
+
} else if (refresh) {
|
|
125
|
+
next = await refresh(url);
|
|
126
|
+
}
|
|
127
|
+
if (next !== url) cache.set(url, next);
|
|
128
|
+
return next;
|
|
129
|
+
};
|
|
130
|
+
const liftRef = async (ref) => {
|
|
131
|
+
if (ref.kind === "url") ref.url = await lift(ref.url);
|
|
132
|
+
};
|
|
133
|
+
for (const step of compiled.steps) {
|
|
134
|
+
await liftRef(step.primaryInput);
|
|
135
|
+
for (const value of Object.values((_a = step.inputRefs) != null ? _a : {})) {
|
|
136
|
+
for (const ref of Array.isArray(value) ? value : [value]) await liftRef(ref);
|
|
137
|
+
}
|
|
138
|
+
for (const [key, value] of Object.entries(step.params)) {
|
|
139
|
+
if (typeof value === "string" && /^(https?|file|ph|assets-library|content|data|blob):/i.test(value)) {
|
|
140
|
+
step.params[key] = await lift(value);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
await liftRef(compiled.finalRef);
|
|
145
|
+
return cache.size;
|
|
146
|
+
}
|
|
147
|
+
function probeDuration(raw) {
|
|
148
|
+
var _a, _b;
|
|
149
|
+
const d = payload(raw);
|
|
150
|
+
const format = d.format;
|
|
151
|
+
const n = Number((_b = (_a = d.duration_secs) != null ? _a : d.duration) != null ? _b : format == null ? void 0 : format.duration);
|
|
152
|
+
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
153
|
+
}
|
|
154
|
+
function probeHasAudio(raw) {
|
|
155
|
+
const d = payload(raw);
|
|
156
|
+
if (typeof d.has_audio === "boolean") return d.has_audio;
|
|
157
|
+
if (typeof d.hasAudio === "boolean") return d.hasAudio;
|
|
158
|
+
if (Array.isArray(d.streams)) {
|
|
159
|
+
return d.streams.some((s) => (s == null ? void 0 : s.codec_type) === "audio" || (s == null ? void 0 : s.type) === "audio");
|
|
160
|
+
}
|
|
161
|
+
if ("audio_codec" in d) return Boolean(d.audio_codec);
|
|
162
|
+
if (d.audio && typeof d.audio === "object") return true;
|
|
163
|
+
if (d.audio === null || d.audio === false) return false;
|
|
164
|
+
return void 0;
|
|
165
|
+
}
|
|
166
|
+
async function probeSpecSources(spec, run, {
|
|
167
|
+
needAudio
|
|
168
|
+
}) {
|
|
169
|
+
const holdsAfter = (i) => {
|
|
170
|
+
var _a;
|
|
171
|
+
return Boolean((_a = spec.clips[i + 1]) == null ? void 0 : _a.transitionIn);
|
|
172
|
+
};
|
|
173
|
+
const wants = spec.clips.map((c, i) => ({
|
|
174
|
+
c,
|
|
175
|
+
i
|
|
176
|
+
})).filter(({
|
|
177
|
+
c,
|
|
178
|
+
i
|
|
179
|
+
}) => c.type === "video" && !isLocalOnlyUrl(c.src) && (c.sourceDurationSec == null && (c.trimEndSec === null || holdsAfter(i)) || needAudio && c.hasAudio === void 0 && !c.muted));
|
|
180
|
+
if (!wants.length) return spec;
|
|
181
|
+
const answers = /* @__PURE__ */ new Map();
|
|
182
|
+
await Promise.all([...new Set(wants.map(({
|
|
183
|
+
c
|
|
184
|
+
}) => c.src))].map(async (src) => {
|
|
185
|
+
try {
|
|
186
|
+
answers.set(src, await run(VIDEO_EDIT_CONNECTOR, "YANTRA_VIDEO_EDIT_PROBE", {
|
|
187
|
+
input_url: src
|
|
188
|
+
}));
|
|
189
|
+
} catch (e) {
|
|
190
|
+
answers.set(src, null);
|
|
191
|
+
}
|
|
192
|
+
}));
|
|
193
|
+
return __spreadProps(__spreadValues({}, spec), {
|
|
194
|
+
clips: spec.clips.map((c) => {
|
|
195
|
+
var _a, _b;
|
|
196
|
+
const a = c.type === "video" ? answers.get(c.src) : null;
|
|
197
|
+
if (!a) return c;
|
|
198
|
+
const duration = (_a = c.sourceDurationSec) != null ? _a : probeDuration(a);
|
|
199
|
+
const hasAudio = (_b = c.hasAudio) != null ? _b : needAudio ? probeHasAudio(a) : void 0;
|
|
200
|
+
return __spreadValues(__spreadValues(__spreadValues({}, c), duration ? {
|
|
201
|
+
sourceDurationSec: duration
|
|
202
|
+
} : {}), hasAudio === void 0 ? {} : {
|
|
203
|
+
hasAudio
|
|
204
|
+
});
|
|
205
|
+
})
|
|
206
|
+
});
|
|
207
|
+
}export{LEASE_GRACE_MS,MAX_POLL_ERRORS,RENDER_POLL_EVERY_MS,RENDER_POLL_MAX_MS,RENDER_STATUS_ACTION,RENDER_SUBMIT_ACTION,VIDEO_EDIT_CONNECTOR,isLocalOnlyUrl,materializeTimelineInputs,parseRenderHandle,parseRenderPoll,pollRenderTimeline,probeDuration,probeHasAudio,probeSpecSources,renderDeadline,renderProgressPct,renderTimeLeft,submitRenderTimeline};//# sourceMappingURL=renderTimeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderTimeline.js","sources":["../../../../src/features/canvas/videoEditor/renderTimeline.ts"],"sourcesContent":["/**\n * Detached timeline render - native twin of web rpc/renderTimelineRpc.ts.\n *\n * SUBMIT stages the compiled timeline in the video connector's own sandbox\n * and answers with a handle in seconds; STATUS reads how it is going. The\n * render uploads its own output, so nothing holds a request open and the\n * phone can sleep, close the editor or relaunch and pick it back up from the\n * stored handle (canvasTasks kind 'export').\n *\n * Transport-agnostic like exportRenderer: everything goes through a\n * RunMediaAction.\n */\nimport type { CompiledTimeline, InputSource } from './compileTimeline';\nimport type { VideoExportSpec } from './editorModel';\nimport type { RunMediaAction } from './mediaActions';\n\nexport const VIDEO_EDIT_CONNECTOR = 'yantra-video-editing' as const;\nexport const RENDER_SUBMIT_ACTION = 'YANTRA_VIDEO_EDIT_RENDER_TIMELINE_SUBMIT';\nexport const RENDER_STATUS_ACTION = 'YANTRA_VIDEO_EDIT_RENDER_TIMELINE_STATUS';\nexport const RENDER_POLL_EVERY_MS = 10_000;\n/** Follow a render whose handle names no lease for the plan's hour and a bit. */\nexport const RENDER_POLL_MAX_MS = 65 * 60_000;\n/** Past its lease a render is gone; this covers the last poll in flight. */\nexport const LEASE_GRACE_MS = 2 * 60_000;\n/** A poll can blip; this many failures in a row is a lost render. */\nexport const MAX_POLL_ERRORS = 4;\n\n/** The wire timeline: warnings stay on the phone. */\nexport type RenderTimeline = Pick<CompiledTimeline, 'steps' | 'finalRef'>;\n\nexport interface RenderHandle {\n sandboxId: string;\n runId: string;\n /** Where the finished file will be; fetchable once a poll reports `succeeded`. */\n outputUrl: string;\n /** The connector's projection of the render time, for \"time left\". */\n projectedMs?: number;\n /** How long the render may run from launch; polling stops past it. */\n leaseMs?: number;\n /** The connector's word for the person (close to / past the render time limit). */\n notice?: string;\n}\n\nexport interface RenderPoll {\n state: 'running' | 'succeeded' | 'failed';\n step?: { index: number; total: number; label: string };\n label?: string;\n url?: string;\n error?: string;\n}\n\nconst str = (v: unknown): string => (typeof v === 'string' ? v : '');\nconst positiveMs = (v: unknown): number | undefined => {\n const n = Number(v);\n return Number.isFinite(n) && n > 0 ? n : undefined;\n};\n\n/** The runner can hand back the connector JSON with or without its `{ successful, data }` envelope. */\nconst payload = (raw: Record<string, unknown>): Record<string, unknown> =>\n (raw.data && typeof raw.data === 'object' ? raw.data : raw) as Record<string, unknown>;\n\n/** Read one SUBMIT answer; undefined without a handle to poll. Pure. */\nexport function parseRenderHandle(d: Record<string, unknown>): RenderHandle | undefined {\n const [sandboxId, runId, outputUrl] = [str(d.sandbox_id), str(d.run_id), str(d.output_url)];\n if (!sandboxId || !runId || !outputUrl) return undefined;\n const projectedMs = positiveMs(d.projected_ms);\n const leaseMs = positiveMs(d.lease_ms);\n const notice = str(d.notice).trim();\n return {\n sandboxId,\n runId,\n outputUrl,\n ...(projectedMs ? { projectedMs } : {}),\n ...(leaseMs ? { leaseMs } : {}),\n ...(notice ? { notice } : {}),\n };\n}\n\n/** Read one STATUS answer. Pure. */\nexport function parseRenderPoll(d: Record<string, unknown>): RenderPoll {\n const state = d.state === 'succeeded' || d.state === 'failed' ? d.state : 'running';\n const total = Number(d.total);\n const step =\n Number.isFinite(total) && total > 0 ? { index: Number(d.step) || 0, total, label: str(d.label) } : undefined;\n return {\n state,\n ...(step ? { step } : {}),\n ...(str(d.label) ? { label: str(d.label) } : {}),\n ...(str(d.output_url) ? { url: str(d.output_url) } : {}),\n ...(str(d.error) ? { error: str(d.error) } : {}),\n };\n}\n\n/** Submit sends no time budget: the connector projects the render from its sources. */\nexport async function submitRenderTimeline(run: RunMediaAction, timeline: RenderTimeline): Promise<RenderHandle> {\n const raw = await run(VIDEO_EDIT_CONNECTOR, RENDER_SUBMIT_ACTION, {\n timeline: { steps: timeline.steps, finalRef: timeline.finalRef },\n });\n if (raw.successful === false) throw new Error(str(raw.error) || 'Could not start the render');\n const handle = parseRenderHandle(payload(raw));\n if (!handle) throw new Error('Could not start the render (no handle returned)');\n return handle;\n}\n\n/** One status poll. Throws on a transport failure; a failed render is a `failed` poll. */\nexport async function pollRenderTimeline(run: RunMediaAction, handle: RenderHandle): Promise<RenderPoll> {\n const raw = await run(VIDEO_EDIT_CONNECTOR, RENDER_STATUS_ACTION, {\n sandbox_id: handle.sandboxId,\n run_id: handle.runId,\n });\n if (raw.successful === false) throw new Error(str(raw.error) || 'Render status poll failed');\n return parseRenderPoll(payload(raw));\n}\n\n/** When to stop following a render: its lease (+grace) when named, else the plan's hour. Pure. */\nexport function renderDeadline(startedAt: number, handle: Pick<RenderHandle, 'leaseMs'> | undefined): number {\n return startedAt + (handle?.leaseMs ? handle.leaseMs + LEASE_GRACE_MS : RENDER_POLL_MAX_MS);\n}\n\n/** What is left by the connector's projection, in words (web renderTimeLeft). Pure. */\nexport function renderTimeLeft(projectedMs: number, elapsedMs: number): string {\n const left = projectedMs - elapsedMs;\n if (left <= 0) return 'Taking longer than estimated';\n if (left < 60_000) return 'Less than a minute left';\n return `About ${Math.max(1, Math.round(left / 60_000))} min left`;\n}\n\n/** How full a progress bar is: steps done, or time against the projection (never claims 100% on time alone). Pure. */\nexport function renderProgressPct(\n step: RenderPoll['step'],\n projectedMs: number | undefined,\n elapsedMs: number,\n): number {\n const byStep = step && step.total > 0 ? Math.min(100, ((step.index - 1) / step.total) * 100) : 0;\n const byTime = projectedMs ? Math.min(95, (elapsedMs / projectedMs) * 100) : 0;\n return Math.max(0, byStep, byTime);\n}\n\n/** Phone-local or inline URIs the connector cannot fetch. */\nexport function isLocalOnlyUrl(url: string): boolean {\n return /^(file|ph|assets-library|content|data|blob):/i.test(url);\n}\n\n/**\n * Make every input of a compiled timeline fetchable by the connector,\n * rewriting it in place: phone-local / data: sources are uploaded once each,\n * and `refresh` (optional) re-signs stored links that may have lapsed. Walks\n * primary inputs, cross-step refs and string params alike (web\n * materializeTimelineInputs). Returns how many distinct URLs were rewritten.\n */\nexport async function materializeTimelineInputs(\n compiled: RenderTimeline,\n {\n upload,\n refresh,\n onProgress,\n }: {\n upload?: (localUri: string) => Promise<string>;\n refresh?: (url: string) => Promise<string>;\n onProgress?: (label: string) => void;\n } = {},\n): Promise<number> {\n const cache = new Map<string, string>();\n const lift = async (url: string): Promise<string> => {\n if (!url) return url;\n const cached = cache.get(url);\n if (cached) return cached;\n let next = url;\n if (isLocalOnlyUrl(url)) {\n if (!upload) throw new Error('A clip is on this phone and no uploader is available');\n onProgress?.(`Uploading media ${cache.size + 1}…`);\n next = await upload(url);\n } else if (refresh) {\n next = await refresh(url);\n }\n if (next !== url) cache.set(url, next);\n return next;\n };\n const liftRef = async (ref: InputSource) => {\n if (ref.kind === 'url') ref.url = await lift(ref.url);\n };\n for (const step of compiled.steps) {\n await liftRef(step.primaryInput);\n for (const value of Object.values(step.inputRefs ?? {})) {\n for (const ref of Array.isArray(value) ? value : [value]) await liftRef(ref);\n }\n for (const [key, value] of Object.entries(step.params)) {\n if (typeof value === 'string' && /^(https?|file|ph|assets-library|content|data|blob):/i.test(value)) {\n step.params[key] = await lift(value);\n }\n }\n }\n await liftRef(compiled.finalRef);\n return cache.size;\n}\n\n// ── Probing (open trims + sound-less videos) ────────────────────────────────\n\n/** Seconds from a PROBE answer (several connector shapes). */\nexport function probeDuration(raw: Record<string, unknown>): number | undefined {\n const d = payload(raw);\n const format = d.format as Record<string, unknown> | undefined;\n const n = Number(d.duration_secs ?? d.duration ?? format?.duration);\n return Number.isFinite(n) && n > 0 ? n : undefined;\n}\n\n/** Whether a PROBE answer shows an audio stream; undefined when it cannot tell. */\nexport function probeHasAudio(raw: Record<string, unknown>): boolean | undefined {\n const d = payload(raw);\n if (typeof d.has_audio === 'boolean') return d.has_audio;\n if (typeof d.hasAudio === 'boolean') return d.hasAudio;\n if (Array.isArray(d.streams)) {\n return (d.streams as Array<Record<string, unknown>>).some(\n (s) => s?.codec_type === 'audio' || s?.type === 'audio',\n );\n }\n if ('audio_codec' in d) return Boolean(d.audio_codec);\n if (d.audio && typeof d.audio === 'object') return true;\n if (d.audio === null || d.audio === false) return false;\n return undefined;\n}\n\n/**\n * Fill what the compiler needs to know about video sources before it runs:\n * the length of an open-ended trim (so the trim and a transition hold are\n * exact), and - only when the compiled lane mixes audio - whether each video\n * carries sound, so a silent one stays out of the lane. One PROBE per\n * distinct source; a failed probe leaves the clip as it was.\n */\nexport async function probeSpecSources(\n spec: VideoExportSpec,\n run: RunMediaAction,\n { needAudio }: { needAudio: boolean },\n): Promise<VideoExportSpec> {\n const holdsAfter = (i: number) => Boolean(spec.clips[i + 1]?.transitionIn);\n const wants = spec.clips\n .map((c, i) => ({ c, i }))\n .filter(\n ({ c, i }) =>\n c.type === 'video' &&\n !isLocalOnlyUrl(c.src) &&\n ((c.sourceDurationSec == null && (c.trimEndSec === null || holdsAfter(i))) ||\n (needAudio && c.hasAudio === undefined && !c.muted)),\n );\n if (!wants.length) return spec;\n const answers = new Map<string, Record<string, unknown> | null>();\n await Promise.all(\n [...new Set(wants.map(({ c }) => c.src))].map(async (src) => {\n try {\n answers.set(src, await run(VIDEO_EDIT_CONNECTOR, 'YANTRA_VIDEO_EDIT_PROBE', { input_url: src }));\n } catch {\n answers.set(src, null);\n }\n }),\n );\n return {\n ...spec,\n clips: spec.clips.map((c) => {\n const a = c.type === 'video' ? answers.get(c.src) : null;\n if (!a) return c;\n const duration = c.sourceDurationSec ?? probeDuration(a);\n const hasAudio = c.hasAudio ?? (needAudio ? probeHasAudio(a) : undefined);\n return {\n ...c,\n ...(duration ? { sourceDurationSec: duration } : {}),\n ...(hasAudio === undefined ? {} : { hasAudio }),\n };\n }),\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import {isPresignedUrlExpiring}from'../mediaUrls.js';var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
function timelineMediaUrls(t) {
|
|
21
|
+
var _a, _b, _c;
|
|
22
|
+
const urls = [...t.clips.filter((c) => !c.fillColor).map((c) => c.src), (_a = t.voiceover) == null ? void 0 : _a.audioUrl, (_b = t.soundtrack) == null ? void 0 : _b.audioUrl, ...((_c = t.sceneAudio) != null ? _c : []).map((a) => a.audioUrl)].filter((u) => typeof u === "string" && u.length > 0);
|
|
23
|
+
return [...new Set(urls)];
|
|
24
|
+
}
|
|
25
|
+
function staleMediaUrls(t, nowMs = Date.now()) {
|
|
26
|
+
return timelineMediaUrls(t).filter((u) => isPresignedUrlExpiring(u, nowMs));
|
|
27
|
+
}
|
|
28
|
+
function withRenewedUrls(t, fresh) {
|
|
29
|
+
var _a;
|
|
30
|
+
if (fresh.size === 0) return t;
|
|
31
|
+
const swap = (u) => {
|
|
32
|
+
var _a2;
|
|
33
|
+
return (_a2 = fresh.get(u)) != null ? _a2 : u;
|
|
34
|
+
};
|
|
35
|
+
let changed = false;
|
|
36
|
+
const clips = t.clips.map((c) => {
|
|
37
|
+
const src = swap(c.src);
|
|
38
|
+
if (src === c.src) return c;
|
|
39
|
+
changed = true;
|
|
40
|
+
return __spreadProps(__spreadValues({}, c), {
|
|
41
|
+
src
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
const audio = (a) => {
|
|
45
|
+
if (!a) return a;
|
|
46
|
+
const audioUrl = swap(a.audioUrl);
|
|
47
|
+
if (audioUrl === a.audioUrl) return a;
|
|
48
|
+
changed = true;
|
|
49
|
+
return __spreadProps(__spreadValues({}, a), {
|
|
50
|
+
audioUrl
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
const voiceover = audio(t.voiceover);
|
|
54
|
+
const soundtrack = audio(t.soundtrack);
|
|
55
|
+
const sceneAudio = (_a = t.sceneAudio) == null ? void 0 : _a.map((a) => audio(a));
|
|
56
|
+
if (!changed) return t;
|
|
57
|
+
return __spreadValues(__spreadProps(__spreadValues({}, t), {
|
|
58
|
+
clips,
|
|
59
|
+
voiceover,
|
|
60
|
+
soundtrack
|
|
61
|
+
}), sceneAudio ? {
|
|
62
|
+
sceneAudio
|
|
63
|
+
} : {});
|
|
64
|
+
}export{staleMediaUrls,timelineMediaUrls,withRenewedUrls};//# sourceMappingURL=renewLinks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renewLinks.js","sources":["../../../../src/features/canvas/videoEditor/renewLinks.ts"],"sourcesContent":["/**\n * Media links renewed on editor open: a saved timeline keeps the presigned\n * URL each clip was given when it was added, and those lapse (as soon as an\n * hour) while a project is edited over days. On open, every stale link in\n * the timeline is traded for a fresh signature on the same object\n * (mediaUrls.ensureFetchableMediaUrl), so the preview plays and the export\n * does not die on an ExpiredToken.\n */\nimport { isPresignedUrlExpiring } from '../mediaUrls';\nimport type { EditorTimeline } from './editorModel';\n\n/** Every media URL a timeline holds (clip sources, audio beds, scene audio). Pure. */\nexport function timelineMediaUrls(t: EditorTimeline): string[] {\n const urls = [\n ...t.clips.filter((c) => !c.fillColor).map((c) => c.src),\n t.voiceover?.audioUrl,\n t.soundtrack?.audioUrl,\n ...(t.sceneAudio ?? []).map((a) => a.audioUrl),\n ].filter((u): u is string => typeof u === 'string' && u.length > 0);\n return [...new Set(urls)];\n}\n\n/** The stale ones, by the signature's own lifetime (offline check). Pure. */\nexport function staleMediaUrls(t: EditorTimeline, nowMs = Date.now()): string[] {\n return timelineMediaUrls(t).filter((u) => isPresignedUrlExpiring(u, nowMs));\n}\n\n/** Rewrite URLs through a map (old -> fresh); returns `t` itself when nothing changed. Pure. */\nexport function withRenewedUrls(t: EditorTimeline, fresh: ReadonlyMap<string, string>): EditorTimeline {\n if (fresh.size === 0) return t;\n const swap = (u: string) => fresh.get(u) ?? u;\n let changed = false;\n const clips = t.clips.map((c) => {\n const src = swap(c.src);\n if (src === c.src) return c;\n changed = true;\n return { ...c, src };\n });\n const audio = <T extends { audioUrl: string }>(a: T | null | undefined): T | null | undefined => {\n if (!a) return a;\n const audioUrl = swap(a.audioUrl);\n if (audioUrl === a.audioUrl) return a;\n changed = true;\n return { ...a, audioUrl };\n };\n const voiceover = audio(t.voiceover);\n const soundtrack = audio(t.soundtrack);\n const sceneAudio = t.sceneAudio?.map((a) => audio(a)!);\n if (!changed) return t;\n return { ...t, clips, voiceover, soundtrack, ...(sceneAudio ? { sceneAudio } : {}) };\n}\n"],"names":["_a"],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import {DEFAULT_IMAGE_SEC}from'./editorModel.js';var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
function sceneLengthSec(clip, sourceSec) {
|
|
21
|
+
var _a, _b;
|
|
22
|
+
if (clip.type === "image") return ((_a = clip.durationSec) != null ? _a : DEFAULT_IMAGE_SEC) / clip.speed;
|
|
23
|
+
const end = (_b = clip.trimEndSec) != null ? _b : sourceSec && sourceSec > 0 ? sourceSec : null;
|
|
24
|
+
if (end === null) return 0;
|
|
25
|
+
return Math.max(0, end - clip.trimStartSec) / clip.speed;
|
|
26
|
+
}
|
|
27
|
+
function sceneSpans(clips, sourceSec = {}) {
|
|
28
|
+
let cursor = 0;
|
|
29
|
+
return clips.map((clip, index) => {
|
|
30
|
+
const len = sceneLengthSec(clip, sourceSec[clip.id]);
|
|
31
|
+
const span = {
|
|
32
|
+
id: clip.id,
|
|
33
|
+
index,
|
|
34
|
+
startSec: cursor,
|
|
35
|
+
endSec: cursor + len
|
|
36
|
+
};
|
|
37
|
+
cursor += len;
|
|
38
|
+
return span;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
function sceneAtSec(spans, t) {
|
|
42
|
+
const hit = spans.find((s) => t >= s.startSec && t < s.endSec);
|
|
43
|
+
if (hit) return hit;
|
|
44
|
+
const last = spans[spans.length - 1];
|
|
45
|
+
return last && Math.abs(t - last.endSec) < 1e-6 ? last : void 0;
|
|
46
|
+
}
|
|
47
|
+
function layerInView(layer, focusedSceneId) {
|
|
48
|
+
return !!layer && (!layer.sceneId || layer.sceneId === focusedSceneId);
|
|
49
|
+
}
|
|
50
|
+
function stampScene(layer, clips, sourceSec) {
|
|
51
|
+
const scene = sceneAtSec(sceneSpans(clips, sourceSec), layer.startSec);
|
|
52
|
+
return scene ? __spreadProps(__spreadValues({}, layer), {
|
|
53
|
+
sceneId: scene.id
|
|
54
|
+
}) : layer;
|
|
55
|
+
}
|
|
56
|
+
const MIN_LAYER_SEC = 0.1;
|
|
57
|
+
function reflowSceneChildren(prev, next, sourceSec = {}) {
|
|
58
|
+
var _a, _b;
|
|
59
|
+
if (prev.clips === next.clips) return next;
|
|
60
|
+
const before = new Map(sceneSpans(prev.clips, sourceSec).map((s) => [s.id, s]));
|
|
61
|
+
const after = new Map(sceneSpans(next.clips, sourceSec).map((s) => [s.id, s]));
|
|
62
|
+
let changed = false;
|
|
63
|
+
const carry = (layer, clamp) => {
|
|
64
|
+
if (!layer.sceneId) return layer;
|
|
65
|
+
const was = before.get(layer.sceneId);
|
|
66
|
+
if (!was) return layer;
|
|
67
|
+
const now = after.get(layer.sceneId);
|
|
68
|
+
if (!now) {
|
|
69
|
+
changed = true;
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
let startSec = layer.startSec + (now.startSec - was.startSec);
|
|
73
|
+
let durationSec = layer.durationSec;
|
|
74
|
+
if (clamp && durationSec !== null) {
|
|
75
|
+
const len = now.endSec - now.startSec;
|
|
76
|
+
if (len > 0) {
|
|
77
|
+
durationSec = Math.max(MIN_LAYER_SEC, Math.min(durationSec, len));
|
|
78
|
+
startSec = Math.max(now.startSec, Math.min(startSec, now.endSec - durationSec));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
startSec = Math.round(startSec * 1e3) / 1e3;
|
|
82
|
+
if (startSec === layer.startSec && durationSec === layer.durationSec) return layer;
|
|
83
|
+
changed = true;
|
|
84
|
+
return __spreadProps(__spreadValues({}, layer), {
|
|
85
|
+
startSec,
|
|
86
|
+
durationSec
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
const keep = (v) => v !== null;
|
|
90
|
+
const texts = next.texts.map((t) => carry(t, false)).filter(keep);
|
|
91
|
+
const segments = (_a = next.segments) == null ? void 0 : _a.map((s) => carry(s, true)).filter(keep);
|
|
92
|
+
const sceneAudio = (_b = next.sceneAudio) == null ? void 0 : _b.map((a) => carry(a, false)).filter(keep);
|
|
93
|
+
if (!changed) return next;
|
|
94
|
+
return __spreadValues(__spreadValues(__spreadProps(__spreadValues({}, next), {
|
|
95
|
+
texts
|
|
96
|
+
}), segments ? {
|
|
97
|
+
segments
|
|
98
|
+
} : {}), sceneAudio ? {
|
|
99
|
+
sceneAudio
|
|
100
|
+
} : {});
|
|
101
|
+
}export{layerInView,reflowSceneChildren,sceneAtSec,sceneLengthSec,sceneSpans,stampScene};//# sourceMappingURL=sceneLayers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sceneLayers.js","sources":["../../../../src/features/canvas/videoEditor/sceneLayers.ts"],"sourcesContent":["/**\n * Scene-scoped layers - native twin of the web editor's `ownerSceneId` /\n * `sceneChildren` / `clipInView` / `reconcileScenes` (types.ts, state.tsx).\n *\n * A scene is one base clip. A text, segment or scene-audio layer stamped with\n * `sceneId` belongs to that scene: it moves when the scene moves or is\n * trimmed, goes when the scene goes, and the timeline shows it only while\n * that scene is open. Unstamped layers are global - every project saved\n * before this existed keeps loading exactly as it was.\n *\n * Pure: no RN imports.\n */\nimport {\n DEFAULT_IMAGE_SEC,\n type EditorClip,\n type EditorSegment,\n type EditorTimeline,\n type SceneAudio,\n type TextClip,\n} from './editorModel';\n\nexport interface SceneSpan {\n id: string;\n index: number;\n startSec: number;\n endSec: number;\n}\n\n/** Seconds a clip occupies on the timeline; `sourceSec` fills in a video whose out point is open. */\nexport function sceneLengthSec(clip: EditorClip, sourceSec?: number): number {\n if (clip.type === 'image') return (clip.durationSec ?? DEFAULT_IMAGE_SEC) / clip.speed;\n const end = clip.trimEndSec ?? (sourceSec && sourceSec > 0 ? sourceSec : null);\n if (end === null) return 0;\n return Math.max(0, end - clip.trimStartSec) / clip.speed;\n}\n\n/** Every scene's window on the timeline, in order. Unknown-length videos count as 0s. */\nexport function sceneSpans(\n clips: readonly EditorClip[],\n sourceSec: Readonly<Record<string, number>> = {},\n): SceneSpan[] {\n let cursor = 0;\n return clips.map((clip, index) => {\n const len = sceneLengthSec(clip, sourceSec[clip.id]);\n const span = { id: clip.id, index, startSec: cursor, endSec: cursor + len };\n cursor += len;\n return span;\n });\n}\n\n/** The scene under `t`, if any (the last scene owns its own end point). */\nexport function sceneAtSec(spans: readonly SceneSpan[], t: number): SceneSpan | undefined {\n const hit = spans.find((s) => t >= s.startSec && t < s.endSec);\n if (hit) return hit;\n const last = spans[spans.length - 1];\n return last && Math.abs(t - last.endSec) < 1e-6 ? last : undefined;\n}\n\ntype Layer = { sceneId?: string };\n\n/** web clipInView: a global layer always shows; a scene's own only while that scene is open. */\nexport function layerInView(layer: Layer | undefined, focusedSceneId: string | null | undefined): boolean {\n return !!layer && (!layer.sceneId || layer.sceneId === focusedSceneId);\n}\n\n/** web sceneChildren: every layer stamped with a scene's id. */\nexport function sceneChildren(timeline: EditorTimeline, sceneId: string): Array<TextClip | EditorSegment | SceneAudio> {\n return [\n ...timeline.texts.filter((t) => t.sceneId === sceneId),\n ...(timeline.segments ?? []).filter((s) => s.sceneId === sceneId),\n ...(timeline.sceneAudio ?? []).filter((a) => a.sceneId === sceneId),\n ];\n}\n\n/** Stamp a new layer with the scene the playhead is in (no scene = global). */\nexport function stampScene<T extends Layer & { startSec: number }>(\n layer: T,\n clips: readonly EditorClip[],\n sourceSec?: Readonly<Record<string, number>>,\n): T {\n const scene = sceneAtSec(sceneSpans(clips, sourceSec), layer.startSec);\n return scene ? { ...layer, sceneId: scene.id } : layer;\n}\n\nconst MIN_LAYER_SEC = 0.1;\n\n/**\n * Carry stamped layers along with their scenes after a clip edit (move, trim,\n * speed, duration, remove). Layers of a scene that moved shift by the scene's\n * start delta; a timed effect (segment) is also kept inside its scene when the\n * scene got shorter; layers of a removed scene are removed with it. Scenes not\n * in `prev` (a wholesale load) are left alone. Returns `next` itself when\n * nothing moved, so state setters can bail out.\n */\nexport function reflowSceneChildren(\n prev: EditorTimeline,\n next: EditorTimeline,\n sourceSec: Readonly<Record<string, number>> = {},\n): EditorTimeline {\n if (prev.clips === next.clips) return next;\n const before = new Map(sceneSpans(prev.clips, sourceSec).map((s) => [s.id, s]));\n const after = new Map(sceneSpans(next.clips, sourceSec).map((s) => [s.id, s]));\n let changed = false;\n\n const carry = <T extends Layer & { startSec: number; durationSec: number | null }>(\n layer: T,\n clamp: boolean,\n ): T | null => {\n if (!layer.sceneId) return layer;\n const was = before.get(layer.sceneId);\n if (!was) return layer;\n const now = after.get(layer.sceneId);\n if (!now) {\n changed = true;\n return null;\n }\n let startSec = layer.startSec + (now.startSec - was.startSec);\n let durationSec = layer.durationSec;\n if (clamp && durationSec !== null) {\n const len = now.endSec - now.startSec;\n if (len > 0) {\n durationSec = Math.max(MIN_LAYER_SEC, Math.min(durationSec, len));\n startSec = Math.max(now.startSec, Math.min(startSec, now.endSec - durationSec));\n }\n }\n startSec = Math.round(startSec * 1000) / 1000;\n if (startSec === layer.startSec && durationSec === layer.durationSec) return layer;\n changed = true;\n return { ...layer, startSec, durationSec };\n };\n const keep = <T>(v: T | null): v is T => v !== null;\n\n const texts = next.texts.map((t) => carry(t, false)).filter(keep);\n const segments = next.segments?.map((s) => carry(s, true)).filter(keep);\n const sceneAudio = next.sceneAudio?.map((a) => carry(a, false)).filter(keep);\n if (!changed) return next;\n return {\n ...next,\n texts,\n ...(segments ? { segments } : {}),\n ...(sceneAudio ? { sceneAudio } : {}),\n };\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAqBgB,SAAA,cAAA,CAAe,MAAkB,SAA4B,EAAA;AArB7E,EAAA,IAAA,EAAA,EAAA,EAAA;AAsBE,EAAI,IAAA,IAAA,CAAK,SAAS,OAAS,EAAA,OAAA,CAAA,CAAQ,UAAK,WAAL,KAAA,IAAA,GAAA,EAAA,GAAoB,qBAAqB,IAAK,CAAA,KAAA;AACjF,EAAA,MAAM,OAAM,EAAK,GAAA,IAAA,CAAA,UAAA,KAAL,YAAoB,SAAa,IAAA,SAAA,GAAY,IAAI,SAAY,GAAA,IAAA;AACzE,EAAI,IAAA,GAAA,KAAQ,MAAa,OAAA,CAAA;AACzB,EAAA,OAAO,KAAK,GAAI,CAAA,CAAA,EAAG,MAAM,IAAK,CAAA,YAAY,IAAI,IAAK,CAAA,KAAA;AACrD;AAGO,SAAS,UAAW,CAAA,KAAA,EAA8B,SAA8C,GAAA,EAAiB,EAAA;AACtH,EAAA,IAAI,MAAS,GAAA,CAAA;AACb,EAAA,OAAO,KAAM,CAAA,GAAA,CAAI,CAAC,IAAA,EAAM,KAAU,KAAA;AAChC,IAAA,MAAM,MAAM,cAAe,CAAA,IAAA,EAAM,SAAU,CAAA,IAAA,CAAK,EAAE,CAAC,CAAA;AACnD,IAAA,MAAM,IAAO,GAAA;AAAA,MACX,IAAI,IAAK,CAAA,EAAA;AAAA,MACT,KAAA;AAAA,MACA,QAAU,EAAA,MAAA;AAAA,MACV,QAAQ,MAAS,GAAA;AAAA,KACnB;AACA,IAAU,MAAA,IAAA,GAAA;AACV,IAAO,OAAA,IAAA;AAAA,GACR,CAAA;AACH;AAGgB,SAAA,UAAA,CAAW,OAA6B,CAAkC,EAAA;AACxF,EAAM,MAAA,GAAA,GAAM,MAAM,IAAK,CAAA,CAAA,CAAA,KAAK,KAAK,CAAE,CAAA,QAAA,IAAY,CAAI,GAAA,CAAA,CAAE,MAAM,CAAA;AAC3D,EAAA,IAAI,KAAY,OAAA,GAAA;AAChB,EAAA,MAAM,IAAO,GAAA,KAAA,CAAM,KAAM,CAAA,MAAA,GAAS,CAAC,CAAA;AACnC,EAAO,OAAA,IAAA,IAAQ,KAAK,GAAI,CAAA,CAAA,GAAI,KAAK,MAAM,CAAA,GAAI,OAAO,IAAO,GAAA,MAAA;AAC3D;AAMgB,SAAA,WAAA,CAAY,OAA0B,cAAoD,EAAA;AACxG,EAAA,OAAO,CAAC,CAAC,KAAA,KAAU,CAAC,KAAM,CAAA,OAAA,IAAW,MAAM,OAAY,KAAA,cAAA,CAAA;AACzD;AAQgB,SAAA,UAAA,CAEb,KAAU,EAAA,KAAA,EAA8B,SAAiD,EAAA;AAC1F,EAAA,MAAM,QAAQ,UAAW,CAAA,UAAA,CAAW,OAAO,SAAS,CAAA,EAAG,MAAM,QAAQ,CAAA;AACrE,EAAO,OAAA,KAAA,GAAQ,iCACV,KADU,CAAA,EAAA;AAAA,IAEb,SAAS,KAAM,CAAA;AAAA,GACb,CAAA,GAAA,KAAA;AACN;AACA,MAAM,aAAgB,GAAA,GAAA;AAUf,SAAS,mBAAoB,CAAA,IAAA,EAAsB,IAAsB,EAAA,SAAA,GAA8C,EAAoB,EAAA;AArFlJ,EAAA,IAAA,EAAA,EAAA,EAAA;AAsFE,EAAA,IAAI,IAAK,CAAA,KAAA,KAAU,IAAK,CAAA,KAAA,EAAc,OAAA,IAAA;AACtC,EAAA,MAAM,MAAS,GAAA,IAAI,GAAI,CAAA,UAAA,CAAW,KAAK,KAAO,EAAA,SAAS,CAAE,CAAA,GAAA,CAAI,OAAK,CAAC,CAAA,CAAE,EAAI,EAAA,CAAC,CAAC,CAAC,CAAA;AAC5E,EAAA,MAAM,KAAQ,GAAA,IAAI,GAAI,CAAA,UAAA,CAAW,KAAK,KAAO,EAAA,SAAS,CAAE,CAAA,GAAA,CAAI,OAAK,CAAC,CAAA,CAAE,EAAI,EAAA,CAAC,CAAC,CAAC,CAAA;AAC3E,EAAA,IAAI,OAAU,GAAA,KAAA;AACd,EAAM,MAAA,KAAA,GAAQ,CAGV,KAAA,EAAU,KAA6B,KAAA;AACzC,IAAI,IAAA,CAAC,KAAM,CAAA,OAAA,EAAgB,OAAA,KAAA;AAC3B,IAAA,MAAM,GAAM,GAAA,MAAA,CAAO,GAAI,CAAA,KAAA,CAAM,OAAO,CAAA;AACpC,IAAI,IAAA,CAAC,KAAY,OAAA,KAAA;AACjB,IAAA,MAAM,GAAM,GAAA,KAAA,CAAM,GAAI,CAAA,KAAA,CAAM,OAAO,CAAA;AACnC,IAAA,IAAI,CAAC,GAAK,EAAA;AACR,MAAU,OAAA,GAAA,IAAA;AACV,MAAO,OAAA,IAAA;AAAA;AAET,IAAA,IAAI,QAAW,GAAA,KAAA,CAAM,QAAY,IAAA,GAAA,CAAI,WAAW,GAAI,CAAA,QAAA,CAAA;AACpD,IAAA,IAAI,cAAc,KAAM,CAAA,WAAA;AACxB,IAAI,IAAA,KAAA,IAAS,gBAAgB,IAAM,EAAA;AACjC,MAAM,MAAA,GAAA,GAAM,GAAI,CAAA,MAAA,GAAS,GAAI,CAAA,QAAA;AAC7B,MAAA,IAAI,MAAM,CAAG,EAAA;AACX,QAAA,WAAA,GAAc,KAAK,GAAI,CAAA,aAAA,EAAe,KAAK,GAAI,CAAA,WAAA,EAAa,GAAG,CAAC,CAAA;AAChE,QAAW,QAAA,GAAA,IAAA,CAAK,GAAI,CAAA,GAAA,CAAI,QAAU,EAAA,IAAA,CAAK,IAAI,QAAU,EAAA,GAAA,CAAI,MAAS,GAAA,WAAW,CAAC,CAAA;AAAA;AAChF;AAEF,IAAA,QAAA,GAAW,IAAK,CAAA,KAAA,CAAM,QAAW,GAAA,GAAI,CAAI,GAAA,GAAA;AACzC,IAAA,IAAI,aAAa,KAAM,CAAA,QAAA,IAAY,WAAgB,KAAA,KAAA,CAAM,aAAoB,OAAA,KAAA;AAC7E,IAAU,OAAA,GAAA,IAAA;AACV,IAAA,OAAO,iCACF,KADE,CAAA,EAAA;AAAA,MAEL,QAAA;AAAA,MACA;AAAA,KACF,CAAA;AAAA,GACF;AACA,EAAM,MAAA,IAAA,GAAO,CAAK,CAAA,KAAwB,CAAM,KAAA,IAAA;AAChD,EAAM,MAAA,KAAA,GAAQ,IAAK,CAAA,KAAA,CAAM,GAAI,CAAA,CAAA,CAAA,KAAK,KAAM,CAAA,CAAA,EAAG,KAAK,CAAC,CAAE,CAAA,MAAA,CAAO,IAAI,CAAA;AAC9D,EAAM,MAAA,QAAA,GAAA,CAAW,EAAK,GAAA,IAAA,CAAA,QAAA,KAAL,IAAe,GAAA,MAAA,GAAA,EAAA,CAAA,GAAA,CAAI,OAAK,KAAM,CAAA,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,MAAO,CAAA,IAAA,CAAA;AAChE,EAAM,MAAA,UAAA,GAAA,CAAa,EAAK,GAAA,IAAA,CAAA,UAAA,KAAL,IAAiB,GAAA,MAAA,GAAA,EAAA,CAAA,GAAA,CAAI,OAAK,KAAM,CAAA,CAAA,EAAG,KAAK,CAAA,CAAA,CAAG,MAAO,CAAA,IAAA,CAAA;AACrE,EAAI,IAAA,CAAC,SAAgB,OAAA,IAAA;AACrB,EAAA,OAAO,+DACF,IADE,CAAA,EAAA;AAAA,IAEL;AAAA,GAAA,CAAA,EACI,QAAW,GAAA;AAAA,IACb;AAAA,GACF,GAAI,EAAC,CAAA,EACD,UAAa,GAAA;AAAA,IACf;AAAA,MACE,EAAC,CAAA;AAET"}
|