@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.
Files changed (175) hide show
  1. package/lib/features/apps/appArt.js +1 -1
  2. package/lib/features/apps/appArt.js.map +1 -1
  3. package/lib/features/apps/mobileAppCatalog.js +15 -11
  4. package/lib/features/apps/mobileAppCatalog.js.map +1 -1
  5. package/lib/features/canvas/CanvasAgentChatPane.js +82 -20
  6. package/lib/features/canvas/CanvasAgentChatPane.js.map +1 -1
  7. package/lib/features/canvas/CanvasBoardsGrid.js +291 -100
  8. package/lib/features/canvas/CanvasBoardsGrid.js.map +1 -1
  9. package/lib/features/canvas/CanvasEditToolsPanel.js +105 -12
  10. package/lib/features/canvas/CanvasEditToolsPanel.js.map +1 -1
  11. package/lib/features/canvas/CanvasExperience.js +266 -68
  12. package/lib/features/canvas/CanvasExperience.js.map +1 -1
  13. package/lib/features/canvas/CanvasGeneratePanel.js +204 -66
  14. package/lib/features/canvas/CanvasGeneratePanel.js.map +1 -1
  15. package/lib/features/canvas/CanvasLibrarySheet.js +31 -13
  16. package/lib/features/canvas/CanvasLibrarySheet.js.map +1 -1
  17. package/lib/features/canvas/CanvasModelPicker.js +176 -0
  18. package/lib/features/canvas/CanvasModelPicker.js.map +1 -0
  19. package/lib/features/canvas/CanvasTasksPanel.js +325 -29
  20. package/lib/features/canvas/CanvasTasksPanel.js.map +1 -1
  21. package/lib/features/canvas/CanvasTemplatesPanel.js +5 -4
  22. package/lib/features/canvas/CanvasTemplatesPanel.js.map +1 -1
  23. package/lib/features/canvas/CanvasToolDock.js +137 -61
  24. package/lib/features/canvas/CanvasToolDock.js.map +1 -1
  25. package/lib/features/canvas/FrameExtractorExperience.js +33 -2
  26. package/lib/features/canvas/FrameExtractorExperience.js.map +1 -1
  27. package/lib/features/canvas/GeneratorReferenceSlots.js +197 -0
  28. package/lib/features/canvas/GeneratorReferenceSlots.js.map +1 -0
  29. package/lib/features/canvas/NativeCanvasViewer.js +89 -11
  30. package/lib/features/canvas/NativeCanvasViewer.js.map +1 -1
  31. package/lib/features/canvas/PromoContextFields.js +55 -2
  32. package/lib/features/canvas/PromoContextFields.js.map +1 -1
  33. package/lib/features/canvas/SetStudioExperience.js +323 -13
  34. package/lib/features/canvas/SetStudioExperience.js.map +1 -1
  35. package/lib/features/canvas/VideoEditExperience.js +1 -53
  36. package/lib/features/canvas/VideoEditExperience.js.map +1 -1
  37. package/lib/features/canvas/VideoEditorExperience.js +697 -506
  38. package/lib/features/canvas/VideoEditorExperience.js.map +1 -1
  39. package/lib/features/canvas/VideoGeneratorExperience.js +22 -5
  40. package/lib/features/canvas/VideoGeneratorExperience.js.map +1 -1
  41. package/lib/features/canvas/canvasAgentChat.js +125 -11
  42. package/lib/features/canvas/canvasAgentChat.js.map +1 -1
  43. package/lib/features/canvas/canvasCore.js +117 -12
  44. package/lib/features/canvas/canvasCore.js.map +1 -1
  45. package/lib/features/canvas/canvasEditOps.js +148 -111
  46. package/lib/features/canvas/canvasEditOps.js.map +1 -1
  47. package/lib/features/canvas/canvasTaskSync.js +235 -0
  48. package/lib/features/canvas/canvasTaskSync.js.map +1 -0
  49. package/lib/features/canvas/canvasTasks.js +98 -11
  50. package/lib/features/canvas/canvasTasks.js.map +1 -1
  51. package/lib/features/canvas/createTiles.js +247 -0
  52. package/lib/features/canvas/createTiles.js.map +1 -0
  53. package/lib/features/canvas/deepLinks.js +83 -0
  54. package/lib/features/canvas/deepLinks.js.map +1 -0
  55. package/lib/features/canvas/frameExtract.js +13 -1
  56. package/lib/features/canvas/frameExtract.js.map +1 -1
  57. package/lib/features/canvas/generationModels.js +36 -8
  58. package/lib/features/canvas/generationModels.js.map +1 -1
  59. package/lib/features/canvas/generatorCommands.js +106 -0
  60. package/lib/features/canvas/generatorCommands.js.map +1 -0
  61. package/lib/features/canvas/generatorReferences.js +82 -0
  62. package/lib/features/canvas/generatorReferences.js.map +1 -0
  63. package/lib/features/canvas/homeWork.js +74 -0
  64. package/lib/features/canvas/homeWork.js.map +1 -0
  65. package/lib/features/canvas/linksRpc.js +130 -0
  66. package/lib/features/canvas/linksRpc.js.map +1 -0
  67. package/lib/features/canvas/mediaRecheck.js +176 -0
  68. package/lib/features/canvas/mediaRecheck.js.map +1 -0
  69. package/lib/features/canvas/mediaUrls.js +258 -0
  70. package/lib/features/canvas/mediaUrls.js.map +1 -0
  71. package/lib/features/canvas/nativeViewerRegistry.js.map +1 -1
  72. package/lib/features/canvas/promoProjectImport.js +80 -13
  73. package/lib/features/canvas/promoProjectImport.js.map +1 -1
  74. package/lib/features/canvas/promoVideo.js +106 -15
  75. package/lib/features/canvas/promoVideo.js.map +1 -1
  76. package/lib/features/canvas/reframe.js +228 -0
  77. package/lib/features/canvas/reframe.js.map +1 -0
  78. package/lib/features/canvas/serverTasks.js +697 -0
  79. package/lib/features/canvas/serverTasks.js.map +1 -0
  80. package/lib/features/canvas/set/SetViewportWebView.js +207 -28
  81. package/lib/features/canvas/set/SetViewportWebView.js.map +1 -1
  82. package/lib/features/canvas/set/agent/prompt.js +66 -0
  83. package/lib/features/canvas/set/agent/prompt.js.map +1 -0
  84. package/lib/features/canvas/set/agent/setOps.js +203 -0
  85. package/lib/features/canvas/set/agent/setOps.js.map +1 -0
  86. package/lib/features/canvas/set/agent/setTurn.js +128 -0
  87. package/lib/features/canvas/set/agent/setTurn.js.map +1 -0
  88. package/lib/features/canvas/set/agent/snapshot.js +43 -0
  89. package/lib/features/canvas/set/agent/snapshot.js.map +1 -0
  90. package/lib/features/canvas/set/agent/tools.js +580 -0
  91. package/lib/features/canvas/set/agent/tools.js.map +1 -0
  92. package/lib/features/canvas/set/setProject.js +43 -4
  93. package/lib/features/canvas/set/setProject.js.map +1 -1
  94. package/lib/features/canvas/set/supplyLibrary.js +397 -0
  95. package/lib/features/canvas/set/supplyLibrary.js.map +1 -0
  96. package/lib/features/canvas/storageLibrary.js +113 -52
  97. package/lib/features/canvas/storageLibrary.js.map +1 -1
  98. package/lib/features/canvas/studioCatalog.js +15 -2
  99. package/lib/features/canvas/studioCatalog.js.map +1 -1
  100. package/lib/features/canvas/studioLooks.js +1 -8
  101. package/lib/features/canvas/studioLooks.js.map +1 -1
  102. package/lib/features/canvas/useBoardMediaRefresh.js +66 -0
  103. package/lib/features/canvas/useBoardMediaRefresh.js.map +1 -0
  104. package/lib/features/canvas/useMediaSource.js +84 -0
  105. package/lib/features/canvas/useMediaSource.js.map +1 -0
  106. package/lib/features/canvas/video3d.js +11 -10
  107. package/lib/features/canvas/video3d.js.map +1 -1
  108. package/lib/features/canvas/videoEditor/BlurBoxOverlay.js +46 -0
  109. package/lib/features/canvas/videoEditor/BlurBoxOverlay.js.map +1 -0
  110. package/lib/features/canvas/videoEditor/ExportTaskCard.js +134 -0
  111. package/lib/features/canvas/videoEditor/ExportTaskCard.js.map +1 -0
  112. package/lib/features/canvas/videoEditor/agent/AgentCutPane.js +45 -7
  113. package/lib/features/canvas/videoEditor/agent/AgentCutPane.js.map +1 -1
  114. package/lib/features/canvas/videoEditor/agent/agentLoop.js +4 -2
  115. package/lib/features/canvas/videoEditor/agent/agentLoop.js.map +1 -1
  116. package/lib/features/canvas/videoEditor/agent/attachments.js +304 -0
  117. package/lib/features/canvas/videoEditor/agent/attachments.js.map +1 -0
  118. package/lib/features/canvas/videoEditor/agent/brainClient.js +3 -2
  119. package/lib/features/canvas/videoEditor/agent/brainClient.js.map +1 -1
  120. package/lib/features/canvas/videoEditor/agent/cutTools.js +207 -7
  121. package/lib/features/canvas/videoEditor/agent/cutTools.js.map +1 -1
  122. package/lib/features/canvas/videoEditor/blurBox.js +34 -0
  123. package/lib/features/canvas/videoEditor/blurBox.js.map +1 -0
  124. package/lib/features/canvas/videoEditor/compileTimeline.js +668 -0
  125. package/lib/features/canvas/videoEditor/compileTimeline.js.map +1 -0
  126. package/lib/features/canvas/videoEditor/editorModel.js +56 -22
  127. package/lib/features/canvas/videoEditor/editorModel.js.map +1 -1
  128. package/lib/features/canvas/videoEditor/exportPipeline.js +77 -0
  129. package/lib/features/canvas/videoEditor/exportPipeline.js.map +1 -0
  130. package/lib/features/canvas/videoEditor/exportRenderer.js +19 -12
  131. package/lib/features/canvas/videoEditor/exportRenderer.js.map +1 -1
  132. package/lib/features/canvas/videoEditor/exportTask.js +216 -0
  133. package/lib/features/canvas/videoEditor/exportTask.js.map +1 -0
  134. package/lib/features/canvas/videoEditor/formWidgets.js +142 -0
  135. package/lib/features/canvas/videoEditor/formWidgets.js.map +1 -0
  136. package/lib/features/canvas/videoEditor/produce/ProduceVideoSheet.js +195 -0
  137. package/lib/features/canvas/videoEditor/produce/ProduceVideoSheet.js.map +1 -0
  138. package/lib/features/canvas/videoEditor/produce/produceScenes.js +158 -0
  139. package/lib/features/canvas/videoEditor/produce/produceScenes.js.map +1 -0
  140. package/lib/features/canvas/videoEditor/remoteMediaClient.js +17 -5
  141. package/lib/features/canvas/videoEditor/remoteMediaClient.js.map +1 -1
  142. package/lib/features/canvas/videoEditor/renderTimeline.js +207 -0
  143. package/lib/features/canvas/videoEditor/renderTimeline.js.map +1 -0
  144. package/lib/features/canvas/videoEditor/renewLinks.js +64 -0
  145. package/lib/features/canvas/videoEditor/renewLinks.js.map +1 -0
  146. package/lib/features/canvas/videoEditor/sceneLayers.js +101 -0
  147. package/lib/features/canvas/videoEditor/sceneLayers.js.map +1 -0
  148. package/lib/features/canvas/videoEditor/tools/ToolsDrawer.js +283 -0
  149. package/lib/features/canvas/videoEditor/tools/ToolsDrawer.js.map +1 -0
  150. package/lib/features/canvas/videoEditor/tools/catalog.js +576 -0
  151. package/lib/features/canvas/videoEditor/tools/catalog.js.map +1 -0
  152. package/lib/features/canvas/videoEditor/videoProjectsStore.js +27 -3
  153. package/lib/features/canvas/videoEditor/videoProjectsStore.js.map +1 -1
  154. package/lib/features/webbuilder/WebBuilderExperience.js +29 -1
  155. package/lib/features/webbuilder/WebBuilderExperience.js.map +1 -1
  156. package/lib/features/webbuilder/buildFragments.js +8 -4
  157. package/lib/features/webbuilder/buildFragments.js.map +1 -1
  158. package/lib/features/webbuilder/codezenHandoff.js +108 -0
  159. package/lib/features/webbuilder/codezenHandoff.js.map +1 -0
  160. package/lib/features/webbuilder/workflow.js.map +1 -1
  161. package/lib/hooks/useChatApi.js +1 -2
  162. package/lib/hooks/useChatApi.js.map +1 -1
  163. package/lib/screens/CanvasBoard/index.js +12 -1
  164. package/lib/screens/CanvasBoard/index.js.map +1 -1
  165. package/lib/screens/Home/HomeScreen.js.map +1 -1
  166. package/lib/screens/Home/components/HomeSuggestions.js +3 -3
  167. package/lib/screens/Home/components/HomeSuggestions.js.map +1 -1
  168. package/lib/screens/WebBuilder/index.js +4 -2
  169. package/lib/screens/WebBuilder/index.js.map +1 -1
  170. package/lib/screens/WebBuilderNative/index.js +29 -2
  171. package/lib/screens/WebBuilderNative/index.js.map +1 -1
  172. package/lib/screens/WebBuilderNative/useWebBuilderHost.js +30 -6
  173. package/lib/screens/WebBuilderNative/useWebBuilderHost.js.map +1 -1
  174. package/package.json +4 -4
  175. /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
- }) => __spreadValues({
329
- type,
330
- src,
331
- durationSec,
332
- trimStartSec,
333
- trimEndSec,
334
- speed,
335
- speedCurve,
336
- filter,
337
- kenBurns,
338
- transitionIn,
339
- volume,
340
- muted
341
- }, fillColor ? {
342
- fillColor
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":"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"}
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 run = async (action, params, label) => resultUrl(await runAction(VIDEO, action, params), label);
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