@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 @@
|
|
|
1
|
+
{"version":3,"file":"compileTimeline.js","sources":["../../../../src/features/canvas/videoEditor/compileTimeline.ts"],"sourcesContent":["/**\n * Compile a native VideoExportSpec into the ordered `yantra-video-editing`\n * step list the connector's detached render (RENDER_TIMELINE_SUBMIT) runs -\n * the phone twin of the web editor's export/compileTimeline.ts, adapted to\n * the native sequential-clip model.\n *\n * Pure + deterministic (no RN, no network) so every rule is unit-tested.\n * Wire shape is the web's: `{ op, label, primaryInput, params, inputRefs?,\n * audioOnly? }` with `primaryInput`/`inputRefs` naming either a URL or an\n * earlier step's output, and `finalRef` naming the finished video.\n *\n * Pipeline: per-scene prep (still -> slideshow/ken_burns, footage -> trim ->\n * speed -> grade -> level) -> letterbox to the frame when scenes differ or a\n * segment needs frame pixels -> a scene's own titles composited into it when\n * it crosses a transition -> assembly (one concat per run of cuts, a\n * transition op where a scene asks for one) -> titles -> blur boxes -> audio\n * -> segments (cut at every edge; trim drops, speed/zoom/crop apply, re-join).\n *\n * What the old client chain (exportRenderer) dropped and this keeps:\n * transitions (with the hold rule, so the cut stays as long as the timeline),\n * segments (speed / zoom / crop / trim / blur) and scene-scoped audio.\n */\nimport {\n DEFAULT_IMAGE_SEC,\n type EditorSegment,\n type SceneAudio,\n type TextClip,\n type VideoExportSpec,\n type ZoomDepth,\n} from './editorModel';\nimport { colorFromSolidSrc, solidColorPngDataUrl } from './solidColorPng';\n\n/** The connector ops this compiler emits (a subset of web VideoEditOp). */\nexport type VideoEditOp =\n | 'trim'\n | 'speed'\n | 'transcode'\n | 'crop'\n | 'letterbox'\n | 'ken_burns'\n | 'slideshow'\n | 'color_adjust'\n | 'blur'\n | 'mute'\n | 'volume'\n | 'concat'\n | 'transition'\n | 'overlay_text'\n | 'picture_in_picture'\n | 'add_audio'\n | 'audio_mix'\n | 'audio_delay';\n\n/** op -> connector action, for the client-driven lane and labels. */\nexport const VIDEO_EDIT_ACTIONS: Record<VideoEditOp, string> = {\n trim: 'YANTRA_VIDEO_EDIT_TRIM',\n speed: 'YANTRA_VIDEO_EDIT_SPEED',\n transcode: 'YANTRA_VIDEO_EDIT_TRANSCODE',\n crop: 'YANTRA_VIDEO_EDIT_CROP',\n letterbox: 'YANTRA_VIDEO_EDIT_LETTERBOX',\n ken_burns: 'YANTRA_VIDEO_EDIT_KEN_BURNS',\n slideshow: 'YANTRA_VIDEO_EDIT_SLIDESHOW',\n color_adjust: 'YANTRA_VIDEO_EDIT_COLOR_ADJUST',\n blur: 'YANTRA_VIDEO_EDIT_BLUR',\n mute: 'YANTRA_VIDEO_EDIT_MUTE',\n volume: 'YANTRA_VIDEO_EDIT_VOLUME',\n concat: 'YANTRA_VIDEO_EDIT_CONCAT',\n transition: 'YANTRA_VIDEO_EDIT_TRANSITION',\n overlay_text: 'YANTRA_VIDEO_EDIT_OVERLAY_TEXT',\n picture_in_picture: 'YANTRA_VIDEO_EDIT_PICTURE_IN_PICTURE',\n add_audio: 'YANTRA_VIDEO_EDIT_ADD_AUDIO',\n audio_mix: 'YANTRA_AUDIO_EDIT_MIX',\n audio_delay: 'YANTRA_VIDEO_EDIT_AUDIO_DELAY',\n};\n\n/** A connector input: a literal URL or the output of an earlier step. */\nexport type InputSource = { kind: 'url'; url: string } | { kind: 'step'; index: number };\n\nexport interface ExportStep {\n op: VideoEditOp;\n label: string;\n primaryInput: InputSource;\n params: Record<string, unknown>;\n /** URL-bearing params resolved at run time (concat `input_urls`, transition `input2_url`, ...). */\n inputRefs?: Record<string, InputSource | InputSource[]>;\n /** Input carries no video stream - the render runs it on the audio connector. */\n audioOnly?: true;\n}\n\nexport interface CompiledTimeline {\n steps: ExportStep[];\n finalRef: InputSource;\n /** Non-fatal notes for the person (overlapping transitions, ...). */\n warnings: string[];\n}\n\nexport interface CompileOptions {\n /** Output frame; defaults to spec.canvas, then 1280x720. */\n canvas?: { width: number; height: number };\n}\n\n/** Footage played slower than this share of its speed to cover a crossfade visibly drags (web MIN_HOLD_SLOWDOWN). */\nexport const MIN_HOLD_SLOWDOWN = 0.8;\nexport const DEFAULT_CANVAS = { width: 1280, height: 720 } as const;\n\n/** Server-side grade per editor filter id - COLOR_ADJUST params (kept in lockstep with exportRenderer). */\nexport const FILTER_GRADE: Record<string, Record<string, number> | null> = {\n none: null,\n cinematic: { contrast: 1.12, saturation: 0.92, brightness: -0.04 },\n film: { saturation: 0.85, gamma: 1.05, brightness: 0.03 },\n kodak: { saturation: 1.15, gamma: 0.95, hue: 8 },\n mono: { saturation: 0, contrast: 1.08 },\n vivid: { contrast: 1.15, saturation: 1.35 },\n warm: { hue: -12, saturation: 1.08, brightness: 0.03 },\n cool: { hue: 12, saturation: 0.95 },\n dreamy: { blur: 4, brightness: 0.06, saturation: 1.1 },\n};\n\n/** Zoom scale per native depth (web cameraSim ZOOM_DEPTHS; native 'strong' = web 'deep'). */\nexport const ZOOM_SCALE: Record<ZoomDepth, number> = { subtle: 1.5, moderate: 2.0, strong: 2.6 };\n\ntype SpecClip = VideoExportSpec['clips'][number];\n\nconst urlRef = (url: string): InputSource => ({ kind: 'url', url });\nconst stepRef = (index: number): InputSource => ({ kind: 'step', index });\nconst pctToPx = (pct: number, dim: number): number => Math.round((pct / 100) * dim);\n/** h264 rejects odd sizes. */\nconst evenPx = (px: number): number => Math.max(2, Math.round(px / 2) * 2);\nconst clamp = (v: number, lo: number, hi: number) => Math.min(hi, Math.max(lo, v));\nconst r3 = (v: number) => Math.round(v * 1000) / 1000;\n\n/** Seconds a spec clip occupies on the timeline (0 when an open-ended video's length is unknown). */\nexport function specClipSec(clip: SpecClip): number {\n if (clip.type === 'image') return (clip.durationSec ?? DEFAULT_IMAGE_SEC) / clip.speed;\n const end = clip.trimEndSec ?? clip.sourceDurationSec ?? null;\n if (end === null) return 0;\n return Math.max(0, end - clip.trimStartSec) / clip.speed;\n}\n\n/** Frame for an export: portrait items -> 720x1280, square -> 1080x1080, else 1280x720. */\nexport function canvasForAspect(width: number, height: number): { width: number; height: number } {\n if (!(width > 0) || !(height > 0)) return { ...DEFAULT_CANVAS };\n const ratio = width / height;\n if (ratio < 0.9) return { width: 720, height: 1280 };\n if (ratio <= 1.1) return { width: 1080, height: 1080 };\n return { ...DEFAULT_CANVAS };\n}\n\n/** Frame for an \"W:H\" ratio label (designed promos, templates); undefined when unreadable. */\nexport function canvasForRatio(ratio: string | undefined): { width: number; height: number } | undefined {\n const m = /^(\\d+(?:\\.\\d+)?)\\s*[:x/]\\s*(\\d+(?:\\.\\d+)?)$/.exec((ratio ?? '').trim());\n return m ? canvasForAspect(Number(m[1]), Number(m[2])) : undefined;\n}\n\n// ── Segments -> pieces (web utils/segments.ts, in seconds) ──────────────────\n\nexport interface SegmentWindow {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface SegmentPiece {\n from: number;\n to: number;\n speed?: number;\n window?: SegmentWindow;\n}\n\n/** The canvas-aspect window a zoom shows; the centre slides so it never leaves the frame. */\nexport function zoomWindow(z: NonNullable<EditorSegment['zoom']>): SegmentWindow {\n const side = 100 / (ZOOM_SCALE[z.depth] ?? ZOOM_SCALE.moderate);\n return { x: (z.x / 100) * (100 - side), y: (z.y / 100) * (100 - side), width: side, height: side };\n}\n\nconst segEnd = (s: EditorSegment) => s.startSec + s.durationSec;\nconst covering = (segs: readonly EditorSegment[], kind: EditorSegment['kind'], t: number) =>\n segs.find((s) => s.kind === kind && t >= s.startSec && t < segEnd(s));\n\nfunction windowAt(segs: readonly EditorSegment[], t: number): SegmentWindow | null {\n const z = covering(segs, 'zoom', t)?.zoom;\n if (z) return zoomWindow(z);\n const c = covering(segs, 'crop', t)?.crop;\n if (!c) return null;\n const width = clamp(c.width, 5, 100);\n const height = clamp(c.height, 5, 100);\n return { x: clamp(c.x, 0, 100 - width), y: clamp(c.y, 0, 100 - height), width, height };\n}\n\n/** End of the trimmed span covering t (adjacent trims chain), or null when t plays. */\nfunction trimAt(segs: readonly EditorSegment[], t: number): number | null {\n let end: number | null = null;\n for (const s of [...segs].sort((a, b) => a.startSec - b.startSec)) {\n const cursor = end ?? t;\n if (s.kind === 'trim' && s.startSec <= cursor && cursor < segEnd(s)) end = segEnd(s);\n }\n return end;\n}\n\n/** The cut split at every segment edge, trimmed runs dropped; empty when no cutting segment exists. */\nexport function segmentPieces(segments: readonly EditorSegment[], durationSec: number): SegmentPiece[] {\n const segs = segments.filter((s) => s.kind !== 'blur' && s.durationSec > 0);\n if (!segs.length || durationSec <= 0) return [];\n const cuts = [...new Set([0, durationSec, ...segs.flatMap((s) => [s.startSec, segEnd(s)])])]\n .filter((t) => t >= 0 && t <= durationSec)\n .sort((a, b) => a - b);\n const out: SegmentPiece[] = [];\n for (let i = 1; i < cuts.length; i++) {\n const from = cuts[i - 1];\n const to = cuts[i];\n const mid = (from + to) / 2;\n if (to <= from || trimAt(segs, mid) != null) continue;\n const speed = covering(segs, 'speed', mid)?.speed ?? 1;\n const window = windowAt(segs, mid);\n out.push({ from, to, ...(speed !== 1 ? { speed } : {}), ...(window ? { window } : {}) });\n }\n return out;\n}\n\n// ── Compile ────────────────────────────────────────────────────────────────\n\nexport function compileTimeline(spec: VideoExportSpec, options: CompileOptions = {}): CompiledTimeline {\n const steps: ExportStep[] = [];\n const warnings: string[] = [];\n const push = (s: ExportStep): number => steps.push(s) - 1;\n const canvas = options.canvas ?? spec.canvas ?? DEFAULT_CANVAS;\n const canvasW = evenPx(canvas.width);\n const canvasH = evenPx(canvas.height);\n const fps = spec.fps || 30;\n const clips = spec.clips;\n\n if (clips.length === 0) {\n return { steps: [], finalRef: urlRef(''), warnings: ['Nothing to render - add a scene first.'] };\n }\n\n // Scene windows on the timeline clock, so scene-scoped layers find their scene.\n const spans: Array<{ start: number; end: number }> = [];\n {\n let cursor = 0;\n for (const clip of clips) {\n const len = specClipSec(clip);\n spans.push({ start: cursor, end: cursor + len });\n cursor += len;\n }\n }\n const totalSec = spans.length ? spans[spans.length - 1].end : 0;\n if (clips.some((c) => c.type === 'video' && specClipSec(c) === 0)) {\n warnings.push(\n 'A video without a known length sits in the cut, so titles and segments after it may land early.',\n );\n }\n\n const stillSrc = (clip: SpecClip): string => {\n const fill = clip.fillColor || colorFromSolidSrc(clip.src);\n if (!fill) return clip.src;\n // A solid scene paints at the frame's aspect, small (a stored PNG); the letterbox scales it.\n const scale = 640 / Math.max(canvasW, canvasH);\n return solidColorPngDataUrl(fill, Math.round(canvasW * scale), Math.round(canvasH * scale));\n };\n\n // A transition crossfades the end of one scene into the start of the next.\n // Without a hold the two overlap and the cut comes out shorter than the\n // timeline - every later title lands late. A still is simply held longer;\n // footage runs on into frames past its out point (or plays a touch\n // slower); only footage far short of the crossfade still overlaps.\n const holdMs = (index: number): number => clips[index + 1]?.transitionIn?.durationMs ?? 0;\n let unheldMs = 0;\n\n const levelOps = (ref: InputSource, clip: SpecClip): InputSource => {\n if (clip.type !== 'video') return ref;\n if (clip.muted || clip.volume <= 0) {\n return stepRef(push({ op: 'mute', label: 'Mute', primaryInput: ref, params: {} }));\n }\n if (clip.volume < 0.99) {\n return stepRef(\n push({\n op: 'volume',\n label: `Volume ${Math.round(clip.volume * 100)}%`,\n primaryInput: ref,\n params: { level: clip.volume },\n }),\n );\n }\n return ref;\n };\n\n const segmentRefs: InputSource[] = clips.map((clip, index) => {\n const hold = holdMs(index);\n let ref: InputSource;\n if (clip.type === 'image') {\n const seconds = specClipSec(clip) + hold / 1000;\n if (clip.kenBurns) {\n ref = stepRef(\n push({\n op: 'ken_burns',\n label: `Ken Burns (${clip.kenBurns.direction})`,\n primaryInput: urlRef(stillSrc(clip)),\n params: {\n width: canvasW,\n height: canvasH,\n fps,\n duration_ms: Math.round(seconds * 1000),\n zoom_start: clip.kenBurns.zoomStart,\n zoom_end: clip.kenBurns.zoomEnd,\n direction: clip.kenBurns.direction,\n },\n }),\n );\n } else {\n ref = stepRef(\n push({\n op: 'slideshow',\n label: `Image → ${seconds.toFixed(1)}s clip`,\n primaryInput: urlRef(stillSrc(clip)),\n params: { duration_per_image: r3(seconds), fps },\n }),\n );\n }\n } else {\n let trimEnd = clip.trimEndSec;\n let speed: number = clip.speed;\n if (hold > 0) {\n const source = clip.sourceDurationSec;\n const outPoint = trimEnd ?? source ?? null;\n const extended = outPoint === null ? null : outPoint + (hold / 1000) * speed;\n if (source && extended !== null && extended <= source + 1e-6) {\n trimEnd = r3(extended);\n } else if (source && outPoint !== null) {\n const len = (outPoint - clip.trimStartSec) / speed;\n const slowed = Math.floor(((source - clip.trimStartSec) / (len + hold / 1000)) * 1000) / 1000;\n if (slowed >= speed * MIN_HOLD_SLOWDOWN) {\n trimEnd = source;\n speed = slowed;\n } else unheldMs += hold;\n } else unheldMs += hold;\n }\n ref = urlRef(clip.src);\n const coversSource =\n clip.trimStartSec <= 0 &&\n (trimEnd === null || (clip.sourceDurationSec != null && trimEnd >= clip.sourceDurationSec));\n if (!coversSource) {\n const end = trimEnd ?? clip.sourceDurationSec ?? null;\n ref = stepRef(\n push({\n op: 'trim',\n label: `Trim ${clip.trimStartSec.toFixed(1)}–${end === null ? 'end' : `${end.toFixed(1)}s`}`,\n primaryInput: ref,\n params: { start_secs: clip.trimStartSec, ...(end === null ? {} : { end_secs: end }) },\n }),\n );\n }\n if (speed !== 1) {\n ref = stepRef(\n push({ op: 'speed', label: `Speed ×${speed}`, primaryInput: ref, params: { factor: speed } }),\n );\n }\n }\n const grade = FILTER_GRADE[clip.filter] ?? null;\n if (grade) {\n ref = stepRef(\n push({ op: 'color_adjust', label: `Grade (${clip.filter})`, primaryInput: ref, params: { ...grade } }),\n );\n }\n return levelOps(ref, clip);\n });\n\n // Concat/transition need same-size inputs (a mismatched concat silently\n // keeps only its first input), and segment windows and blur boxes cut in\n // frame pixels - so scenes land on the frame first whenever that matters.\n const segments = spec.segments ?? [];\n const pieces = segmentPieces(segments, totalSec);\n const blurs = segments.filter((s) => s.kind === 'blur' && s.blur && s.durationSec > 0);\n // Scenes cut from one source share a raster; anything else (different\n // stills, footage, Ken Burns at the frame size) is put on the frame.\n const mixedSources =\n new Set(\n clips.map(\n (c) => `${c.fillColor || colorFromSolidSrc(c.src) ? 'solid' : c.src}|${c.kenBurns ? 'kb' : 'raw'}`,\n ),\n ).size > 1;\n const normalized = (clips.length > 1 && mixedSources) || pieces.some((p) => p.window) || blurs.length > 0;\n if (normalized) {\n for (let i = 0; i < segmentRefs.length; i++) {\n segmentRefs[i] = stepRef(\n push({\n op: 'letterbox',\n label: `Fit scene ${i + 1} → ${canvasW}×${canvasH}`,\n primaryInput: segmentRefs[i],\n params: { width: canvasW, height: canvasH, color: 'black' },\n }),\n );\n }\n }\n\n const textStep = (base: InputSource, t: TextClip, from: number, to: number): InputSource =>\n stepRef(\n push({\n op: 'overlay_text',\n label: `Text \"${t.text.slice(0, 24)}\"`,\n primaryInput: base,\n params: {\n text: t.text,\n // Normalized editor position -> ffmpeg expressions on the real frame, text-centre anchored.\n x: `(w-text_w)*${t.x.toFixed(3)}`,\n y: `(h-text_h)*${t.y.toFixed(3)}`,\n font_size: 36,\n font_color: 'white',\n start_secs: r3(Math.max(0, from)),\n end_secs: r3(to),\n },\n }),\n );\n\n // A scene on either side of a transition takes its own titles into its\n // segment (on the scene's clock) so they cross the fade with it instead\n // of hard-cutting over the blended picture (web #576).\n const sceneIndex = new Map(\n clips.map((c, i) => [c.id, i] as const).filter(([id]) => !!id) as Array<[string, number]>,\n );\n const crosses = (i: number) => Boolean(clips[i].transitionIn) || holdMs(i) > 0;\n const frame = 1 / fps;\n const ridesScene = new Set<string>();\n let cutAtTransition = 0;\n const texts = spec.texts.filter((t) => t.text.trim() && t.durationSec > 0);\n texts.forEach((t, k) => {\n const i = t.sceneId == null ? undefined : sceneIndex.get(t.sceneId);\n if (i === undefined || !crosses(i)) return;\n const span = spans[i];\n const end = t.startSec + t.durationSec;\n const inside = t.startSec >= span.start - frame && end <= span.end + frame;\n const covered = texts\n .slice(0, k)\n .some(\n (below) =>\n !ridesScene.has(below.id) &&\n below.startSec < end &&\n below.startSec + below.durationSec > t.startSec,\n );\n if (!inside || covered) {\n cutAtTransition += 1;\n return;\n }\n ridesScene.add(t.id);\n const heldThroughCut = end >= span.end - frame;\n segmentRefs[i] = textStep(\n segmentRefs[i],\n t,\n t.startSec - span.start,\n end - span.start + (heldThroughCut ? holdMs(i) / 1000 : 0),\n );\n });\n if (cutAtTransition > 0) {\n warnings.push(\n `${cutAtTransition} title${cutAtTransition === 1 ? '' : 's'} of a scene with a transition run${cutAtTransition === 1 ? 's' : ''} past the scene, so ${cutAtTransition === 1 ? 'it cuts' : 'they cut'} at the transition instead of crossing it.`,\n );\n }\n\n // Assembly: one concat per run of plain cuts (each scene re-encoded once), a transition between runs.\n let baseRef = segmentRefs[0];\n let pending: InputSource[] = [];\n const flush = (): void => {\n if (!pending.length) return;\n baseRef = stepRef(\n push({\n op: 'concat',\n label: `Join ${pending.length + 1} clips`,\n primaryInput: baseRef,\n params: { reencode: true },\n inputRefs: { input_urls: pending },\n }),\n );\n pending = [];\n };\n for (let i = 1; i < segmentRefs.length; i++) {\n const transition = clips[i].transitionIn;\n if (!transition || !(transition.durationMs > 0)) {\n pending.push(segmentRefs[i]);\n continue;\n }\n flush();\n baseRef = stepRef(\n push({\n op: 'transition',\n label: `Transition (${transition.effect})`,\n primaryInput: baseRef,\n params: { effect: transition.effect, duration_ms: transition.durationMs },\n inputRefs: { input2_url: segmentRefs[i] },\n }),\n );\n }\n flush();\n if (unheldMs > 0) {\n warnings.push(\n `A transition after a video clip overlaps the two clips, so the export runs ${(unheldMs / 1000).toFixed(1)}s shorter than the timeline and later titles land that much late; end that clip earlier in its source, put a still before it, or cut instead.`,\n );\n }\n\n // Titles on the timeline clock.\n for (const t of texts) {\n if (!ridesScene.has(t.id)) baseRef = textStep(baseRef, t, t.startSec, t.startSec + t.durationSec);\n }\n\n // Blur boxes: blur the span, cut the box out, paste it back over the same span.\n for (const seg of blurs) {\n const b = seg.blur!;\n const x = Math.floor(pctToPx(b.x, canvasW) / 2) * 2;\n const y = Math.floor(pctToPx(b.y, canvasH) / 2) * 2;\n const span = stepRef(\n push({\n op: 'trim',\n label: `Blur span ${seg.startSec.toFixed(1)}–${segEnd(seg).toFixed(1)}s`,\n primaryInput: baseRef,\n params: { start_secs: r3(seg.startSec), end_secs: r3(segEnd(seg)) },\n }),\n );\n const blurred = stepRef(\n push({ op: 'blur', label: `Blur ${b.radius}px`, primaryInput: span, params: { radius: b.radius } }),\n );\n const box = stepRef(\n push({\n op: 'crop',\n label: 'Blur box',\n primaryInput: blurred,\n params: {\n x: String(x),\n y: String(y),\n width: String(Math.min(evenPx(pctToPx(b.width, canvasW)), canvasW - x)),\n height: String(Math.min(evenPx(pctToPx(b.height, canvasH)), canvasH - y)),\n },\n }),\n );\n baseRef = stepRef(\n push({\n op: 'picture_in_picture',\n label: `Paste ${seg.name || 'blur'}`,\n primaryInput: baseRef,\n params: {\n x,\n y,\n start_ms: Math.round(seg.startSec * 1000),\n end_ms: Math.round(segEnd(seg) * 1000),\n },\n inputRefs: { overlay_url: box },\n }),\n );\n }\n\n baseRef = compileAudio(spec, baseRef, spans, push, warnings);\n\n // Segments: cut the composite at every edge, apply, re-join once.\n if (!pieces.length && segments.some((s) => s.kind === 'trim' && s.durationSec > 0) && totalSec > 0) {\n warnings.push('Trim segments cover the whole cut - nothing is left to export.');\n }\n const effective = pieces.length > 1 || pieces.some((p) => p.speed || p.window || p.from > 0 || p.to < totalSec);\n if (effective) {\n const refs = pieces.map((piece, i) => {\n let ref = stepRef(\n push({\n op: 'trim',\n label: `Segment ${i + 1}`,\n primaryInput: baseRef,\n params: { start_secs: r3(piece.from), end_secs: r3(piece.to) },\n }),\n );\n if (piece.window) {\n const win = piece.window;\n const w = evenPx(pctToPx(win.width, canvasW));\n const h = evenPx(pctToPx(win.height, canvasH));\n ref = stepRef(\n push({\n op: 'crop',\n label: `Window ${w}×${h}`,\n primaryInput: ref,\n params: {\n x: String(pctToPx(win.x, canvasW)),\n y: String(pctToPx(win.y, canvasH)),\n width: String(w),\n height: String(h),\n },\n }),\n );\n // A frame-aspect window (zoom) scales straight back; any other aspect (crop) letterboxes.\n const fills = Math.abs(w / h - canvasW / canvasH) < 0.01;\n ref = stepRef(\n push(\n fills\n ? {\n op: 'transcode',\n label: `Window → ${canvasW}×${canvasH}`,\n primaryInput: ref,\n params: { resolution: `${canvasW}x${canvasH}` },\n }\n : {\n op: 'letterbox',\n label: `Window → ${canvasW}×${canvasH}`,\n primaryInput: ref,\n params: { width: canvasW, height: canvasH, color: 'black' },\n },\n ),\n );\n }\n if (piece.speed) {\n ref = stepRef(\n push({\n op: 'speed',\n label: `Speed ×${piece.speed}`,\n primaryInput: ref,\n params: { factor: piece.speed },\n }),\n );\n }\n return ref;\n });\n baseRef =\n refs.length > 1\n ? stepRef(\n push({\n op: 'concat',\n label: `Join ${refs.length} segments`,\n primaryInput: refs[0],\n params: { reencode: true },\n inputRefs: { input_urls: refs.slice(1) },\n }),\n )\n : refs[0];\n }\n\n return { steps, finalRef: baseRef, warnings };\n}\n\n/**\n * The audio lane. Without scene audio it is the client chain's (proven)\n * shape: soundtrack muxed, then voiceover over it. With scene audio every\n * source - each audible video scene's own sound, the soundtrack, the\n * voiceover and every scene-audio layer - is trimmed/levelled/delayed onto\n * the timeline, mixed once and set once (add_audio replaces outright, so one\n * add per source would keep only the last). A video known to carry no audio\n * stream (`hasAudio: false`, probed before compiling) never enters the lane:\n * audio ops refuse a video-only input.\n */\nfunction compileAudio(\n spec: VideoExportSpec,\n base: InputSource,\n spans: ReadonlyArray<{ start: number; end: number }>,\n push: (s: ExportStep) => number,\n warnings: string[],\n): InputSource {\n const sceneAudio = (spec.sceneAudio ?? []).filter((a) => a.audioUrl);\n let baseRef = base;\n if (!sceneAudio.length) {\n if (spec.soundtrack) {\n baseRef = stepRef(\n push({\n op: 'add_audio',\n label: 'Soundtrack',\n primaryInput: baseRef,\n params: { replace_existing: spec.soundtrack.mode === 'replace' },\n inputRefs: { audio_input_url: urlRef(spec.soundtrack.audioUrl) },\n }),\n );\n }\n if (spec.voiceover) {\n baseRef = stepRef(\n push({\n op: 'add_audio',\n label: 'Voiceover',\n primaryInput: baseRef,\n // A replace-mode voiceover must not erase the soundtrack muxed a step earlier.\n params: { replace_existing: spec.voiceover.mode === 'replace' && !spec.soundtrack },\n inputRefs: { audio_input_url: urlRef(spec.voiceover.audioUrl) },\n }),\n );\n }\n return baseRef;\n }\n\n const refs: InputSource[] = [];\n const lane = (src: string, at: number, sliceFrom: number, sliceTo: number | null, level: number, label: string) => {\n let ref = urlRef(src);\n if (sliceFrom > 0 || sliceTo !== null) {\n ref = stepRef(\n push({\n op: 'trim',\n label: `Trim ${label}`,\n primaryInput: ref,\n params: { start_secs: r3(sliceFrom), ...(sliceTo === null ? {} : { end_secs: r3(sliceTo) }) },\n audioOnly: true,\n }),\n );\n }\n if (level < 0.99) {\n ref = stepRef(\n push({\n op: 'volume',\n label: `${label} ${Math.round(level * 100)}%`,\n primaryInput: ref,\n params: { level },\n }),\n );\n }\n if (at > 0.0005) {\n ref = stepRef(\n push({\n op: 'audio_delay',\n label: `${label} at ${at.toFixed(1)}s`,\n primaryInput: ref,\n params: { delay_ms: Math.round(at * 1000) },\n audioOnly: true,\n }),\n );\n }\n refs.push(ref);\n };\n\n const replaced = spec.soundtrack?.mode === 'replace' || spec.voiceover?.mode === 'replace';\n if (!replaced) {\n let skipped = 0;\n spec.clips.forEach((clip, i) => {\n if (clip.type !== 'video' || clip.muted || clip.volume <= 0 || clip.hasAudio === false) return;\n const len = spans[i].end - spans[i].start;\n if (clip.speed !== 1 || len <= 0) {\n skipped += 1;\n return;\n }\n lane(\n clip.src,\n spans[i].start,\n clip.trimStartSec,\n clip.trimStartSec + len,\n clip.volume,\n `Scene ${i + 1} sound`,\n );\n });\n if (skipped) {\n warnings.push(\n `${skipped} sped-up or open-ended video scene${skipped === 1 ? '' : 's'} lose${skipped === 1 ? 's' : ''} its own sound where scene audio is mixed in.`,\n );\n }\n }\n if (spec.soundtrack) lane(spec.soundtrack.audioUrl, 0, 0, null, 1, 'Soundtrack');\n if (spec.voiceover) lane(spec.voiceover.audioUrl, 0, 0, null, 1, 'Voiceover');\n sceneAudio.forEach((a: SceneAudio, i) =>\n lane(a.audioUrl, a.startSec, 0, a.durationSec, a.volume ?? 1, a.label?.slice(0, 20) || `Audio ${i + 1}`),\n );\n\n const [first, ...rest] = refs;\n const mixRef = rest.length\n ? stepRef(\n push({\n op: 'audio_mix',\n label: `Mix ${refs.length} audio clips`,\n primaryInput: first,\n params: { duration: 'longest', normalize: false },\n inputRefs: { input_urls: rest },\n audioOnly: true,\n }),\n )\n : first;\n return stepRef(\n push({\n op: 'add_audio',\n label: 'Set audio',\n primaryInput: baseRef,\n params: { replace_existing: true },\n inputRefs: { audio_input_url: mixRef },\n }),\n );\n}\n\n/** Whether a compiled audio lane needs to know which video sources carry sound (task: sound-less videos). */\nexport function specMixesSceneAudio(spec: VideoExportSpec): boolean {\n return (spec.sceneAudio ?? []).some((a) => a.audioUrl);\n}\n"],"names":["_a","_b","_c"],"mappings":"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"}
|
|
@@ -78,6 +78,13 @@ function moveIdOf(kb) {
|
|
|
78
78
|
}
|
|
79
79
|
const SPEED_PRESETS = [0.5, 1, 1.5, 2];
|
|
80
80
|
const SPEED_CURVES = ["constant", "ease-in", "ease-out", "pulse"];
|
|
81
|
+
const DEFAULT_BLUR_BOX = {
|
|
82
|
+
x: 35,
|
|
83
|
+
y: 40,
|
|
84
|
+
width: 30,
|
|
85
|
+
height: 20,
|
|
86
|
+
radius: 5
|
|
87
|
+
};
|
|
81
88
|
const SEGMENT_LENGTH_SEC = 2;
|
|
82
89
|
function rangeAtPlayhead(playheadSec, totalSec) {
|
|
83
90
|
const span = Math.max(totalSec, SEGMENT_LENGTH_SEC);
|
|
@@ -132,6 +139,16 @@ function newSegment(kind, playheadSec, totalSec) {
|
|
|
132
139
|
}
|
|
133
140
|
};
|
|
134
141
|
}
|
|
142
|
+
if (kind === "blur") {
|
|
143
|
+
return {
|
|
144
|
+
id: `seg-${counter}`,
|
|
145
|
+
kind,
|
|
146
|
+
name: "Blur",
|
|
147
|
+
startSec,
|
|
148
|
+
durationSec,
|
|
149
|
+
blur: __spreadValues({}, DEFAULT_BLUR_BOX)
|
|
150
|
+
};
|
|
151
|
+
}
|
|
135
152
|
return {
|
|
136
153
|
id: `seg-${counter}`,
|
|
137
154
|
kind: "trim",
|
|
@@ -154,7 +171,7 @@ let counter = 0;
|
|
|
154
171
|
function clipFromItem(item) {
|
|
155
172
|
var _a;
|
|
156
173
|
counter += 1;
|
|
157
|
-
return {
|
|
174
|
+
return __spreadValues({
|
|
158
175
|
id: `clip-${counter}`,
|
|
159
176
|
itemId: item.id,
|
|
160
177
|
type: item.type === "video" ? "video" : "image",
|
|
@@ -170,7 +187,9 @@ function clipFromItem(item) {
|
|
|
170
187
|
transitionIn: null,
|
|
171
188
|
volume: 1,
|
|
172
189
|
muted: false
|
|
173
|
-
}
|
|
190
|
+
}, item.hasAudio === false ? {
|
|
191
|
+
hasAudio: false
|
|
192
|
+
} : {});
|
|
174
193
|
}
|
|
175
194
|
function solidColorSrc(hex) {
|
|
176
195
|
const h = hex.replace("#", "").padEnd(6, "0");
|
|
@@ -298,9 +317,9 @@ function trimClip(clip, startSec, endSec) {
|
|
|
298
317
|
trimEndSec: Math.max(endSec, start + 0.1)
|
|
299
318
|
};
|
|
300
319
|
}
|
|
301
|
-
function buildExportSpec(timeline) {
|
|
302
|
-
var _a;
|
|
303
|
-
return __spreadProps(__spreadValues(__spreadValues(__spreadValues({
|
|
320
|
+
function buildExportSpec(timeline, options = {}) {
|
|
321
|
+
var _a, _b;
|
|
322
|
+
return __spreadProps(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues({
|
|
304
323
|
version: 2,
|
|
305
324
|
fps: 30,
|
|
306
325
|
format: "mp4"
|
|
@@ -310,8 +329,14 @@ function buildExportSpec(timeline) {
|
|
|
310
329
|
soundtrack: timeline.soundtrack
|
|
311
330
|
} : {}), ((_a = timeline.segments) == null ? void 0 : _a.length) ? {
|
|
312
331
|
segments: timeline.segments
|
|
332
|
+
} : {}), ((_b = timeline.sceneAudio) == null ? void 0 : _b.length) ? {
|
|
333
|
+
sceneAudio: timeline.sceneAudio
|
|
334
|
+
} : {}), options.canvas ? {
|
|
335
|
+
canvas: options.canvas
|
|
313
336
|
} : {}), {
|
|
314
337
|
clips: timeline.clips.map(({
|
|
338
|
+
id,
|
|
339
|
+
hasAudio,
|
|
315
340
|
type,
|
|
316
341
|
src,
|
|
317
342
|
durationSec,
|
|
@@ -325,22 +350,31 @@ function buildExportSpec(timeline) {
|
|
|
325
350
|
volume,
|
|
326
351
|
muted,
|
|
327
352
|
fillColor
|
|
328
|
-
}) =>
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
353
|
+
}) => {
|
|
354
|
+
var _a2;
|
|
355
|
+
return __spreadValues(__spreadValues(__spreadProps(__spreadValues({
|
|
356
|
+
type,
|
|
357
|
+
src,
|
|
358
|
+
durationSec,
|
|
359
|
+
trimStartSec,
|
|
360
|
+
trimEndSec,
|
|
361
|
+
speed,
|
|
362
|
+
speedCurve,
|
|
363
|
+
filter,
|
|
364
|
+
kenBurns,
|
|
365
|
+
transitionIn,
|
|
366
|
+
volume,
|
|
367
|
+
muted
|
|
368
|
+
}, fillColor ? {
|
|
369
|
+
fillColor
|
|
370
|
+
} : {}), {
|
|
371
|
+
id
|
|
372
|
+
}), hasAudio === false ? {
|
|
373
|
+
hasAudio
|
|
374
|
+
} : {}), ((_a2 = options.sourceSec) == null ? void 0 : _a2[id]) && options.sourceSec[id] > 0 ? {
|
|
375
|
+
sourceDurationSec: options.sourceSec[id]
|
|
376
|
+
} : {});
|
|
377
|
+
}),
|
|
344
378
|
texts: timeline.texts
|
|
345
379
|
});
|
|
346
|
-
}export{CLIP_TRANSITIONS,DEFAULT_IMAGE_SEC,MOTION_MOVES,MOTION_STRENGTHS,SEGMENT_LENGTH_SEC,SPEED_CURVES,SPEED_PRESETS,TEXT_PRESETS,buildExportSpec,clipFromColor,clipFromItem,clipTimelineSec,emptyTimeline,kenBurnsFor,moveClip,moveIdOf,newSegment,rangeAtPlayhead,removeClip,removeText,solidColorSrc,textClipAt,timelineDuration,trimClip,updateClip,updateText};//# sourceMappingURL=editorModel.js.map
|
|
380
|
+
}export{CLIP_TRANSITIONS,DEFAULT_BLUR_BOX,DEFAULT_IMAGE_SEC,MOTION_MOVES,MOTION_STRENGTHS,SEGMENT_LENGTH_SEC,SPEED_CURVES,SPEED_PRESETS,TEXT_PRESETS,buildExportSpec,clipFromColor,clipFromItem,clipTimelineSec,emptyTimeline,kenBurnsFor,moveClip,moveIdOf,newSegment,rangeAtPlayhead,removeClip,removeText,solidColorSrc,textClipAt,timelineDuration,trimClip,updateClip,updateText};//# sourceMappingURL=editorModel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editorModel.js","sources":["../../../../src/features/canvas/videoEditor/editorModel.ts"],"sourcesContent":["/**\n * Pure timeline model for the native video editor - every edit the UI can\n * make, as data. No RN imports so it runs identically under Metro, rspack\n * and jest, and the export spec is the single contract the yantra-video\n * render service consumes.\n */\nimport type { CanvasItem } from '../canvasCore';\nimport { parseHexColor } from './solidColorPng';\n\nexport { colorFromSolidSrc, solidColorPngDataUrl, uploadFilenameFor } from './solidColorPng';\n\nexport type FilterId = 'none' | 'cinematic' | 'film' | 'kodak' | 'mono' | 'vivid' | 'warm' | 'cool' | 'dreamy';\n\n/** Stage-toolbar motion — canvas-surface StageToolbar. */\nexport type KenBurns = { zoomStart: number; zoomEnd: number; direction: string };\n\nexport const MOTION_STRENGTHS = [\n { id: 'subtle', label: 'Subtle', zoom: 1.1 },\n { id: 'normal', label: 'Normal', zoom: 1.3 },\n { id: 'strong', label: 'Strong', zoom: 1.7 },\n] as const;\n\nexport const MOTION_MOVES = [\n { id: 'none', label: 'None' },\n { id: 'zoom-in', label: 'Zoom in' },\n { id: 'zoom-out', label: 'Zoom out' },\n { id: 'pan-left', label: 'Pan left' },\n { id: 'pan-right', label: 'Pan right' },\n { id: 'pan-up', label: 'Pan up' },\n { id: 'pan-down', label: 'Pan down' },\n] as const;\n\nexport const CLIP_TRANSITIONS = [\n 'fade',\n 'wipeleft',\n 'wiperight',\n 'slideup',\n 'slidedown',\n 'circleopen',\n 'dissolve',\n] as const;\n\nexport function kenBurnsFor(move: string, zoom: number): KenBurns | null {\n if (move === 'none') return null;\n if (move === 'zoom-in') return { zoomStart: 1, zoomEnd: zoom, direction: 'center' };\n if (move === 'zoom-out') return { zoomStart: zoom, zoomEnd: 1, direction: 'center' };\n return { zoomStart: zoom, zoomEnd: zoom, direction: move.replace('pan-', '') };\n}\n\nexport function moveIdOf(kb: KenBurns | null | undefined): string {\n if (!kb) return 'none';\n if (kb.direction !== 'center') return `pan-${kb.direction}`;\n return kb.zoomEnd >= kb.zoomStart ? 'zoom-in' : 'zoom-out';\n}\n\n/** Constant playback speeds the preview can honestly reproduce. */\nexport const SPEED_PRESETS = [0.5, 1, 1.5, 2] as const;\nexport type SpeedPreset = (typeof SPEED_PRESETS)[number];\n\n/** Speed-curve intents rendered server-side; preview plays the base speed. */\nexport type SpeedCurve = 'constant' | 'ease-in' | 'ease-out' | 'pulse';\nexport const SPEED_CURVES: readonly SpeedCurve[] = ['constant', 'ease-in', 'ease-out', 'pulse'];\n\nexport interface EditorClip {\n /** Unique per timeline entry - the same media can appear twice. */\n id: string;\n itemId: string;\n type: 'image' | 'video';\n src: string;\n name: string;\n /** Images hold a still for this long; null = the video's own length. */\n durationSec: number | null;\n /** Seconds cut from the head of a video clip. */\n trimStartSec: number;\n /** Absolute end point in source seconds; null = source end. */\n trimEndSec: number | null;\n speed: SpeedPreset;\n speedCurve: SpeedCurve;\n filter: FilterId;\n kenBurns?: KenBurns | null;\n /** xfade into this clip from the previous one. */\n transitionIn?: { effect: string; durationMs: number } | null;\n /** 0..1 */\n volume: number;\n muted: boolean;\n /** Solid colour scene — `src` is a preview GIF; export paints a PNG. */\n fillColor?: string | null;\n}\n\nexport interface TextClip {\n id: string;\n text: string;\n startSec: number;\n durationSec: number;\n /** Normalized 0..1 position of the text centre on the frame. */\n x: number;\n y: number;\n}\n\n/** Cursorful-style ranged effect over the cut (web ClipSegment). */\nexport type SegmentKind = 'speed' | 'zoom' | 'crop' | 'trim';\nexport type ZoomDepth = 'subtle' | 'moderate' | 'strong';\n\nexport interface EditorSegment {\n id: string;\n kind: SegmentKind;\n name: string;\n startSec: number;\n durationSec: number;\n speed?: number;\n zoom?: { x: number; y: number; depth: ZoomDepth };\n crop?: { x: number; y: number; width: number; height: number };\n}\n\nexport const SEGMENT_LENGTH_SEC = 2;\n\n/** 2s range at the playhead, kept inside the cut so the ruler does not grow. */\nexport function rangeAtPlayhead(playheadSec: number, totalSec: number): { startSec: number; durationSec: number } {\n const span = Math.max(totalSec, SEGMENT_LENGTH_SEC);\n const startSec = Math.max(0, Math.min(playheadSec, span - SEGMENT_LENGTH_SEC));\n return { startSec, durationSec: Math.min(SEGMENT_LENGTH_SEC, Math.max(0.5, span - startSec)) };\n}\n\nexport function newSegment(kind: SegmentKind, playheadSec: number, totalSec: number): EditorSegment {\n counter += 1;\n const { startSec, durationSec } = rangeAtPlayhead(playheadSec, totalSec);\n if (kind === 'speed') {\n return { id: `seg-${counter}`, kind, name: 'Speed ×2', startSec, durationSec, speed: 2 };\n }\n if (kind === 'zoom') {\n return {\n id: `seg-${counter}`,\n kind,\n name: 'Zoom subtle',\n startSec,\n durationSec,\n zoom: { x: 50, y: 50, depth: 'subtle' },\n };\n }\n if (kind === 'crop') {\n return {\n id: `seg-${counter}`,\n kind,\n name: 'Crop',\n startSec,\n durationSec,\n crop: { x: 10, y: 10, width: 80, height: 80 },\n };\n }\n return { id: `seg-${counter}`, kind: 'trim', name: 'Trim', startSec, durationSec };\n}\n\n/** A generated narration/voice track laid under the whole timeline. */\nexport interface Voiceover {\n /** Rendered speech audio (voicebox SPEAK output). */\n audioUrl: string;\n /** mix = duck under existing audio; replace = swap the audio track. */\n mode: 'mix' | 'replace';\n /** Voice name/profile used - display only. */\n voiceLabel?: string;\n /** The spoken text - kept for re-generation. */\n text?: string;\n}\n\n/** A music bed laid under the whole timeline (generated or user-provided). */\nexport interface Soundtrack {\n /** Fetchable audio URL (yantra-audio generation output or an upload). */\n audioUrl: string;\n /** mix = duck under existing audio; replace = swap the audio track. */\n mode: 'mix' | 'replace';\n /** Display label - the generation prompt or the track name. */\n title?: string;\n}\n\nexport interface EditorTimeline {\n clips: EditorClip[];\n texts: TextClip[];\n segments?: EditorSegment[];\n voiceover?: Voiceover | null;\n soundtrack?: Soundtrack | null;\n}\n\nexport function emptyTimeline(): EditorTimeline {\n return { clips: [], texts: [], segments: [], voiceover: null, soundtrack: null };\n}\n\nexport interface VideoExportSpec {\n version: 2;\n fps: 30;\n format: 'mp4';\n clips: Array<\n Pick<\n EditorClip,\n | 'type'\n | 'src'\n | 'durationSec'\n | 'trimStartSec'\n | 'trimEndSec'\n | 'speed'\n | 'speedCurve'\n | 'filter'\n | 'kenBurns'\n | 'transitionIn'\n | 'volume'\n | 'muted'\n | 'fillColor'\n >\n >;\n texts: TextClip[];\n segments?: EditorSegment[];\n voiceover?: Voiceover | null;\n soundtrack?: Soundtrack | null;\n}\n\nexport const DEFAULT_IMAGE_SEC = 3;\n\nlet counter = 0;\n/** Test seam: deterministic ids. */\nexport function resetEditorIds(): void {\n counter = 0;\n}\n\nexport function clipFromItem(item: CanvasItem): EditorClip {\n counter += 1;\n return {\n id: `clip-${counter}`,\n itemId: item.id,\n type: item.type === 'video' ? 'video' : 'image',\n src: item.src,\n name: item.generatedAssetName?.trim() || (item.type === 'video' ? 'Video' : 'Image'),\n durationSec: item.type === 'video' ? null : DEFAULT_IMAGE_SEC,\n trimStartSec: 0,\n trimEndSec: null,\n speed: 1,\n speedCurve: 'constant',\n filter: 'none',\n kenBurns: null,\n transitionIn: null,\n volume: 1,\n muted: false,\n };\n}\n\n/** 1×1 GIF data URL — blank color scenes without a network placeholder. */\nexport function solidColorSrc(hex: string): string {\n const h = hex.replace('#', '').padEnd(6, '0');\n const r = Number.parseInt(h.slice(0, 2), 16) || 0;\n const g = Number.parseInt(h.slice(2, 4), 16) || 0;\n const b = Number.parseInt(h.slice(4, 6), 16) || 0;\n const bytes = [\n 0x47,\n 0x49,\n 0x46,\n 0x38,\n 0x39,\n 0x61,\n 0x01,\n 0x00,\n 0x01,\n 0x00,\n 0x80,\n 0x00,\n 0x00,\n r,\n g,\n b,\n 0x00,\n 0x00,\n 0x00,\n 0x2c,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x01,\n 0x00,\n 0x01,\n 0x00,\n 0x00,\n 0x02,\n 0x02,\n 0x44,\n 0x01,\n 0x00,\n 0x3b,\n ];\n let bin = '';\n for (const byte of bytes) bin += String.fromCharCode(byte);\n const b64 =\n typeof globalThis.btoa === 'function'\n ? globalThis.btoa(bin)\n : Buffer.from(Uint8Array.from(bytes)).toString('base64');\n return `data:image/gif;base64,${b64}`;\n}\n\nexport function clipFromColor(hex: string): EditorClip {\n const { hex: fillColor } = parseHexColor(hex);\n return {\n ...clipFromItem({\n id: `scene-${hex.replace('#', '')}-${counter + 1}`,\n type: 'image',\n src: solidColorSrc(fillColor),\n x: 0,\n y: 0,\n width: 640,\n height: 360,\n zIndex: 1,\n generatedAssetName: 'Blank scene',\n }),\n fillColor,\n };\n}\n\n/** Title-card presets — same four as canvas-surface MediaLibrary TEXT_PRESETS. */\nexport const TEXT_PRESETS = [\n { id: 'title', label: 'Title', text: 'Title', x: 0.5, y: 0.38 },\n { id: 'subtitle', label: 'Subtitle', text: 'Subtitle', x: 0.5, y: 0.54 },\n { id: 'caption', label: 'Caption', text: 'Caption', x: 0.5, y: 0.86 },\n { id: 'lower-third', label: 'Lower third', text: 'Name · Role', x: 0.5, y: 0.78 },\n] as const;\n\nexport function textClipAt(startSec: number, preset?: { text: string; x: number; y: number }): TextClip {\n counter += 1;\n return {\n id: `text-${counter}`,\n text: preset?.text ?? 'Title',\n startSec,\n durationSec: 2,\n x: preset?.x ?? 0.5,\n y: preset?.y ?? 0.35,\n };\n}\n\n/** Effective duration a clip contributes to the timeline, after trim+speed.\n * Unknown-length videos report null - the UI says \"video\", not a guess. */\nexport function clipTimelineSec(clip: EditorClip): number | null {\n if (clip.type === 'image') return (clip.durationSec ?? DEFAULT_IMAGE_SEC) / clip.speed;\n if (clip.trimEndSec === null) return null;\n return Math.max(0, clip.trimEndSec - clip.trimStartSec) / clip.speed;\n}\n\n/** Total known seconds + whether unknown-length video remains. */\nexport function timelineDuration(clips: readonly EditorClip[]): { knownSec: number; hasUnknown: boolean } {\n let knownSec = 0;\n let hasUnknown = false;\n for (const clip of clips) {\n const sec = clipTimelineSec(clip);\n if (sec === null) hasUnknown = true;\n else knownSec += sec;\n }\n return { knownSec: Math.round(knownSec * 10) / 10, hasUnknown };\n}\n\nexport function updateClip(timeline: EditorTimeline, id: string, patch: Partial<EditorClip>): EditorTimeline {\n return {\n ...timeline,\n clips: timeline.clips.map((c) => (c.id === id ? { ...c, ...patch, id: c.id } : c)),\n };\n}\n\nexport function moveClip(timeline: EditorTimeline, id: string, dir: -1 | 1): EditorTimeline {\n const index = timeline.clips.findIndex((c) => c.id === id);\n const to = index + dir;\n if (index < 0 || to < 0 || to >= timeline.clips.length) return timeline;\n const clips = [...timeline.clips];\n const [clip] = clips.splice(index, 1);\n clips.splice(to, 0, clip);\n return { ...timeline, clips };\n}\n\nexport function removeClip(timeline: EditorTimeline, id: string): EditorTimeline {\n return { ...timeline, clips: timeline.clips.filter((c) => c.id !== id) };\n}\n\nexport function updateText(timeline: EditorTimeline, id: string, patch: Partial<TextClip>): EditorTimeline {\n return {\n ...timeline,\n texts: timeline.texts.map((t) => (t.id === id ? { ...t, ...patch, id: t.id } : t)),\n };\n}\n\nexport function removeText(timeline: EditorTimeline, id: string): EditorTimeline {\n return { ...timeline, texts: timeline.texts.filter((t) => t.id !== id) };\n}\n\n/** Clamp a trim edit so the window never inverts or escapes the source. */\nexport function trimClip(\n clip: EditorClip,\n startSec: number,\n endSec: number | null,\n): Pick<EditorClip, 'trimStartSec' | 'trimEndSec'> {\n const start = Math.max(0, startSec);\n if (endSec === null) return { trimStartSec: start, trimEndSec: null };\n return { trimStartSec: Math.min(start, Math.max(0, endSec - 0.1)), trimEndSec: Math.max(endSec, start + 0.1) };\n}\n\nexport function buildExportSpec(timeline: EditorTimeline): VideoExportSpec {\n return {\n version: 2,\n fps: 30,\n format: 'mp4',\n ...(timeline.voiceover ? { voiceover: timeline.voiceover } : {}),\n ...(timeline.soundtrack ? { soundtrack: timeline.soundtrack } : {}),\n ...(timeline.segments?.length ? { segments: timeline.segments } : {}),\n clips: timeline.clips.map(\n ({\n type,\n src,\n durationSec,\n trimStartSec,\n trimEndSec,\n speed,\n speedCurve,\n filter,\n kenBurns,\n transitionIn,\n volume,\n muted,\n fillColor,\n }) => ({\n type,\n src,\n durationSec,\n trimStartSec,\n trimEndSec,\n speed,\n speedCurve,\n filter,\n kenBurns,\n transitionIn,\n volume,\n muted,\n ...(fillColor ? { fillColor } : {}),\n }),\n ),\n texts: timeline.texts,\n };\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAiBO,MAAM,mBAAmB,CAAC;AAAA,EAC/B,EAAI,EAAA,QAAA;AAAA,EACJ,KAAO,EAAA,QAAA;AAAA,EACP,IAAM,EAAA;AACR,CAAG,EAAA;AAAA,EACD,EAAI,EAAA,QAAA;AAAA,EACJ,KAAO,EAAA,QAAA;AAAA,EACP,IAAM,EAAA;AACR,CAAG,EAAA;AAAA,EACD,EAAI,EAAA,QAAA;AAAA,EACJ,KAAO,EAAA,QAAA;AAAA,EACP,IAAM,EAAA;AACR,CAAC;AACM,MAAM,eAAe,CAAC;AAAA,EAC3B,EAAI,EAAA,MAAA;AAAA,EACJ,KAAO,EAAA;AACT,CAAG,EAAA;AAAA,EACD,EAAI,EAAA,SAAA;AAAA,EACJ,KAAO,EAAA;AACT,CAAG,EAAA;AAAA,EACD,EAAI,EAAA,UAAA;AAAA,EACJ,KAAO,EAAA;AACT,CAAG,EAAA;AAAA,EACD,EAAI,EAAA,UAAA;AAAA,EACJ,KAAO,EAAA;AACT,CAAG,EAAA;AAAA,EACD,EAAI,EAAA,WAAA;AAAA,EACJ,KAAO,EAAA;AACT,CAAG,EAAA;AAAA,EACD,EAAI,EAAA,QAAA;AAAA,EACJ,KAAO,EAAA;AACT,CAAG,EAAA;AAAA,EACD,EAAI,EAAA,UAAA;AAAA,EACJ,KAAO,EAAA;AACT,CAAC;AACY,MAAA,gBAAA,GAAmB,CAAC,MAAQ,EAAA,UAAA,EAAY,aAAa,SAAW,EAAA,WAAA,EAAa,cAAc,UAAU;AAClG,SAAA,WAAA,CAAY,MAAc,IAA+B,EAAA;AACvE,EAAI,IAAA,IAAA,KAAS,QAAe,OAAA,IAAA;AAC5B,EAAI,IAAA,IAAA,KAAS,WAAkB,OAAA;AAAA,IAC7B,SAAW,EAAA,CAAA;AAAA,IACX,OAAS,EAAA,IAAA;AAAA,IACT,SAAW,EAAA;AAAA,GACb;AACA,EAAI,IAAA,IAAA,KAAS,YAAmB,OAAA;AAAA,IAC9B,SAAW,EAAA,IAAA;AAAA,IACX,OAAS,EAAA,CAAA;AAAA,IACT,SAAW,EAAA;AAAA,GACb;AACA,EAAO,OAAA;AAAA,IACL,SAAW,EAAA,IAAA;AAAA,IACX,OAAS,EAAA,IAAA;AAAA,IACT,SAAW,EAAA,IAAA,CAAK,OAAQ,CAAA,MAAA,EAAQ,EAAE;AAAA,GACpC;AACF;AACO,SAAS,SAAS,EAAyC,EAAA;AAChE,EAAI,IAAA,CAAC,IAAW,OAAA,MAAA;AAChB,EAAA,IAAI,GAAG,SAAc,KAAA,QAAA,EAAiB,OAAA,CAAA,IAAA,EAAO,GAAG,SAAS,CAAA,CAAA;AACzD,EAAA,OAAO,EAAG,CAAA,OAAA,IAAW,EAAG,CAAA,SAAA,GAAY,SAAY,GAAA,UAAA;AAClD;AAGO,MAAM,aAAgB,GAAA,CAAC,GAAK,EAAA,CAAA,EAAG,KAAK,CAAC;AAKrC,MAAM,YAAsC,GAAA,CAAC,UAAY,EAAA,SAAA,EAAW,YAAY,OAAO;AA6DvF,MAAM,kBAAqB,GAAA;AAGlB,SAAA,eAAA,CAAgB,aAAqB,QAGnD,EAAA;AACA,EAAA,MAAM,IAAO,GAAA,IAAA,CAAK,GAAI,CAAA,QAAA,EAAU,kBAAkB,CAAA;AAClD,EAAM,MAAA,QAAA,GAAW,KAAK,GAAI,CAAA,CAAA,EAAG,KAAK,GAAI,CAAA,WAAA,EAAa,IAAO,GAAA,kBAAkB,CAAC,CAAA;AAC7E,EAAO,OAAA;AAAA,IACL,QAAA;AAAA,IACA,WAAA,EAAa,KAAK,GAAI,CAAA,kBAAA,EAAoB,KAAK,GAAI,CAAA,GAAA,EAAK,IAAO,GAAA,QAAQ,CAAC;AAAA,GAC1E;AACF;AACgB,SAAA,UAAA,CAAW,IAAmB,EAAA,WAAA,EAAqB,QAAiC,EAAA;AAClG,EAAW,OAAA,IAAA,CAAA;AACX,EAAM,MAAA;AAAA,IACJ,QAAA;AAAA,IACA;AAAA,GACF,GAAI,eAAgB,CAAA,WAAA,EAAa,QAAQ,CAAA;AACzC,EAAA,IAAI,SAAS,OAAS,EAAA;AACpB,IAAO,OAAA;AAAA,MACL,EAAA,EAAI,OAAO,OAAO,CAAA,CAAA;AAAA,MAClB,IAAA;AAAA,MACA,IAAM,EAAA,aAAA;AAAA,MACN,QAAA;AAAA,MACA,WAAA;AAAA,MACA,KAAO,EAAA;AAAA,KACT;AAAA;AAEF,EAAA,IAAI,SAAS,MAAQ,EAAA;AACnB,IAAO,OAAA;AAAA,MACL,EAAA,EAAI,OAAO,OAAO,CAAA,CAAA;AAAA,MAClB,IAAA;AAAA,MACA,IAAM,EAAA,aAAA;AAAA,MACN,QAAA;AAAA,MACA,WAAA;AAAA,MACA,IAAM,EAAA;AAAA,QACJ,CAAG,EAAA,EAAA;AAAA,QACH,CAAG,EAAA,EAAA;AAAA,QACH,KAAO,EAAA;AAAA;AACT,KACF;AAAA;AAEF,EAAA,IAAI,SAAS,MAAQ,EAAA;AACnB,IAAO,OAAA;AAAA,MACL,EAAA,EAAI,OAAO,OAAO,CAAA,CAAA;AAAA,MAClB,IAAA;AAAA,MACA,IAAM,EAAA,MAAA;AAAA,MACN,QAAA;AAAA,MACA,WAAA;AAAA,MACA,IAAM,EAAA;AAAA,QACJ,CAAG,EAAA,EAAA;AAAA,QACH,CAAG,EAAA,EAAA;AAAA,QACH,KAAO,EAAA,EAAA;AAAA,QACP,MAAQ,EAAA;AAAA;AACV,KACF;AAAA;AAEF,EAAO,OAAA;AAAA,IACL,EAAA,EAAI,OAAO,OAAO,CAAA,CAAA;AAAA,IAClB,IAAM,EAAA,MAAA;AAAA,IACN,IAAM,EAAA,MAAA;AAAA,IACN,QAAA;AAAA,IACA;AAAA,GACF;AACF;AA8BO,SAAS,aAAgC,GAAA;AAC9C,EAAO,OAAA;AAAA,IACL,OAAO,EAAC;AAAA,IACR,OAAO,EAAC;AAAA,IACR,UAAU,EAAC;AAAA,IACX,SAAW,EAAA,IAAA;AAAA,IACX,UAAY,EAAA;AAAA,GACd;AACF;AAWO,MAAM,iBAAoB,GAAA;AACjC,IAAI,OAAU,GAAA,CAAA;AAKP,SAAS,aAAa,IAA8B,EAAA;AAzQ3D,EAAA,IAAA,EAAA;AA0QE,EAAW,OAAA,IAAA,CAAA;AACX,EAAO,OAAA;AAAA,IACL,EAAA,EAAI,QAAQ,OAAO,CAAA,CAAA;AAAA,IACnB,QAAQ,IAAK,CAAA,EAAA;AAAA,IACb,IAAM,EAAA,IAAA,CAAK,IAAS,KAAA,OAAA,GAAU,OAAU,GAAA,OAAA;AAAA,IACxC,KAAK,IAAK,CAAA,GAAA;AAAA,IACV,IAAA,EAAA,CAAA,CAAM,UAAK,kBAAL,KAAA,IAAA,GAAA,MAAA,GAAA,EAAA,CAAyB,YAAW,IAAK,CAAA,IAAA,KAAS,UAAU,OAAU,GAAA,OAAA,CAAA;AAAA,IAC5E,WAAa,EAAA,IAAA,CAAK,IAAS,KAAA,OAAA,GAAU,IAAO,GAAA,iBAAA;AAAA,IAC5C,YAAc,EAAA,CAAA;AAAA,IACd,UAAY,EAAA,IAAA;AAAA,IACZ,KAAO,EAAA,CAAA;AAAA,IACP,UAAY,EAAA,UAAA;AAAA,IACZ,MAAQ,EAAA,MAAA;AAAA,IACR,QAAU,EAAA,IAAA;AAAA,IACV,YAAc,EAAA,IAAA;AAAA,IACd,MAAQ,EAAA,CAAA;AAAA,IACR,KAAO,EAAA;AAAA,GACT;AACF;AAGO,SAAS,cAAc,GAAqB,EAAA;AACjD,EAAM,MAAA,CAAA,GAAI,IAAI,OAAQ,CAAA,GAAA,EAAK,EAAE,CAAE,CAAA,MAAA,CAAO,GAAG,GAAG,CAAA;AAC5C,EAAM,MAAA,CAAA,GAAI,OAAO,QAAS,CAAA,CAAA,CAAE,MAAM,CAAG,EAAA,CAAC,CAAG,EAAA,EAAE,CAAK,IAAA,CAAA;AAChD,EAAM,MAAA,CAAA,GAAI,OAAO,QAAS,CAAA,CAAA,CAAE,MAAM,CAAG,EAAA,CAAC,CAAG,EAAA,EAAE,CAAK,IAAA,CAAA;AAChD,EAAM,MAAA,CAAA,GAAI,OAAO,QAAS,CAAA,CAAA,CAAE,MAAM,CAAG,EAAA,CAAC,CAAG,EAAA,EAAE,CAAK,IAAA,CAAA;AAChD,EAAA,MAAM,QAAQ,CAAC,EAAA,EAAM,EAAM,EAAA,EAAA,EAAM,IAAM,EAAM,EAAA,EAAA,EAAM,CAAM,EAAA,CAAA,EAAM,GAAM,CAAM,EAAA,GAAA,EAAM,CAAM,EAAA,CAAA,EAAM,GAAG,CAAG,EAAA,CAAA,EAAG,CAAM,EAAA,CAAA,EAAM,GAAM,EAAM,EAAA,CAAA,EAAM,CAAM,EAAA,CAAA,EAAM,GAAM,CAAM,EAAA,CAAA,EAAM,CAAM,EAAA,CAAA,EAAM,GAAM,CAAM,EAAA,CAAA,EAAM,EAAM,EAAA,CAAA,EAAM,GAAM,EAAI,CAAA;AACtN,EAAA,IAAI,GAAM,GAAA,EAAA;AACV,EAAA,KAAA,MAAW,IAAQ,IAAA,KAAA,EAAc,GAAA,IAAA,MAAA,CAAO,aAAa,IAAI,CAAA;AACzD,EAAA,MAAM,MAAM,OAAO,UAAA,CAAW,IAAS,KAAA,UAAA,GAAa,WAAW,IAAK,CAAA,GAAG,CAAI,GAAA,MAAA,CAAO,KAAK,UAAW,CAAA,IAAA,CAAK,KAAK,CAAC,CAAA,CAAE,SAAS,QAAQ,CAAA;AAChI,EAAA,OAAO,yBAAyB,GAAG,CAAA,CAAA;AACrC;AACO,SAAS,cAAc,GAAyB,EAAA;AACrD,EAAM,MAAA;AAAA,IACJ,GAAK,EAAA;AAAA,GACP,GAAI,cAAc,GAAG,CAAA;AACrB,EAAA,OAAO,iCACF,YAAa,CAAA;AAAA,IACd,EAAA,EAAI,SAAS,GAAI,CAAA,OAAA,CAAQ,KAAK,EAAE,CAAC,CAAI,CAAA,EAAA,OAAA,GAAU,CAAC,CAAA,CAAA;AAAA,IAChD,IAAM,EAAA,OAAA;AAAA,IACN,GAAA,EAAK,cAAc,SAAS,CAAA;AAAA,IAM5B,kBAAoB,EAAA;AAAA,GACrB,CAXI,CAAA,EAAA;AAAA,IAYL;AAAA,GACF,CAAA;AACF;AAGO,MAAM,eAAe,CAAC;AAAA,EAC3B,EAAI,EAAA,OAAA;AAAA,EACJ,KAAO,EAAA,OAAA;AAAA,EACP,IAAM,EAAA,OAAA;AAAA,EACN,CAAG,EAAA,GAAA;AAAA,EACH,CAAG,EAAA;AACL,CAAG,EAAA;AAAA,EACD,EAAI,EAAA,UAAA;AAAA,EACJ,KAAO,EAAA,UAAA;AAAA,EACP,IAAM,EAAA,UAAA;AAAA,EACN,CAAG,EAAA,GAAA;AAAA,EACH,CAAG,EAAA;AACL,CAAG,EAAA;AAAA,EACD,EAAI,EAAA,SAAA;AAAA,EACJ,KAAO,EAAA,SAAA;AAAA,EACP,IAAM,EAAA,SAAA;AAAA,EACN,CAAG,EAAA,GAAA;AAAA,EACH,CAAG,EAAA;AACL,CAAG,EAAA;AAAA,EACD,EAAI,EAAA,aAAA;AAAA,EACJ,KAAO,EAAA,aAAA;AAAA,EACP,IAAM,EAAA,gBAAA;AAAA,EACN,CAAG,EAAA,GAAA;AAAA,EACH,CAAG,EAAA;AACL,CAAC;AACe,SAAA,UAAA,CAAW,UAAkB,MAIhC,EAAA;AA5Vb,EAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA;AA6VE,EAAW,OAAA,IAAA,CAAA;AACX,EAAO,OAAA;AAAA,IACL,EAAA,EAAI,QAAQ,OAAO,CAAA,CAAA;AAAA,IACnB,IAAA,EAAA,CAAM,EAAQ,GAAA,MAAA,IAAA,IAAA,GAAA,MAAA,GAAA,MAAA,CAAA,IAAA,KAAR,IAAgB,GAAA,EAAA,GAAA,OAAA;AAAA,IACtB,QAAA;AAAA,IACA,WAAa,EAAA,CAAA;AAAA,IACb,CAAA,EAAA,CAAG,EAAQ,GAAA,MAAA,IAAA,IAAA,GAAA,MAAA,GAAA,MAAA,CAAA,CAAA,KAAR,IAAa,GAAA,EAAA,GAAA,GAAA;AAAA,IAChB,CAAA,EAAA,CAAG,EAAQ,GAAA,MAAA,IAAA,IAAA,GAAA,MAAA,GAAA,MAAA,CAAA,CAAA,KAAR,IAAa,GAAA,EAAA,GAAA;AAAA,GAClB;AACF;AAIO,SAAS,gBAAgB,IAAiC,EAAA;AA1WjE,EAAA,IAAA,EAAA;AA2WE,EAAI,IAAA,IAAA,CAAK,SAAS,OAAS,EAAA,OAAA,CAAA,CAAQ,UAAK,WAAL,KAAA,IAAA,GAAA,EAAA,GAAoB,qBAAqB,IAAK,CAAA,KAAA;AACjF,EAAI,IAAA,IAAA,CAAK,UAAe,KAAA,IAAA,EAAa,OAAA,IAAA;AACrC,EAAO,OAAA,IAAA,CAAK,IAAI,CAAG,EAAA,IAAA,CAAK,aAAa,IAAK,CAAA,YAAY,IAAI,IAAK,CAAA,KAAA;AACjE;AAGO,SAAS,iBAAiB,KAG/B,EAAA;AACA,EAAA,IAAI,QAAW,GAAA,CAAA;AACf,EAAA,IAAI,UAAa,GAAA,KAAA;AACjB,EAAA,KAAA,MAAW,QAAQ,KAAO,EAAA;AACxB,IAAM,MAAA,GAAA,GAAM,gBAAgB,IAAI,CAAA;AAChC,IAAI,IAAA,GAAA,KAAQ,MAAmB,UAAA,GAAA,IAAA;AAAA,SAAsB,QAAA,IAAA,GAAA;AAAA;AAEvD,EAAO,OAAA;AAAA,IACL,QAAU,EAAA,IAAA,CAAK,KAAM,CAAA,QAAA,GAAW,EAAE,CAAI,GAAA,EAAA;AAAA,IACtC;AAAA,GACF;AACF;AACgB,SAAA,UAAA,CAAW,QAA0B,EAAA,EAAA,EAAY,KAA4C,EAAA;AAC3G,EAAA,OAAO,iCACF,QADE,CAAA,EAAA;AAAA,IAEL,KAAA,EAAO,QAAS,CAAA,KAAA,CAAM,GAAI,CAAA,CAAA,CAAA,KAAK,EAAE,EAAO,KAAA,EAAA,GAAK,aACxC,CAAA,cAAA,CAAA,cAAA,CAAA,EAAA,EAAA,CAAA,CAAA,EACA,KAFwC,CAAA,EAAA;AAAA,MAG3C,IAAI,CAAE,CAAA;AAAA,SACJ,CAAC;AAAA,GACP,CAAA;AACF;AACgB,SAAA,QAAA,CAAS,QAA0B,EAAA,EAAA,EAAY,GAA6B,EAAA;AAC1F,EAAA,MAAM,QAAQ,QAAS,CAAA,KAAA,CAAM,UAAU,CAAK,CAAA,KAAA,CAAA,CAAE,OAAO,EAAE,CAAA;AACvD,EAAA,MAAM,KAAK,KAAQ,GAAA,GAAA;AACnB,EAAI,IAAA,KAAA,GAAQ,KAAK,EAAK,GAAA,CAAA,IAAK,MAAM,QAAS,CAAA,KAAA,CAAM,QAAe,OAAA,QAAA;AAC/D,EAAA,MAAM,KAAQ,GAAA,CAAC,GAAG,QAAA,CAAS,KAAK,CAAA;AAChC,EAAA,MAAM,CAAC,IAAI,CAAA,GAAI,KAAM,CAAA,MAAA,CAAO,OAAO,CAAC,CAAA;AACpC,EAAM,KAAA,CAAA,MAAA,CAAO,EAAI,EAAA,CAAA,EAAG,IAAI,CAAA;AACxB,EAAA,OAAO,iCACF,QADE,CAAA,EAAA;AAAA,IAEL;AAAA,GACF,CAAA;AACF;AACgB,SAAA,UAAA,CAAW,UAA0B,EAA4B,EAAA;AAC/E,EAAA,OAAO,iCACF,QADE,CAAA,EAAA;AAAA,IAEL,OAAO,QAAS,CAAA,KAAA,CAAM,OAAO,CAAK,CAAA,KAAA,CAAA,CAAE,OAAO,EAAE;AAAA,GAC/C,CAAA;AACF;AACgB,SAAA,UAAA,CAAW,QAA0B,EAAA,EAAA,EAAY,KAA0C,EAAA;AACzG,EAAA,OAAO,iCACF,QADE,CAAA,EAAA;AAAA,IAEL,KAAA,EAAO,QAAS,CAAA,KAAA,CAAM,GAAI,CAAA,CAAA,CAAA,KAAK,EAAE,EAAO,KAAA,EAAA,GAAK,aACxC,CAAA,cAAA,CAAA,cAAA,CAAA,EAAA,EAAA,CAAA,CAAA,EACA,KAFwC,CAAA,EAAA;AAAA,MAG3C,IAAI,CAAE,CAAA;AAAA,SACJ,CAAC;AAAA,GACP,CAAA;AACF;AACgB,SAAA,UAAA,CAAW,UAA0B,EAA4B,EAAA;AAC/E,EAAA,OAAO,iCACF,QADE,CAAA,EAAA;AAAA,IAEL,OAAO,QAAS,CAAA,KAAA,CAAM,OAAO,CAAK,CAAA,KAAA,CAAA,CAAE,OAAO,EAAE;AAAA,GAC/C,CAAA;AACF;AAGgB,SAAA,QAAA,CAAS,IAAkB,EAAA,QAAA,EAAkB,MAAwE,EAAA;AACnI,EAAA,MAAM,KAAQ,GAAA,IAAA,CAAK,GAAI,CAAA,CAAA,EAAG,QAAQ,CAAA;AAClC,EAAI,IAAA,MAAA,KAAW,MAAa,OAAA;AAAA,IAC1B,YAAc,EAAA,KAAA;AAAA,IACd,UAAY,EAAA;AAAA,GACd;AACA,EAAO,OAAA;AAAA,IACL,YAAA,EAAc,KAAK,GAAI,CAAA,KAAA,EAAO,KAAK,GAAI,CAAA,CAAA,EAAG,MAAS,GAAA,GAAG,CAAC,CAAA;AAAA,IACvD,UAAY,EAAA,IAAA,CAAK,GAAI,CAAA,MAAA,EAAQ,QAAQ,GAAG;AAAA,GAC1C;AACF;AACO,SAAS,gBAAgB,QAA2C,EAAA;AAzb3E,EAAA,IAAA,EAAA;AA0bE,EAAO,OAAA,aAAA,CAAA,cAAA,CAAA,cAAA,CAAA,cAAA,CAAA;AAAA,IACL,OAAS,EAAA,CAAA;AAAA,IACT,GAAK,EAAA,EAAA;AAAA,IACL,MAAQ,EAAA;AAAA,GAAA,EACJ,SAAS,SAAY,GAAA;AAAA,IACvB,WAAW,QAAS,CAAA;AAAA,GAClB,GAAA,EACA,CAAA,EAAA,QAAA,CAAS,UAAa,GAAA;AAAA,IACxB,YAAY,QAAS,CAAA;AAAA,MACnB,EAAC,CAAA,EAAA,CAAA,CACD,EAAS,GAAA,QAAA,CAAA,QAAA,KAAT,mBAAmB,MAAS,IAAA;AAAA,IAC9B,UAAU,QAAS,CAAA;AAAA,GACrB,GAAI,EAZC,CAAA,EAAA;AAAA,IAaL,KAAO,EAAA,QAAA,CAAS,KAAM,CAAA,GAAA,CAAI,CAAC;AAAA,MACzB,IAAA;AAAA,MACA,GAAA;AAAA,MACA,WAAA;AAAA,MACA,YAAA;AAAA,MACA,UAAA;AAAA,MACA,KAAA;AAAA,MACA,UAAA;AAAA,MACA,MAAA;AAAA,MACA,QAAA;AAAA,MACA,YAAA;AAAA,MACA,MAAA;AAAA,MACA,KAAA;AAAA,MACA;AAAA,KACK,KAAA,cAAA,CAAA;AAAA,MACL,IAAA;AAAA,MACA,GAAA;AAAA,MACA,WAAA;AAAA,MACA,YAAA;AAAA,MACA,UAAA;AAAA,MACA,KAAA;AAAA,MACA,UAAA;AAAA,MACA,MAAA;AAAA,MACA,QAAA;AAAA,MACA,YAAA;AAAA,MACA,MAAA;AAAA,MACA;AAAA,KAAA,EACI,SAAY,GAAA;AAAA,MACd;AAAA,KACF,GAAI,EACJ,CAAA,CAAA;AAAA,IACF,OAAO,QAAS,CAAA;AAAA,GAClB,CAAA;AACF"}
|
|
1
|
+
{"version":3,"file":"editorModel.js","sources":["../../../../src/features/canvas/videoEditor/editorModel.ts"],"sourcesContent":["/**\n * Pure timeline model for the native video editor - every edit the UI can\n * make, as data. No RN imports so it runs identically under Metro, rspack\n * and jest, and the export spec is the single contract the yantra-video\n * render service consumes.\n */\nimport type { CanvasItem } from '../canvasCore';\nimport { parseHexColor } from './solidColorPng';\n\nexport { colorFromSolidSrc, solidColorPngDataUrl, uploadFilenameFor } from './solidColorPng';\n\nexport type FilterId = 'none' | 'cinematic' | 'film' | 'kodak' | 'mono' | 'vivid' | 'warm' | 'cool' | 'dreamy';\n\n/** Stage-toolbar motion — canvas-surface StageToolbar. */\nexport type KenBurns = { zoomStart: number; zoomEnd: number; direction: string };\n\nexport const MOTION_STRENGTHS = [\n { id: 'subtle', label: 'Subtle', zoom: 1.1 },\n { id: 'normal', label: 'Normal', zoom: 1.3 },\n { id: 'strong', label: 'Strong', zoom: 1.7 },\n] as const;\n\nexport const MOTION_MOVES = [\n { id: 'none', label: 'None' },\n { id: 'zoom-in', label: 'Zoom in' },\n { id: 'zoom-out', label: 'Zoom out' },\n { id: 'pan-left', label: 'Pan left' },\n { id: 'pan-right', label: 'Pan right' },\n { id: 'pan-up', label: 'Pan up' },\n { id: 'pan-down', label: 'Pan down' },\n] as const;\n\nexport const CLIP_TRANSITIONS = [\n 'fade',\n 'wipeleft',\n 'wiperight',\n 'slideup',\n 'slidedown',\n 'circleopen',\n 'dissolve',\n] as const;\n\nexport function kenBurnsFor(move: string, zoom: number): KenBurns | null {\n if (move === 'none') return null;\n if (move === 'zoom-in') return { zoomStart: 1, zoomEnd: zoom, direction: 'center' };\n if (move === 'zoom-out') return { zoomStart: zoom, zoomEnd: 1, direction: 'center' };\n return { zoomStart: zoom, zoomEnd: zoom, direction: move.replace('pan-', '') };\n}\n\nexport function moveIdOf(kb: KenBurns | null | undefined): string {\n if (!kb) return 'none';\n if (kb.direction !== 'center') return `pan-${kb.direction}`;\n return kb.zoomEnd >= kb.zoomStart ? 'zoom-in' : 'zoom-out';\n}\n\n/** Constant playback speeds the preview can honestly reproduce. */\nexport const SPEED_PRESETS = [0.5, 1, 1.5, 2] as const;\nexport type SpeedPreset = (typeof SPEED_PRESETS)[number];\n\n/** Speed-curve intents rendered server-side; preview plays the base speed. */\nexport type SpeedCurve = 'constant' | 'ease-in' | 'ease-out' | 'pulse';\nexport const SPEED_CURVES: readonly SpeedCurve[] = ['constant', 'ease-in', 'ease-out', 'pulse'];\n\nexport interface EditorClip {\n /** Unique per timeline entry - the same media can appear twice. */\n id: string;\n itemId: string;\n type: 'image' | 'video';\n src: string;\n name: string;\n /** Images hold a still for this long; null = the video's own length. */\n durationSec: number | null;\n /** Seconds cut from the head of a video clip. */\n trimStartSec: number;\n /** Absolute end point in source seconds; null = source end. */\n trimEndSec: number | null;\n speed: SpeedPreset;\n speedCurve: SpeedCurve;\n filter: FilterId;\n kenBurns?: KenBurns | null;\n /** xfade into this clip from the previous one. */\n transitionIn?: { effect: string; durationMs: number } | null;\n /** 0..1 */\n volume: number;\n muted: boolean;\n /** Solid colour scene — `src` is a preview GIF; export paints a PNG. */\n fillColor?: string | null;\n /** Only a definite \"no audio stream\" is carried (from the board item); keeps it out of the audio lane. */\n hasAudio?: false;\n /**\n * On a designed scene: what an AI video model films for it (web\n * EditorClip.shot). Produce video reads it; it stays once the scene has\n * footage so the scene can be filmed again.\n */\n shot?: string;\n}\n\nexport interface TextClip {\n id: string;\n text: string;\n startSec: number;\n durationSec: number;\n /** Normalized 0..1 position of the text centre on the frame. */\n x: number;\n y: number;\n /**\n * The scene (base clip id) this layer belongs to: it moves with that\n * scene and shows only while it is open. Missing = a global layer\n * (every project saved before scene-scoped layers).\n */\n sceneId?: string;\n}\n\n/** Cursorful-style ranged effect over the cut (web ClipSegment). */\nexport type SegmentKind = 'speed' | 'zoom' | 'crop' | 'trim' | 'blur';\nexport type ZoomDepth = 'subtle' | 'moderate' | 'strong';\n\nexport interface EditorSegment {\n id: string;\n kind: SegmentKind;\n name: string;\n startSec: number;\n durationSec: number;\n speed?: number;\n zoom?: { x: number; y: number; depth: ZoomDepth };\n crop?: { x: number; y: number; width: number; height: number };\n /** Box blurred for the range, in frame % (0..100); `radius` in px (web ClipSegment.blur). */\n blur?: BlurBox;\n /** Owning scene (base clip id); missing = global. See TextClip.sceneId. */\n sceneId?: string;\n}\n\nexport interface BlurBox {\n x: number;\n y: number;\n width: number;\n height: number;\n radius: number;\n}\n\n/** Web AddSegmentPopover default: a centred-ish box, 5px blur. */\nexport const DEFAULT_BLUR_BOX: BlurBox = { x: 35, y: 40, width: 30, height: 20, radius: 5 };\n\nexport const SEGMENT_LENGTH_SEC = 2;\n\n/** 2s range at the playhead, kept inside the cut so the ruler does not grow. */\nexport function rangeAtPlayhead(playheadSec: number, totalSec: number): { startSec: number; durationSec: number } {\n const span = Math.max(totalSec, SEGMENT_LENGTH_SEC);\n const startSec = Math.max(0, Math.min(playheadSec, span - SEGMENT_LENGTH_SEC));\n return { startSec, durationSec: Math.min(SEGMENT_LENGTH_SEC, Math.max(0.5, span - startSec)) };\n}\n\nexport function newSegment(kind: SegmentKind, playheadSec: number, totalSec: number): EditorSegment {\n counter += 1;\n const { startSec, durationSec } = rangeAtPlayhead(playheadSec, totalSec);\n if (kind === 'speed') {\n return { id: `seg-${counter}`, kind, name: 'Speed ×2', startSec, durationSec, speed: 2 };\n }\n if (kind === 'zoom') {\n return {\n id: `seg-${counter}`,\n kind,\n name: 'Zoom subtle',\n startSec,\n durationSec,\n zoom: { x: 50, y: 50, depth: 'subtle' },\n };\n }\n if (kind === 'crop') {\n return {\n id: `seg-${counter}`,\n kind,\n name: 'Crop',\n startSec,\n durationSec,\n crop: { x: 10, y: 10, width: 80, height: 80 },\n };\n }\n if (kind === 'blur') {\n return { id: `seg-${counter}`, kind, name: 'Blur', startSec, durationSec, blur: { ...DEFAULT_BLUR_BOX } };\n }\n return { id: `seg-${counter}`, kind: 'trim', name: 'Trim', startSec, durationSec };\n}\n\n/** A generated narration/voice track laid under the whole timeline. */\nexport interface Voiceover {\n /** Rendered speech audio (voicebox SPEAK output). */\n audioUrl: string;\n /** mix = duck under existing audio; replace = swap the audio track. */\n mode: 'mix' | 'replace';\n /** Voice name/profile used - display only. */\n voiceLabel?: string;\n /** The spoken text - kept for re-generation. */\n text?: string;\n}\n\n/** A music bed laid under the whole timeline (generated or user-provided). */\nexport interface Soundtrack {\n /** Fetchable audio URL (yantra-audio generation output or an upload). */\n audioUrl: string;\n /** mix = duck under existing audio; replace = swap the audio track. */\n mode: 'mix' | 'replace';\n /** Display label - the generation prompt or the track name. */\n title?: string;\n}\n\n/**\n * Audio that belongs to one scene (a narration section, a sound effect):\n * it starts at `startSec` on the timeline and moves with its scene.\n */\nexport interface SceneAudio {\n id: string;\n audioUrl: string;\n startSec: number;\n /** Seconds of the source to play; null = to its end. */\n durationSec: number | null;\n /** 0..1 */\n volume: number;\n label?: string;\n /** Owning scene (base clip id); missing = global. */\n sceneId?: string;\n}\n\nexport interface EditorTimeline {\n clips: EditorClip[];\n texts: TextClip[];\n segments?: EditorSegment[];\n voiceover?: Voiceover | null;\n soundtrack?: Soundtrack | null;\n /** Timed audio layers (per-scene narration/effects). Optional: old saves have none. */\n sceneAudio?: SceneAudio[];\n /** The cut's frame, \"W:H\" (from a designed promo or template); absent = the first scene's media decides. */\n aspect?: string;\n}\n\nexport function emptyTimeline(): EditorTimeline {\n return { clips: [], texts: [], segments: [], voiceover: null, soundtrack: null };\n}\n\nexport interface VideoExportSpec {\n version: 2;\n fps: 30;\n format: 'mp4';\n clips: Array<\n Pick<\n EditorClip,\n | 'type'\n | 'src'\n | 'durationSec'\n | 'trimStartSec'\n | 'trimEndSec'\n | 'speed'\n | 'speedCurve'\n | 'filter'\n | 'kenBurns'\n | 'transitionIn'\n | 'volume'\n | 'muted'\n | 'fillColor'\n > & {\n /** The editor clip id - what scene-scoped layers' `sceneId` names. */\n id?: string;\n /** Known source length (s) of a video, from the player; lets the compiler hold footage through a transition. */\n sourceDurationSec?: number;\n /** false = the source is known to carry no audio stream (kept out of the audio lane). */\n hasAudio?: boolean;\n }\n >;\n texts: TextClip[];\n segments?: EditorSegment[];\n voiceover?: Voiceover | null;\n soundtrack?: Soundtrack | null;\n sceneAudio?: SceneAudio[];\n /** Output frame for the compiled render (letterbox target); absent = 1280x720. */\n canvas?: { width: number; height: number };\n}\n\nexport interface ExportSpecOptions {\n /** Known source seconds per clip id (the editor's player measurements). */\n sourceSec?: Readonly<Record<string, number>>;\n /** Output frame - see VideoExportSpec.canvas. */\n canvas?: { width: number; height: number };\n}\n\nexport const DEFAULT_IMAGE_SEC = 3;\n\nlet counter = 0;\n/** Test seam: deterministic ids. */\nexport function resetEditorIds(): void {\n counter = 0;\n}\n\nexport function clipFromItem(item: CanvasItem): EditorClip {\n counter += 1;\n return {\n id: `clip-${counter}`,\n itemId: item.id,\n type: item.type === 'video' ? 'video' : 'image',\n src: item.src,\n name: item.generatedAssetName?.trim() || (item.type === 'video' ? 'Video' : 'Image'),\n durationSec: item.type === 'video' ? null : DEFAULT_IMAGE_SEC,\n trimStartSec: 0,\n trimEndSec: null,\n speed: 1,\n speedCurve: 'constant',\n filter: 'none',\n kenBurns: null,\n transitionIn: null,\n volume: 1,\n muted: false,\n ...(item.hasAudio === false ? { hasAudio: false as const } : {}),\n };\n}\n\n/** 1×1 GIF data URL — blank color scenes without a network placeholder. */\nexport function solidColorSrc(hex: string): string {\n const h = hex.replace('#', '').padEnd(6, '0');\n const r = Number.parseInt(h.slice(0, 2), 16) || 0;\n const g = Number.parseInt(h.slice(2, 4), 16) || 0;\n const b = Number.parseInt(h.slice(4, 6), 16) || 0;\n const bytes = [\n 0x47,\n 0x49,\n 0x46,\n 0x38,\n 0x39,\n 0x61,\n 0x01,\n 0x00,\n 0x01,\n 0x00,\n 0x80,\n 0x00,\n 0x00,\n r,\n g,\n b,\n 0x00,\n 0x00,\n 0x00,\n 0x2c,\n 0x00,\n 0x00,\n 0x00,\n 0x00,\n 0x01,\n 0x00,\n 0x01,\n 0x00,\n 0x00,\n 0x02,\n 0x02,\n 0x44,\n 0x01,\n 0x00,\n 0x3b,\n ];\n let bin = '';\n for (const byte of bytes) bin += String.fromCharCode(byte);\n const b64 =\n typeof globalThis.btoa === 'function'\n ? globalThis.btoa(bin)\n : Buffer.from(Uint8Array.from(bytes)).toString('base64');\n return `data:image/gif;base64,${b64}`;\n}\n\nexport function clipFromColor(hex: string): EditorClip {\n const { hex: fillColor } = parseHexColor(hex);\n return {\n ...clipFromItem({\n id: `scene-${hex.replace('#', '')}-${counter + 1}`,\n type: 'image',\n src: solidColorSrc(fillColor),\n x: 0,\n y: 0,\n width: 640,\n height: 360,\n zIndex: 1,\n generatedAssetName: 'Blank scene',\n }),\n fillColor,\n };\n}\n\n/** Title-card presets — same four as canvas-surface MediaLibrary TEXT_PRESETS. */\nexport const TEXT_PRESETS = [\n { id: 'title', label: 'Title', text: 'Title', x: 0.5, y: 0.38 },\n { id: 'subtitle', label: 'Subtitle', text: 'Subtitle', x: 0.5, y: 0.54 },\n { id: 'caption', label: 'Caption', text: 'Caption', x: 0.5, y: 0.86 },\n { id: 'lower-third', label: 'Lower third', text: 'Name · Role', x: 0.5, y: 0.78 },\n] as const;\n\nexport function textClipAt(startSec: number, preset?: { text: string; x: number; y: number }): TextClip {\n counter += 1;\n return {\n id: `text-${counter}`,\n text: preset?.text ?? 'Title',\n startSec,\n durationSec: 2,\n x: preset?.x ?? 0.5,\n y: preset?.y ?? 0.35,\n };\n}\n\n/** Effective duration a clip contributes to the timeline, after trim+speed.\n * Unknown-length videos report null - the UI says \"video\", not a guess. */\nexport function clipTimelineSec(clip: EditorClip): number | null {\n if (clip.type === 'image') return (clip.durationSec ?? DEFAULT_IMAGE_SEC) / clip.speed;\n if (clip.trimEndSec === null) return null;\n return Math.max(0, clip.trimEndSec - clip.trimStartSec) / clip.speed;\n}\n\n/** Total known seconds + whether unknown-length video remains. */\nexport function timelineDuration(clips: readonly EditorClip[]): { knownSec: number; hasUnknown: boolean } {\n let knownSec = 0;\n let hasUnknown = false;\n for (const clip of clips) {\n const sec = clipTimelineSec(clip);\n if (sec === null) hasUnknown = true;\n else knownSec += sec;\n }\n return { knownSec: Math.round(knownSec * 10) / 10, hasUnknown };\n}\n\nexport function updateClip(timeline: EditorTimeline, id: string, patch: Partial<EditorClip>): EditorTimeline {\n return {\n ...timeline,\n clips: timeline.clips.map((c) => (c.id === id ? { ...c, ...patch, id: c.id } : c)),\n };\n}\n\nexport function moveClip(timeline: EditorTimeline, id: string, dir: -1 | 1): EditorTimeline {\n const index = timeline.clips.findIndex((c) => c.id === id);\n const to = index + dir;\n if (index < 0 || to < 0 || to >= timeline.clips.length) return timeline;\n const clips = [...timeline.clips];\n const [clip] = clips.splice(index, 1);\n clips.splice(to, 0, clip);\n return { ...timeline, clips };\n}\n\nexport function removeClip(timeline: EditorTimeline, id: string): EditorTimeline {\n return { ...timeline, clips: timeline.clips.filter((c) => c.id !== id) };\n}\n\nexport function updateText(timeline: EditorTimeline, id: string, patch: Partial<TextClip>): EditorTimeline {\n return {\n ...timeline,\n texts: timeline.texts.map((t) => (t.id === id ? { ...t, ...patch, id: t.id } : t)),\n };\n}\n\nexport function removeText(timeline: EditorTimeline, id: string): EditorTimeline {\n return { ...timeline, texts: timeline.texts.filter((t) => t.id !== id) };\n}\n\n/** Clamp a trim edit so the window never inverts or escapes the source. */\nexport function trimClip(\n clip: EditorClip,\n startSec: number,\n endSec: number | null,\n): Pick<EditorClip, 'trimStartSec' | 'trimEndSec'> {\n const start = Math.max(0, startSec);\n if (endSec === null) return { trimStartSec: start, trimEndSec: null };\n return { trimStartSec: Math.min(start, Math.max(0, endSec - 0.1)), trimEndSec: Math.max(endSec, start + 0.1) };\n}\n\nexport function buildExportSpec(timeline: EditorTimeline, options: ExportSpecOptions = {}): VideoExportSpec {\n return {\n version: 2,\n fps: 30,\n format: 'mp4',\n ...(timeline.voiceover ? { voiceover: timeline.voiceover } : {}),\n ...(timeline.soundtrack ? { soundtrack: timeline.soundtrack } : {}),\n ...(timeline.segments?.length ? { segments: timeline.segments } : {}),\n ...(timeline.sceneAudio?.length ? { sceneAudio: timeline.sceneAudio } : {}),\n ...(options.canvas ? { canvas: options.canvas } : {}),\n clips: timeline.clips.map(\n ({\n id,\n hasAudio,\n type,\n src,\n durationSec,\n trimStartSec,\n trimEndSec,\n speed,\n speedCurve,\n filter,\n kenBurns,\n transitionIn,\n volume,\n muted,\n fillColor,\n }) => ({\n type,\n src,\n durationSec,\n trimStartSec,\n trimEndSec,\n speed,\n speedCurve,\n filter,\n kenBurns,\n transitionIn,\n volume,\n muted,\n ...(fillColor ? { fillColor } : {}),\n id,\n ...(hasAudio === false ? { hasAudio } : {}),\n ...(options.sourceSec?.[id] && options.sourceSec[id] > 0\n ? { sourceDurationSec: options.sourceSec[id] }\n : {}),\n }),\n ),\n texts: timeline.texts,\n };\n}\n"],"names":["_a"],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {specMixesSceneAudio,compileTimeline}from'./compileTimeline.js';import {colorFromSolidSrc}from'./solidColorPng.js';import {probeSpecSources,materializeTimelineInputs,isLocalOnlyUrl}from'./renderTimeline.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
|
+
const isSolidScene = (clip) => clip.type === "image" && Boolean(clip.fillColor || colorFromSolidSrc(clip.src));
|
|
21
|
+
async function liftSpecSources(spec, options = {}) {
|
|
22
|
+
const cache = /* @__PURE__ */ new Map();
|
|
23
|
+
const lift = (url) => {
|
|
24
|
+
if (!url) return Promise.resolve(url);
|
|
25
|
+
let pending = cache.get(url);
|
|
26
|
+
if (!pending) {
|
|
27
|
+
pending = (async () => {
|
|
28
|
+
var _a;
|
|
29
|
+
if (isLocalOnlyUrl(url)) {
|
|
30
|
+
if (!options.upload) throw new Error("A clip is on this phone and no uploader is available");
|
|
31
|
+
(_a = options.onProgress) == null ? void 0 : _a.call(options, `Uploading media ${cache.size}\u2026`);
|
|
32
|
+
return options.upload(url);
|
|
33
|
+
}
|
|
34
|
+
return options.refresh ? options.refresh(url) : url;
|
|
35
|
+
})();
|
|
36
|
+
cache.set(url, pending);
|
|
37
|
+
}
|
|
38
|
+
return pending;
|
|
39
|
+
};
|
|
40
|
+
const clips = [];
|
|
41
|
+
for (const clip of spec.clips) {
|
|
42
|
+
clips.push(isSolidScene(clip) ? clip : __spreadProps(__spreadValues({}, clip), {
|
|
43
|
+
src: await lift(clip.src)
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
const audio = async (a) => a ? __spreadProps(__spreadValues({}, a), {
|
|
47
|
+
audioUrl: await lift(a.audioUrl)
|
|
48
|
+
}) : a;
|
|
49
|
+
const sceneAudio = spec.sceneAudio ? await Promise.all(spec.sceneAudio.map(async (a) => __spreadProps(__spreadValues({}, a), {
|
|
50
|
+
audioUrl: await lift(a.audioUrl)
|
|
51
|
+
}))) : void 0;
|
|
52
|
+
return __spreadValues(__spreadProps(__spreadValues({}, spec), {
|
|
53
|
+
clips,
|
|
54
|
+
voiceover: await audio(spec.voiceover),
|
|
55
|
+
soundtrack: await audio(spec.soundtrack)
|
|
56
|
+
}), sceneAudio ? {
|
|
57
|
+
sceneAudio
|
|
58
|
+
} : {});
|
|
59
|
+
}
|
|
60
|
+
async function prepareRenderTimeline(spec, run, options = {}) {
|
|
61
|
+
var _a, _b;
|
|
62
|
+
(_a = options.onProgress) == null ? void 0 : _a.call(options, "Preparing media\u2026");
|
|
63
|
+
const lifted = await liftSpecSources(spec, options);
|
|
64
|
+
(_b = options.onProgress) == null ? void 0 : _b.call(options, "Measuring clips\u2026");
|
|
65
|
+
const probed = await probeSpecSources(lifted, run, {
|
|
66
|
+
needAudio: specMixesSceneAudio(lifted)
|
|
67
|
+
});
|
|
68
|
+
const compiled = compileTimeline(probed);
|
|
69
|
+
if (!compiled.steps.length && compiled.finalRef.kind === "url" && !compiled.finalRef.url) {
|
|
70
|
+
throw new Error("Nothing to render");
|
|
71
|
+
}
|
|
72
|
+
await materializeTimelineInputs(compiled, {
|
|
73
|
+
upload: options.upload,
|
|
74
|
+
onProgress: options.onProgress
|
|
75
|
+
});
|
|
76
|
+
return compiled;
|
|
77
|
+
}export{liftSpecSources,prepareRenderTimeline};//# sourceMappingURL=exportPipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exportPipeline.js","sources":["../../../../src/features/canvas/videoEditor/exportPipeline.ts"],"sourcesContent":["/**\n * Everything between the editor's VideoExportSpec and a SUBMIT-ready render\n * timeline: phone-local clips uploaded, stored links re-signed, video sources\n * probed (open trims, sound-less videos), compiled, and every input of the\n * compiled steps made fetchable. Shared by the durable export task and tests.\n */\nimport { compileTimeline, specMixesSceneAudio, type CompiledTimeline } from './compileTimeline';\nimport { colorFromSolidSrc } from './solidColorPng';\nimport type { VideoExportSpec } from './editorModel';\nimport type { RunMediaAction } from './mediaActions';\nimport { isLocalOnlyUrl, materializeTimelineInputs, probeSpecSources } from './renderTimeline';\n\nexport interface PrepareExportOptions {\n /** Host uploader for phone-local media (file://, ph://, data:). */\n upload?: (localUri: string) => Promise<string>;\n /** Re-sign a stored media link that may have lapsed (mediaUrls.ensureFetchableMediaUrl). */\n refresh?: (url: string) => Promise<string>;\n onProgress?: (label: string) => void;\n}\n\n/** A blank colour scene - painted at compile time, never uploaded as its preview GIF. */\nconst isSolidScene = (clip: VideoExportSpec['clips'][number]) =>\n clip.type === 'image' && Boolean(clip.fillColor || colorFromSolidSrc(clip.src));\n\n/** Upload phone-local clip sources and re-sign stored ones, once per distinct URL. */\nexport async function liftSpecSources(\n spec: VideoExportSpec,\n options: PrepareExportOptions = {},\n): Promise<VideoExportSpec> {\n const cache = new Map<string, Promise<string>>();\n const lift = (url: string): Promise<string> => {\n if (!url) return Promise.resolve(url);\n let pending = cache.get(url);\n if (!pending) {\n pending = (async () => {\n if (isLocalOnlyUrl(url)) {\n if (!options.upload) throw new Error('A clip is on this phone and no uploader is available');\n options.onProgress?.(`Uploading media ${cache.size}…`);\n return options.upload(url);\n }\n return options.refresh ? options.refresh(url) : url;\n })();\n cache.set(url, pending);\n }\n return pending;\n };\n const clips = [];\n for (const clip of spec.clips) {\n clips.push(isSolidScene(clip) ? clip : { ...clip, src: await lift(clip.src) });\n }\n const audio = async <T extends { audioUrl: string }>(a: T | null | undefined): Promise<T | null | undefined> =>\n a ? { ...a, audioUrl: await lift(a.audioUrl) } : a;\n const sceneAudio = spec.sceneAudio\n ? await Promise.all(spec.sceneAudio.map(async (a) => ({ ...a, audioUrl: await lift(a.audioUrl) })))\n : undefined;\n return {\n ...spec,\n clips,\n voiceover: await audio(spec.voiceover),\n soundtrack: await audio(spec.soundtrack),\n ...(sceneAudio ? { sceneAudio } : {}),\n };\n}\n\n/** Spec -> fetchable compiled timeline (steps may be empty: then finalRef IS the export). */\nexport async function prepareRenderTimeline(\n spec: VideoExportSpec,\n run: RunMediaAction,\n options: PrepareExportOptions = {},\n): Promise<CompiledTimeline> {\n options.onProgress?.('Preparing media…');\n const lifted = await liftSpecSources(spec, options);\n options.onProgress?.('Measuring clips…');\n const probed = await probeSpecSources(lifted, run, { needAudio: specMixesSceneAudio(lifted) });\n const compiled = compileTimeline(probed);\n if (!compiled.steps.length && compiled.finalRef.kind === 'url' && !compiled.finalRef.url) {\n throw new Error('Nothing to render');\n }\n await materializeTimelineInputs(compiled, {\n upload: options.upload,\n onProgress: options.onProgress,\n });\n return compiled;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import {resultUrl}from'./mediaActions.js';import {colorFromSolidSrc,solidColorPngDataUrl}from'./solidColorPng.js';var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
2
4
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
6
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
@@ -14,6 +16,7 @@ var __spreadValues = (a, b) => {
|
|
|
14
16
|
}
|
|
15
17
|
return a;
|
|
16
18
|
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
17
20
|
const VIDEO = "yantra-video-editing";
|
|
18
21
|
const FILTER_GRADE = {
|
|
19
22
|
none: null,
|
|
@@ -65,7 +68,11 @@ function imageSrcForExport(clip) {
|
|
|
65
68
|
}
|
|
66
69
|
async function renderExportSpec(spec, runAction, uploadMedia, onProgress) {
|
|
67
70
|
var _a, _b, _c, _d, _e;
|
|
68
|
-
const
|
|
71
|
+
const tail = spec.texts.length ? "text" : spec.voiceover ? "voiceover" : spec.soundtrack ? "soundtrack" : spec.clips.length > 1 ? "concat" : "clip";
|
|
72
|
+
const run = async (action, params, label, final = false) => resultUrl(await runAction(VIDEO, action, final ? params : __spreadProps(__spreadValues({}, params), {
|
|
73
|
+
ephemeral: true
|
|
74
|
+
})), label);
|
|
75
|
+
const clipFinal = tail === "clip";
|
|
69
76
|
const clipUrls = [];
|
|
70
77
|
for (let i = 0; i < spec.clips.length; i += 1) {
|
|
71
78
|
const clip = spec.clips[i];
|
|
@@ -91,13 +98,13 @@ async function renderExportSpec(spec, runAction, uploadMedia, onProgress) {
|
|
|
91
98
|
zoom_start: clip.kenBurns.zoomStart,
|
|
92
99
|
zoom_end: clip.kenBurns.zoomEnd,
|
|
93
100
|
direction: clip.kenBurns.direction
|
|
94
|
-
}, "KEN_BURNS");
|
|
101
|
+
}, "KEN_BURNS", clipFinal);
|
|
95
102
|
} else {
|
|
96
103
|
url = await run("YANTRA_VIDEO_EDIT_SLIDESHOW", {
|
|
97
104
|
input_url: url,
|
|
98
105
|
duration_per_image: sec,
|
|
99
106
|
fps: spec.fps
|
|
100
|
-
}, "SLIDESHOW");
|
|
107
|
+
}, "SLIDESHOW", clipFinal);
|
|
101
108
|
}
|
|
102
109
|
} else {
|
|
103
110
|
let end = clip.trimEndSec;
|
|
@@ -119,7 +126,7 @@ async function renderExportSpec(spec, runAction, uploadMedia, onProgress) {
|
|
|
119
126
|
input_url: url,
|
|
120
127
|
start_secs: clip.trimStartSec,
|
|
121
128
|
end_secs: end
|
|
122
|
-
}, "TRIM");
|
|
129
|
+
}, "TRIM", clipFinal);
|
|
123
130
|
}
|
|
124
131
|
if (clip.speed !== 1) {
|
|
125
132
|
onProgress == null ? void 0 : onProgress({
|
|
@@ -128,7 +135,7 @@ async function renderExportSpec(spec, runAction, uploadMedia, onProgress) {
|
|
|
128
135
|
url = await run("YANTRA_VIDEO_EDIT_SPEED", {
|
|
129
136
|
input_url: url,
|
|
130
137
|
factor: clip.speed
|
|
131
|
-
}, "SPEED");
|
|
138
|
+
}, "SPEED", clipFinal);
|
|
132
139
|
}
|
|
133
140
|
if (clip.muted) {
|
|
134
141
|
onProgress == null ? void 0 : onProgress({
|
|
@@ -136,7 +143,7 @@ async function renderExportSpec(spec, runAction, uploadMedia, onProgress) {
|
|
|
136
143
|
});
|
|
137
144
|
url = await run("YANTRA_VIDEO_EDIT_MUTE", {
|
|
138
145
|
input_url: url
|
|
139
|
-
}, "MUTE");
|
|
146
|
+
}, "MUTE", clipFinal);
|
|
140
147
|
} else if (clip.volume < 0.99) {
|
|
141
148
|
onProgress == null ? void 0 : onProgress({
|
|
142
149
|
stage: `Volume ${label}`
|
|
@@ -144,7 +151,7 @@ async function renderExportSpec(spec, runAction, uploadMedia, onProgress) {
|
|
|
144
151
|
url = await run("YANTRA_VIDEO_EDIT_VOLUME", {
|
|
145
152
|
input_url: url,
|
|
146
153
|
level: clip.volume
|
|
147
|
-
}, "VOLUME");
|
|
154
|
+
}, "VOLUME", clipFinal);
|
|
148
155
|
}
|
|
149
156
|
}
|
|
150
157
|
const grade = (_e = FILTER_GRADE[clip.filter]) != null ? _e : null;
|
|
@@ -154,7 +161,7 @@ async function renderExportSpec(spec, runAction, uploadMedia, onProgress) {
|
|
|
154
161
|
});
|
|
155
162
|
url = await run("YANTRA_VIDEO_EDIT_COLOR_ADJUST", __spreadValues({
|
|
156
163
|
input_url: url
|
|
157
|
-
}, grade), "COLOR_ADJUST");
|
|
164
|
+
}, grade), "COLOR_ADJUST", clipFinal);
|
|
158
165
|
}
|
|
159
166
|
clipUrls.push(url);
|
|
160
167
|
}
|
|
@@ -168,7 +175,7 @@ async function renderExportSpec(spec, runAction, uploadMedia, onProgress) {
|
|
|
168
175
|
input_url: clipUrls[0],
|
|
169
176
|
input_urls: clipUrls.slice(1),
|
|
170
177
|
reencode: true
|
|
171
|
-
}, "CONCAT");
|
|
178
|
+
}, "CONCAT", tail === "concat");
|
|
172
179
|
}
|
|
173
180
|
if (spec.soundtrack) {
|
|
174
181
|
onProgress == null ? void 0 : onProgress({
|
|
@@ -178,7 +185,7 @@ async function renderExportSpec(spec, runAction, uploadMedia, onProgress) {
|
|
|
178
185
|
input_url: finalUrl,
|
|
179
186
|
audio_input_url: spec.soundtrack.audioUrl,
|
|
180
187
|
replace_existing: spec.soundtrack.mode === "replace"
|
|
181
|
-
}, "ADD_AUDIO");
|
|
188
|
+
}, "ADD_AUDIO", tail === "soundtrack");
|
|
182
189
|
}
|
|
183
190
|
if (spec.voiceover) {
|
|
184
191
|
onProgress == null ? void 0 : onProgress({
|
|
@@ -190,7 +197,7 @@ async function renderExportSpec(spec, runAction, uploadMedia, onProgress) {
|
|
|
190
197
|
// A replace-mode voiceover must not erase the soundtrack that
|
|
191
198
|
// was muxed one step earlier - narration mixes over it.
|
|
192
199
|
replace_existing: spec.voiceover.mode === "replace" && !spec.soundtrack
|
|
193
|
-
}, "ADD_AUDIO");
|
|
200
|
+
}, "ADD_AUDIO", tail === "voiceover");
|
|
194
201
|
}
|
|
195
202
|
for (let i = 0; i < spec.texts.length; i += 1) {
|
|
196
203
|
const t = spec.texts[i];
|
|
@@ -208,7 +215,7 @@ async function renderExportSpec(spec, runAction, uploadMedia, onProgress) {
|
|
|
208
215
|
font_color: "white",
|
|
209
216
|
start_secs: t.startSec,
|
|
210
217
|
end_secs: t.startSec + t.durationSec
|
|
211
|
-
}, "OVERLAY_TEXT");
|
|
218
|
+
}, "OVERLAY_TEXT", i === spec.texts.length - 1);
|
|
212
219
|
}
|
|
213
220
|
return finalUrl;
|
|
214
221
|
}export{renderExportSpec};//# sourceMappingURL=exportRenderer.js.map
|