@pixerate/editor 0.115.0 → 0.116.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 (117) hide show
  1. package/THIRD_PARTY_NOTICES.md +3 -0
  2. package/dist/animation-editor/index.cjs +54 -54
  3. package/dist/animation-editor/index.d.cts +2 -2
  4. package/dist/animation-editor/index.d.ts +2 -2
  5. package/dist/animation-editor/index.js +2 -2
  6. package/dist/{chunk-DFQEX3AM.cjs → chunk-2UT4GXYA.cjs} +133 -8
  7. package/dist/chunk-2UT4GXYA.cjs.map +1 -0
  8. package/dist/{chunk-VXR7XWMF.js → chunk-7LNZAWSJ.js} +437 -41
  9. package/dist/chunk-7LNZAWSJ.js.map +1 -0
  10. package/dist/{chunk-LKCYANMW.js → chunk-ARQ7PQ6Q.js} +129 -4
  11. package/dist/chunk-ARQ7PQ6Q.js.map +1 -0
  12. package/dist/chunk-COAMRKVI.cjs +159 -0
  13. package/dist/chunk-COAMRKVI.cjs.map +1 -0
  14. package/dist/{chunk-C6C5PDKU.js → chunk-D53KSJUV.js} +3 -322
  15. package/dist/chunk-D53KSJUV.js.map +1 -0
  16. package/dist/chunk-D53VQGEJ.js +3262 -0
  17. package/dist/chunk-D53VQGEJ.js.map +1 -0
  18. package/dist/chunk-EJVDBITD.cjs +501 -0
  19. package/dist/chunk-EJVDBITD.cjs.map +1 -0
  20. package/dist/{chunk-LPLCWZTM.cjs → chunk-FODKPD44.cjs} +555 -159
  21. package/dist/chunk-FODKPD44.cjs.map +1 -0
  22. package/dist/chunk-HOCPSFGA.cjs +3262 -0
  23. package/dist/chunk-HOCPSFGA.cjs.map +1 -0
  24. package/dist/chunk-IPFRWILU.js +1908 -0
  25. package/dist/chunk-IPFRWILU.js.map +1 -0
  26. package/dist/{chunk-FV5AXTSF.cjs → chunk-JSSBHMMU.cjs} +36 -188
  27. package/dist/chunk-JSSBHMMU.cjs.map +1 -0
  28. package/dist/chunk-LF4WOZXZ.js +159 -0
  29. package/dist/chunk-LF4WOZXZ.js.map +1 -0
  30. package/dist/{chunk-26PGXHY7.cjs → chunk-M7O4BJRH.cjs} +36 -36
  31. package/dist/{chunk-26PGXHY7.cjs.map → chunk-M7O4BJRH.cjs.map} +1 -1
  32. package/dist/chunk-N3467VD6.js +501 -0
  33. package/dist/chunk-N3467VD6.js.map +1 -0
  34. package/dist/{chunk-ST7E3NEE.cjs → chunk-PAOWHJ5O.cjs} +18 -337
  35. package/dist/chunk-PAOWHJ5O.cjs.map +1 -0
  36. package/dist/{chunk-XICA4PVO.js → chunk-SEBYNBHW.js} +10 -10
  37. package/dist/chunk-SMJGE7HM.cjs +1908 -0
  38. package/dist/chunk-SMJGE7HM.cjs.map +1 -0
  39. package/dist/{chunk-MMVHBKMM.js → chunk-T2P5TIZ6.js} +2 -2
  40. package/dist/{chunk-FGW5OWJ4.js → chunk-VJUML33I.js} +4 -156
  41. package/dist/chunk-VJUML33I.js.map +1 -0
  42. package/dist/{chunk-I7FQBWMQ.cjs → chunk-ZYZGEILO.cjs} +239 -239
  43. package/dist/{chunk-I7FQBWMQ.cjs.map → chunk-ZYZGEILO.cjs.map} +1 -1
  44. package/dist/export/index.cjs +4 -2
  45. package/dist/export/index.cjs.map +1 -1
  46. package/dist/export/index.js +5 -3
  47. package/dist/{export-BJE8T0YA.d.cts → export-BXxSGBCq.d.cts} +2 -2
  48. package/dist/{export-Con3UKkm.d.ts → export-Dm44YUvS.d.ts} +2 -2
  49. package/dist/export-Dv0-ZVrV.d.cts +501 -0
  50. package/dist/export-Dv0-ZVrV.d.ts +501 -0
  51. package/dist/{retouch-Do6tBs2H.d.ts → flow-BMtHAmg4.d.ts} +561 -2
  52. package/dist/{retouch-Bxkuc0KH.d.cts → flow-COCB42TP.d.cts} +561 -2
  53. package/dist/image-editor/index.cjs +957 -795
  54. package/dist/image-editor/index.cjs.map +1 -1
  55. package/dist/image-editor/index.d.cts +6 -6
  56. package/dist/image-editor/index.d.ts +6 -6
  57. package/dist/image-editor/index.js +180 -18
  58. package/dist/image-editor/index.js.map +1 -1
  59. package/dist/index.cjs +4 -2
  60. package/dist/index.cjs.map +1 -1
  61. package/dist/index.js +5 -3
  62. package/dist/index.js.map +1 -1
  63. package/dist/kernel-wasm-WYCGNZR4.js +10 -0
  64. package/dist/kernel-wasm-WYCGNZR4.js.map +1 -0
  65. package/dist/kernel-wasm-YPVAEMVN.cjs +10 -0
  66. package/dist/kernel-wasm-YPVAEMVN.cjs.map +1 -0
  67. package/dist/paint/index.cjs +165 -3
  68. package/dist/paint/index.cjs.map +1 -1
  69. package/dist/paint/index.d.cts +225 -3
  70. package/dist/paint/index.d.ts +225 -3
  71. package/dist/paint/index.js +166 -4
  72. package/dist/paint-editor/index.cjs +4690 -845
  73. package/dist/paint-editor/index.cjs.map +1 -1
  74. package/dist/paint-editor/index.d.cts +1525 -277
  75. package/dist/paint-editor/index.d.ts +1525 -277
  76. package/dist/paint-editor/index.js +4560 -715
  77. package/dist/paint-editor/index.js.map +1 -1
  78. package/dist/raster/index.cjs +4 -3
  79. package/dist/raster/index.cjs.map +1 -1
  80. package/dist/raster/index.js +10 -9
  81. package/dist/{svg-BnRj0q8i.d.cts → svg-CVdFc80-.d.cts} +2 -2
  82. package/dist/{svg-CmmBFfGT.d.ts → svg-DlEuhwoX.d.ts} +2 -2
  83. package/dist/{types-1SUQKDAw.d.ts → types-CDLGhAZp.d.ts} +40 -2
  84. package/dist/{types-yINF17Ta.d.cts → types-Tfly4Aya.d.cts} +40 -2
  85. package/dist/vector/index.cjs +1897 -975
  86. package/dist/vector/index.cjs.map +1 -1
  87. package/dist/vector/index.d.cts +292 -32
  88. package/dist/vector/index.d.ts +292 -32
  89. package/dist/vector/index.js +928 -6
  90. package/dist/vector/index.js.map +1 -1
  91. package/dist/video-editor/index.cjs +502 -2165
  92. package/dist/video-editor/index.cjs.map +1 -1
  93. package/dist/video-editor/index.d.cts +3 -501
  94. package/dist/video-editor/index.d.ts +3 -501
  95. package/dist/video-editor/index.js +151 -1814
  96. package/dist/video-editor/index.js.map +1 -1
  97. package/package.json +1 -1
  98. package/skills/pixerate-image-editor/references/photoshop-files.md +7 -3
  99. package/skills/pixerate-vector/SKILL.md +3 -0
  100. package/dist/chunk-C6C5PDKU.js.map +0 -1
  101. package/dist/chunk-DFQEX3AM.cjs.map +0 -1
  102. package/dist/chunk-FGW5OWJ4.js.map +0 -1
  103. package/dist/chunk-FV5AXTSF.cjs.map +0 -1
  104. package/dist/chunk-GX332W2C.js +0 -181
  105. package/dist/chunk-GX332W2C.js.map +0 -1
  106. package/dist/chunk-LKCYANMW.js.map +0 -1
  107. package/dist/chunk-LPLCWZTM.cjs.map +0 -1
  108. package/dist/chunk-MUUXNRU4.cjs +0 -181
  109. package/dist/chunk-MUUXNRU4.cjs.map +0 -1
  110. package/dist/chunk-ST7E3NEE.cjs.map +0 -1
  111. package/dist/chunk-TCKIXI46.cjs +0 -1136
  112. package/dist/chunk-TCKIXI46.cjs.map +0 -1
  113. package/dist/chunk-UBIXVXPR.js +0 -1136
  114. package/dist/chunk-UBIXVXPR.js.map +0 -1
  115. package/dist/chunk-VXR7XWMF.js.map +0 -1
  116. /package/dist/{chunk-XICA4PVO.js.map → chunk-SEBYNBHW.js.map} +0 -0
  117. /package/dist/{chunk-MMVHBKMM.js.map → chunk-T2P5TIZ6.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/video-editor/types.ts","../src/video-editor/keyframes.ts","../src/video-editor/lut.ts","../src/video-editor/grade.ts","../src/video-editor/remap.ts","../src/video-editor/timeline.ts","../src/video-editor/clip-animation.ts","../src/video-editor/evaluate.ts","../src/video-editor/render.ts","../src/video-editor/export.ts"],"sourcesContent":["/**\n * A video project is plain JSON: the media it uses (assets), tracks of clips placed on a timeline,\n * and markers. Every time is in milliseconds; `fps` sets the frame grid edits snap to and exports use.\n *\n * Tracks are listed top to bottom as a timeline shows them: on screen, a clip on an earlier video\n * track draws over one on a later track. Clips on one track never overlap.\n */\n\nimport type { VideoAnimatable, VideoKeyframes } from './keyframes.js';\n\nexport type VideoAssetKind = 'video' | 'audio' | 'image';\n\n/** A spoken word in an asset's transcript, timed in the source (ms). */\nexport interface VideoTranscriptWord {\n\tword: string;\n\tstart: number;\n\tend: number;\n}\n\n/** A smaller copy of an asset's media for the preview (see `VideoAsset.proxies`). */\nexport interface VideoAssetProxy {\n\t/** Its size as a fraction of the original (0.5 = half width and height). */\n\tscale: number;\n\t/** What the preview loads instead of the original. */\n\tsrc: string;\n\twidth?: number;\n\theight?: number;\n}\n\n/** A piece of source media. The project refers to it by id; `src` is whatever the host can load. */\nexport interface VideoAsset {\n\tid: string;\n\tkind: VideoAssetKind;\n\t/** URL, blob URL, path or data URL (whatever the playback engine and exporter can open). */\n\tsrc: string;\n\tname?: string;\n\t/** Length of the source (ms). Required for video and audio; images have none. */\n\tduration?: number;\n\t/** Intrinsic size in pixels (video and image). Placement assumes the project size when missing. */\n\twidth?: number;\n\theight?: number;\n\t/** Whether a video asset has sound (default true). */\n\thasAudio?: boolean;\n\t/** A still to show for a video where its frames cannot be drawn (SVG renders, thumbnails). */\n\tposter?: string;\n\t/** What is said in it, word by word, timed in the source (see `parseVideoTranscript`). */\n\ttranscript?: VideoTranscriptWord[];\n\t/**\n\t * Smaller copies of a video for smooth editing (see `videoProxyFfmpeg`). The preview plays the\n\t * one its preview scale picks; exports and EDLs always use `src`. A proxy must have the same\n\t * length and timing as the original.\n\t */\n\tproxies?: VideoAssetProxy[];\n}\n\nexport type VideoTrackKind = 'video' | 'audio';\n\nexport interface VideoTrack {\n\tid: string;\n\tkind: VideoTrackKind;\n\tname?: string;\n\t/** Silences every clip on the track. */\n\tmuted?: boolean;\n\t/** Leaves the track's pictures out of the frame. */\n\thidden?: boolean;\n\t/** Refuses edits to the track's clips. */\n\tlocked?: boolean;\n\t/**\n\t * Moves with ripple edits made on other sync-locked tracks, so it stays in sync (default true).\n\t * Turn it off for a track that should stay put while the others ripple (e.g. a music bed).\n\t */\n\tsyncLocked?: boolean;\n\t/** Gain applied to every clip on the track (1 = unchanged, default 1). */\n\tvolume?: number;\n\tclips: VideoClip[];\n}\n\n/** Where a picture sits in the frame, after it has been fitted. Each field may be keyframed. */\nexport interface VideoTransform {\n\t/** Offset of the centre from the frame's centre, in pixels (default 0). */\n\tx?: VideoAnimatable;\n\ty?: VideoAnimatable;\n\t/** 1 = fitted size (default 1). */\n\tscale?: VideoAnimatable;\n\t/** Degrees clockwise (default 0). */\n\trotation?: VideoAnimatable;\n}\n\n/** How a picture is fitted to the frame before its transform: like CSS `object-fit`. */\nexport type VideoFit = 'contain' | 'cover' | 'fill' | 'none';\nexport const VIDEO_FITS = ['contain', 'cover', 'fill', 'none'] as const;\n\n/**\n * - `crossfade`: this clip fades up over the one before.\n * - `dip`: down into a colour and up out of it.\n * - `wipe`: an edge travels across, revealing this clip.\n * - `push`: this clip slides in, pushing the one before out.\n * - `slide`: this clip slides in over the one before, which stays put.\n * - `iris`: a circle opens from the centre, revealing this clip.\n */\nexport type VideoTransitionType = 'crossfade' | 'dip' | 'wipe' | 'push' | 'slide' | 'iris';\nexport const VIDEO_TRANSITION_TYPES = ['crossfade', 'dip', 'wipe', 'push', 'slide', 'iris'] as const;\nexport type VideoWipeDirection = 'left' | 'right' | 'up' | 'down';\nexport const VIDEO_WIPE_DIRECTIONS = ['left', 'right', 'up', 'down'] as const;\n\n/**\n * A transition into a clip from the clip that ends where it starts on the same track. It plays over\n * the cut, half before and half after, so both clips run past the cut into their handles (media\n * beyond the out point of the one before, before the in point of this one).\n */\nexport interface VideoTransition {\n\ttype: VideoTransitionType;\n\t/** Length (ms), centred on the cut. */\n\tduration: number;\n\t/** For dip: the colour passed through (default black). */\n\tcolor?: string;\n\t/** For wipe, push and slide: the way the edge or picture travels (default right: in from the left). */\n\tdirection?: VideoWipeDirection;\n\t/**\n\t * Shape of the sound's fades through the transition (see `VideoFadeCurve`). Default\n\t * `equal-power` for crossfades and wipes, where two sounds overlap and a linear mix dips in\n\t * loudness halfway; `linear` for dips, where one sound fades out before the other fades in.\n\t */\n\taudioCurve?: VideoFadeCurve;\n}\n\n/** The curve a transition's sound fades follow (its `audioCurve`, else the default for its type). */\nexport const videoTransitionAudioCurve = (t: VideoTransition): VideoFadeCurve => t.audioCurve ?? (t.type === 'dip' ? 'linear' : 'equal-power');\n\n/**\n * How a clip's picture mixes with what is beneath it, as in CSS `mix-blend-mode` (`add` sums the\n * colours, `plus-lighter` in CSS). These are the modes the canvas preview, SVG frames and ffmpeg's\n * `blend` filter all share.\n */\nexport type VideoBlendMode = 'normal' | 'multiply' | 'screen' | 'overlay' | 'darken' | 'lighten' | 'color-dodge' | 'color-burn' | 'hard-light' | 'soft-light' | 'difference' | 'exclusion' | 'add';\nexport const VIDEO_BLEND_MODES = ['normal', 'multiply', 'screen', 'overlay', 'darken', 'lighten', 'color-dodge', 'color-burn', 'hard-light', 'soft-light', 'difference', 'exclusion', 'add'] as const;\n\n/** A 3D LUT a grade applies after its other steps (see `VideoGrade.lut`). */\nexport interface VideoGradeLut {\n\t/** A `.cube` file: whatever the host can load (URL, path) and the exporter can open. */\n\tsrc: string;\n\t/** How much of the LUT's change to apply, 0–1 (default 1). */\n\tstrength?: number;\n\t/** A label for the look (default the file's TITLE or name). */\n\tname?: string;\n}\n\n/**\n * Colour correction for a clip's picture (see `VIDEO_GRADE_CONTROLS` for ranges). Applied in a fixed\n * order: exposure, contrast, saturation, hue, white balance (temperature and tint), then the LUT.\n */\nexport interface VideoGrade {\n\t/** Stops: +1 doubles every channel (default 0). */\n\texposure?: number;\n\t/** -1 (flat grey) to 1 (twice as steep), around mid grey (default 0). */\n\tcontrast?: number;\n\t/** -1 (black and white) to 1 (twice as saturated); default 0. */\n\tsaturation?: number;\n\t/** Hue rotation in degrees (default 0). */\n\thue?: number;\n\t/** -1 (cool) to 1 (warm); default 0. */\n\ttemperature?: number;\n\t/** -1 (green) to 1 (magenta); default 0. */\n\ttint?: number;\n\t/** A 3D LUT (a `.cube` file) applied last, mixed in at its `strength`. */\n\tlut?: VideoGradeLut;\n}\n\n/**\n * How a clip enters or leaves: `fade`; `rise` (up into place) or `drop` (down into place);\n * `slide-left` / `slide-right` (in moving that way); `zoom` (grows into place); `pop` (grows past its\n * size and settles). Each also fades. An exit plays the same movement backwards.\n */\nexport type VideoClipAnimationEffect = 'fade' | 'rise' | 'drop' | 'slide-left' | 'slide-right' | 'zoom' | 'pop';\nexport const VIDEO_CLIP_ANIMATION_EFFECTS = ['fade', 'rise', 'drop', 'slide-left', 'slide-right', 'zoom', 'pop'] as const;\n\n/** An entrance or exit animation (see `VideoClipAnimationEffect`). */\nexport interface VideoClipAnimation {\n\teffect: VideoClipAnimationEffect;\n\t/** Length (ms, default 500). */\n\tduration?: number;\n}\n\ninterface VideoClipBase {\n\tid: string;\n\tname?: string;\n\t/** Where it starts on the timeline (ms). */\n\tstart: number;\n\t/** How long it lasts on the timeline (ms). */\n\tduration: number;\n\t/** 0–1 (default 1), or keyframes (`{ keys: [{ t, v, ease }] }`, `t` in ms from the clip's start). */\n\topacity?: VideoAnimatable;\n\ttransform?: VideoTransform;\n\t/** Default contain. */\n\tfit?: VideoFit;\n\t/** How the picture mixes with what is beneath it (default normal). */\n\tblend?: VideoBlendMode;\n\t/** Colour correction of the picture. */\n\tgrade?: VideoGrade;\n\t/** How the picture enters, from the clip's start (on top of any fade in). */\n\tanimateIn?: VideoClipAnimation;\n\t/** How the picture leaves, up to the clip's end. */\n\tanimateOut?: VideoClipAnimation;\n\t/** Fade in from nothing over this long (ms), pictures and sound. */\n\tfadeIn?: number;\n\t/** Fade out over this long (ms). */\n\tfadeOut?: number;\n\t/** Transition from the clip before (see `VideoTransition`). */\n\ttransition?: VideoTransition;\n}\n\n/**\n * The shape of a sound fade, the same curves ffmpeg's `afade` draws, so previews and exports agree.\n * With `x` running 0→1 through a fade in (1→0 through a fade out), the gain is:\n * - `linear`: x (ffmpeg `tri`). Dips in loudness in the middle of a crossfade.\n * - `equal-power`: sin(x·π/2) (`qsin`). Keeps loudness steady; the usual choice for crossfades.\n * - `s-curve`: (1 − cos(x·π))/2 (`hsin`). Gentle at both ends.\n * - `exponential`: x³ (`cub`). Slow start; a natural-sounding fade in from silence.\n * - `logarithmic`: 1 − (1 − x)² (`ipar`). Fast start, slow finish.\n */\nexport type VideoFadeCurve = 'linear' | 'equal-power' | 's-curve' | 'exponential' | 'logarithmic';\nexport const VIDEO_FADE_CURVES = ['linear', 'equal-power', 's-curve', 'exponential', 'logarithmic'] as const;\n\n/** A stretch of an asset. */\nexport interface VideoMediaClip extends VideoClipBase {\n\ttype: 'media';\n\tasset: string;\n\t/** Where in the source it starts (ms, default 0). */\n\tin?: number;\n\t/** Playback speed (default 1): it uses `duration × speed` of the source. */\n\tspeed?: number;\n\t/**\n\t * A speed ramp: keys mapping clip time to source time after the in point (`v` ms from `in`), so\n\t * a key's slope is the speed there, a flat stretch is a freeze frame and eased keys ramp between\n\t * speeds. Never runs backwards. Before the first key and after the last the picture holds. Takes\n\t * the place of `speed` (see `videoSpeedRampKeys` for building one from speeds).\n\t */\n\ttimeRemap?: VideoKeyframes;\n\t/** Gain (1 = unchanged, default 1), or keyframes. */\n\tvolume?: VideoAnimatable;\n\t/** Silences this clip. */\n\tmuted?: boolean;\n\t/** Shape of the sound's fade in (default linear). The picture always fades linearly. */\n\tfadeInCurve?: VideoFadeCurve;\n\t/** Shape of the sound's fade out (default linear). */\n\tfadeOutCurve?: VideoFadeCurve;\n}\n\n/** A title. */\nexport interface VideoTextClip extends VideoClipBase {\n\ttype: 'text';\n\ttext: string;\n\t/** CSS colour (default white). */\n\tcolor?: string;\n\t/** Pixels (default 64). */\n\tfontSize?: number;\n\t/** Default sans-serif. */\n\tfontFamily?: string;\n\t/** Default 700. */\n\tfontWeight?: number;\n\t/** Box behind the text (CSS colour); none by default. */\n\tbackground?: string;\n}\n\n/** A solid colour filling the frame. */\nexport interface VideoColorClip extends VideoClipBase {\n\ttype: 'color';\n\tcolor: string;\n}\n\n/**\n * A compound clip: a nested sequence (see `VideoProject.sequences`) played as one picture and one\n * sound. It plays the sequence's own time from `in`, at normal speed. Its opacity, transform, blend,\n * grade, fades, transitions and animations apply to the sequence's composite, not to each of its\n * clips; its volume and fades apply to the sequence's mixed sound.\n */\nexport interface VideoSequenceClip extends VideoClipBase {\n\ttype: 'sequence';\n\t/** The id of the sequence it plays (in `project.sequences`). */\n\tsequence: string;\n\t/** Where in the sequence's time it starts (ms, default 0). */\n\tin?: number;\n\t/** Gain on the sequence's sound (1 = unchanged, default 1), or keyframes. */\n\tvolume?: VideoAnimatable;\n\t/** Silences the sequence's sound. */\n\tmuted?: boolean;\n\t/** Shape of the sound's fade in (default linear). */\n\tfadeInCurve?: VideoFadeCurve;\n\t/** Shape of the sound's fade out (default linear). */\n\tfadeOutCurve?: VideoFadeCurve;\n}\n\nexport type VideoClip = VideoMediaClip | VideoTextClip | VideoColorClip | VideoSequenceClip;\nexport type VideoClipType = VideoClip['type'];\n\n/**\n * How a clip is placed where others already are: `refuse` an overlap (the default), `overwrite`\n * what is underneath (cutting, trimming or removing it), or `insert` (cut everything across the\n * point and push later material along on every sync-locked track).\n */\nexport type VideoPlacementMode = 'refuse' | 'overwrite' | 'insert';\nexport const VIDEO_PLACEMENT_MODES = ['refuse', 'overwrite', 'insert'] as const;\nexport const VIDEO_CLIP_TYPES = ['media', 'text', 'color', 'sequence'] as const;\n\nexport interface VideoMarker {\n\tid: string;\n\ttime: number;\n\tlabel?: string;\n\t/** CSS colour. */\n\tcolor?: string;\n}\n\n/**\n * A nested sequence: tracks of clips with their own timeline from 0, played inside the project by\n * compound clips (`type: 'sequence'`). Its frame is the project's frame size, transparent where no\n * clip covers it. A sequence may hold compound clips of other sequences, but never itself (directly\n * or through others).\n */\nexport interface VideoSequence {\n\tid: string;\n\tname?: string;\n\ttracks: VideoTrack[];\n}\n\nexport interface VideoProject {\n\tversion: 1;\n\tname?: string;\n\t/** Frame size in pixels. */\n\twidth: number;\n\theight: number;\n\t/** Frames per second: the grid edits snap to and exports use. */\n\tfps: number;\n\t/** What shows where no clip covers the frame (default black). */\n\tbackground?: string;\n\tassets: VideoAsset[];\n\ttracks: VideoTrack[];\n\t/** Nested sequences that compound clips play (see `VideoSequence`). */\n\tsequences?: VideoSequence[];\n\tmarkers?: VideoMarker[];\n}\n","/**\n * Keyframes for a clip's opacity, volume and transform. A property is either a plain number or\n * `{ keys }`: values at clip-relative times (ms from the clip's start), each with the easing of the\n * segment that leaves it. Pure functions only, so previews, renders and exports agree.\n *\n * Easing is stored as CSS `cubic-bezier(x1, y1, x2, y2)` control points (named easings are the CSS\n * ones), which is also what After Effects / Lottie speed-and-influence handles convert to exactly.\n */\n\n/** How a segment moves from its key to the next: a named curve, `hold` (jump at the next key) or CSS cubic-bezier points. */\nexport type VideoEase = 'linear' | 'hold' | 'ease-in' | 'ease-out' | 'ease-in-out' | [number, number, number, number];\nexport const VIDEO_EASE_NAMES = ['linear', 'hold', 'ease-in', 'ease-out', 'ease-in-out'] as const;\n\nexport interface VideoKey {\n\t/** Clip-relative time (ms from the clip's start). */\n\tt: number;\n\tv: number;\n\t/** The segment from this key to the next (default linear). Ignored on the last key. */\n\tease?: VideoEase;\n}\n\nexport interface VideoKeyframes {\n\t/** In time order, at least one. */\n\tkeys: VideoKey[];\n}\n\n/** A number, or keyframes for it. */\nexport type VideoAnimatable = number | VideoKeyframes;\n\n/** The clip properties that can be keyframed: `opacity`, `volume` (media) and the transform's fields. */\nexport type VideoKeyframeProperty = 'opacity' | 'volume' | 'x' | 'y' | 'scale' | 'rotation';\nexport const VIDEO_KEYFRAME_PROPERTIES = ['opacity', 'volume', 'x', 'y', 'scale', 'rotation'] as const;\nexport const VIDEO_TRANSFORM_PROPERTIES = ['x', 'y', 'scale', 'rotation'] as const;\n\n/** Each property's default and allowed range. */\nexport const VIDEO_KEYFRAME_LIMITS: Record<VideoKeyframeProperty, { default: number; min?: number; max?: number }> = {\n\topacity: { default: 1, min: 0, max: 1 },\n\tvolume: { default: 1, min: 0, max: 4 },\n\tx: { default: 0 },\n\ty: { default: 0 },\n\tscale: { default: 1, min: 0 },\n\trotation: { default: 0 }\n};\n\nconst NAMED: Record<'ease-in' | 'ease-out' | 'ease-in-out', [number, number, number, number]> = {\n\t'ease-in': [0.42, 0, 1, 1],\n\t'ease-out': [0, 0, 0.58, 1],\n\t'ease-in-out': [0.42, 0, 0.58, 1]\n};\n\nexport const isVideoKeyframes = (v: unknown): v is VideoKeyframes => typeof v === 'object' && v !== null && Array.isArray((v as VideoKeyframes).keys);\n\n/** The cubic-bezier points for an ease (`null` for linear and hold). */\nexport function videoEaseBezier(ease: VideoEase | undefined): [number, number, number, number] | null {\n\tif (ease === undefined || ease === 'linear' || ease === 'hold') return null;\n\treturn Array.isArray(ease) ? ease : NAMED[ease];\n}\n\nconst bez = (a: number, b: number, s: number) => 3 * a * (1 - s) * (1 - s) * s + 3 * b * (1 - s) * s * s + s * s * s;\nconst bezSlope = (a: number, b: number, s: number) => 3 * a * (1 - s) * (1 - s) + 6 * (b - a) * (1 - s) * s + 3 * (1 - b) * s * s;\n\n/** The curve parameter where a cubic-bezier's x is `x`: Newton's method, then bisection if that fails. */\nfunction bezierParam(x1: number, x2: number, x: number): number {\n\tlet s = x;\n\tfor (let i = 0; i < 8; i++) {\n\t\tconst err = bez(x1, x2, s) - x;\n\t\tif (Math.abs(err) < 1e-7) return s;\n\t\tconst d = bezSlope(x1, x2, s);\n\t\tif (Math.abs(d) < 1e-6) break;\n\t\ts -= err / d;\n\t\tif (s < 0 || s > 1) break;\n\t}\n\tlet lo = 0;\n\tlet hi = 1;\n\ts = x;\n\tfor (let i = 0; i < 60; i++) {\n\t\tconst v = bez(x1, x2, s);\n\t\tif (Math.abs(v - x) < 1e-9) break;\n\t\tif (v < x) lo = s;\n\t\telse hi = s;\n\t\ts = (lo + hi) / 2;\n\t}\n\treturn s;\n}\n\n/** How far (0–1 in, any y out) an ease has got at progress `p` (0–1) through its segment. */\nexport function videoEaseProgress(ease: VideoEase | undefined, p: number): number {\n\tif (p <= 0) return 0;\n\tif (p >= 1) return ease === 'hold' ? 0 : 1;\n\tif (ease === 'hold') return 0;\n\tconst b = videoEaseBezier(ease);\n\tif (!b) return p;\n\treturn bez(b[1], b[3], bezierParam(b[0], b[2], p));\n}\n\n/** The index of the last key at or before `t` (-1 before the first). */\nfunction keyBefore(keys: readonly VideoKey[], t: number): number {\n\tlet lo = 0;\n\tlet hi = keys.length - 1;\n\tif (t < keys[0].t) return -1;\n\twhile (lo < hi) {\n\t\tconst mid = (lo + hi + 1) >> 1;\n\t\tif (keys[mid].t <= t) lo = mid;\n\t\telse hi = mid - 1;\n\t}\n\treturn lo;\n}\n\n/**\n * A property's value at clip-relative time `clipTime` (ms): the number itself, or the keys\n * interpolated (held before the first and after the last). `fallback` is used when it is unset.\n */\nexport function videoValueAt(prop: VideoAnimatable | undefined, clipTime: number, fallback = 0): number {\n\tif (prop === undefined) return fallback;\n\tif (typeof prop === 'number') return prop;\n\tconst { keys } = prop;\n\tif (!keys.length) return fallback;\n\tconst i = keyBefore(keys, clipTime);\n\tif (i < 0) return keys[0].v;\n\tif (i >= keys.length - 1) return keys[keys.length - 1].v;\n\tconst a = keys[i];\n\tconst b = keys[i + 1];\n\tif (a.ease === 'hold') return a.v;\n\treturn a.v + (b.v - a.v) * videoEaseProgress(a.ease, (clipTime - a.t) / (b.t - a.t));\n}\n\n/** A property's keys (a plain number or unset gives none). */\nexport const videoKeysOf = (prop: VideoAnimatable | undefined): VideoKey[] => (isVideoKeyframes(prop) ? prop.keys : []);\n\n/** Shifts every key by `dt` ms (or scales times by `k` first); numbers pass through. */\nexport function retimeVideoAnimatable<T extends VideoAnimatable | undefined>(prop: T, dt: number, k = 1): T {\n\tif (!isVideoKeyframes(prop)) return prop;\n\treturn { keys: prop.keys.map((key) => ({ ...key, t: key.t * k + dt })) } as T;\n}\n\n/** Splits a cubic-bezier ease at progress `p`, giving the eases of the two halves (renormalised). */\nfunction splitEase(ease: VideoEase | undefined, p: number): [VideoEase | undefined, VideoEase | undefined] {\n\tif (ease === 'hold') return ['hold', 'hold'];\n\tconst b = videoEaseBezier(ease);\n\tif (!b) return [ease, ease];\n\tconst s = bezierParam(b[0], b[2], p);\n\tconst lerp = (u: [number, number], v: [number, number], k: number): [number, number] => [u[0] + (v[0] - u[0]) * k, u[1] + (v[1] - u[1]) * k];\n\tconst P0: [number, number] = [0, 0];\n\tconst P1: [number, number] = [b[0], b[1]];\n\tconst P2: [number, number] = [b[2], b[3]];\n\tconst P3: [number, number] = [1, 1];\n\tconst A = lerp(P0, P1, s);\n\tconst B = lerp(P1, P2, s);\n\tconst C = lerp(P2, P3, s);\n\tconst AB = lerp(A, B, s);\n\tconst BC = lerp(B, C, s);\n\tconst M = lerp(AB, BC, s);\n\tconst r = (v: number) => Math.round(v * 1e6) / 1e6;\n\t// Each half is rescaled to run 0–1 in both x and y; one with no rise has nothing to ease.\n\tconst left: VideoEase | undefined = Math.abs(M[1]) < 1e-9 ? 'linear' : [r(A[0] / M[0]), r(A[1] / M[1]), r(AB[0] / M[0]), r(AB[1] / M[1])];\n\tconst dx = 1 - M[0];\n\tconst dy = 1 - M[1];\n\tconst right: VideoEase | undefined = Math.abs(dy) < 1e-9 ? 'linear' : [r((BC[0] - M[0]) / dx), r((BC[1] - M[1]) / dy), r((C[0] - M[0]) / dx), r((C[1] - M[1]) / dy)];\n\treturn [left, right];\n}\n\n/**\n * Splits keyframes at clip time `at`: the keys before it (with a key added at `at`) and the keys\n * after it, moved to start at 0 (with a key added at 0). Eased segments across the cut are split\n * into two curves that trace the same path, so the two halves play exactly as the whole did.\n */\nexport function splitVideoAnimatable<T extends VideoAnimatable | undefined>(prop: T, at: number): [T, T] {\n\tif (!isVideoKeyframes(prop)) return [prop, prop];\n\tconst keys = prop.keys;\n\tconst eps = 1e-6;\n\tconst v = videoValueAt(prop, at);\n\tconst i = keyBefore(keys, at);\n\tconst exact = i >= 0 && Math.abs(keys[i].t - at) < eps;\n\tlet leftEase: VideoEase | undefined;\n\tlet rightEase: VideoEase | undefined;\n\tif (exact) rightEase = keys[i].ease;\n\telse if (i >= 0 && i < keys.length - 1) {\n\t\tconst a = keys[i];\n\t\t[leftEase, rightEase] = splitEase(a.ease, (at - a.t) / (keys[i + 1].t - a.t));\n\t}\n\tconst before = keys.slice(0, exact ? i : i + 1).map((k) => ({ ...k }));\n\tif (before.length && leftEase !== undefined) before[before.length - 1] = withEase(before[before.length - 1], leftEase);\n\tconst left: VideoKey[] = [...before, { t: at, v }];\n\tconst right: VideoKey[] = [withEase({ t: 0, v }, rightEase), ...keys.slice(i + 1).map((k) => ({ ...k, t: k.t - at }))];\n\treturn [{ keys: left } as T, { keys: right } as T];\n}\n\nconst withEase = (key: VideoKey, ease: VideoEase | undefined): VideoKey => {\n\tconst { ease: _old, ...rest } = key;\n\treturn ease === undefined || ease === 'linear' ? rest : { ...rest, ease };\n};\n\n/** The keys sorted by time, refusing two at the same time. */\nexport function sortVideoKeys(keys: readonly VideoKey[]): VideoKey[] {\n\tconst sorted = [...keys].sort((a, b) => a.t - b.t);\n\tfor (let i = 1; i < sorted.length; i++) if (Math.abs(sorted[i].t - sorted[i - 1].t) < 1e-6) throw new Error(`Two keys are at ${sorted[i].t} ms; give each key its own time.`);\n\treturn sorted;\n}\n\n/**\n * Keys with one set (or replaced) at `t`: a plain value becomes keys holding it and the new one.\n * For a keyframe toggle or \"add key at playhead\".\n */\nexport function setVideoKey(prop: VideoAnimatable | undefined, key: VideoKey, fallback: number): VideoKeyframes {\n\tconst keys = isVideoKeyframes(prop) ? prop.keys.filter((k) => Math.abs(k.t - key.t) >= 1e-6) : [];\n\tif (!isVideoKeyframes(prop)) {\n\t\tconst v = prop ?? fallback;\n\t\tif (key.t !== 0) keys.push({ t: 0, v });\n\t}\n\treturn { keys: sortVideoKeys([...keys, key]) };\n}\n\n/** Keys with the one at `t` removed; the value it then holds when none are left. */\nexport function removeVideoKey(prop: VideoKeyframes, t: number): VideoAnimatable {\n\tconst keys = prop.keys.filter((k) => Math.abs(k.t - t) >= 1e-6);\n\treturn keys.length ? { keys } : prop.keys[0].v;\n}\n\n// ---------------------------------------------------------------------------------------------\n// ffmpeg expressions\n// ---------------------------------------------------------------------------------------------\n\nconst fmt = (v: number) => {\n\tconst r = Math.round(v * 1e4) / 1e4;\n\treturn Object.is(r, -0) ? '0' : String(r);\n};\n\n/** `+n` or `-n`, so expressions never read `--n`. */\nconst signed = (v: number) => (fmt(v).startsWith('-') ? fmt(v) : `+${fmt(v)}`);\n\n/**\n * Breakpoints `[clipTime, value]` tracing a property as straight lines: linear segments as they\n * are, holds as steps, eased segments sampled every `step` ms (about two frames).\n */\nexport function videoKeyframeBreakpoints(prop: VideoKeyframes, step: number): { points: [number, number][]; holds: Set<number> } {\n\tconst { keys } = prop;\n\tconst points: [number, number][] = [];\n\tconst holds = new Set<number>();\n\tfor (let i = 0; i < keys.length; i++) {\n\t\tconst a = keys[i];\n\t\tpoints.push([a.t, a.v]);\n\t\tconst b = keys[i + 1];\n\t\tif (!b) break;\n\t\tif (a.ease === 'hold') {\n\t\t\tholds.add(points.length - 1);\n\t\t\tcontinue;\n\t\t}\n\t\tif (!videoEaseBezier(a.ease)) continue;\n\t\tconst n = Math.max(1, Math.ceil((b.t - a.t) / step));\n\t\tfor (let k = 1; k < n; k++) {\n\t\t\tconst t = a.t + ((b.t - a.t) * k) / n;\n\t\t\tpoints.push([t, videoValueAt(prop, t)]);\n\t\t}\n\t}\n\treturn { points, holds };\n}\n\n/**\n * An ffmpeg expression for a property, given `time`: an expression for the clip-relative time in\n * ms (e.g. `(t*1000-1500)`). Piecewise linear `if(lt(…))` chains; eased segments are baked to\n * breakpoints every `step` ms.\n */\nexport function videoKeyframeFfmpegExpr(prop: VideoAnimatable | undefined, time: string, fallback: number, step: number): string {\n\tif (!isVideoKeyframes(prop)) return fmt(prop ?? fallback);\n\tconst { points, holds } = videoKeyframeBreakpoints(prop, step);\n\tif (points.length === 1 || points.every(([, v]) => v === points[0][1])) return fmt(points[0][1]);\n\tlet expr = fmt(points[points.length - 1][1]);\n\tfor (let i = points.length - 2; i >= 0; i--) {\n\t\tconst [t0, v0] = points[i];\n\t\tconst [t1, v1] = points[i + 1];\n\t\tconst seg = holds.has(i) || v0 === v1 ? fmt(v0) : `${fmt(v0)}${signed((v1 - v0) / (t1 - t0))}*(${time}${signed(-t0)})`;\n\t\texpr = `if(lt(${time},${fmt(t1)}),${seg},${expr})`;\n\t}\n\treturn `if(lt(${time},${fmt(points[0][0])}),${fmt(points[0][1])},${expr})`;\n}\n","/**\n * 3D LUTs for grades: `.cube` files read into a lattice and applied with tetrahedral\n * interpolation, as ffmpeg's `lut3d=interp=tetrahedral` and grading apps apply them, so the\n * preview and the export agree. A grade's LUT (`VideoGrade.lut`) runs after its other steps and is\n * mixed with the picture before it by `strength`.\n */\n\n/** A 3D LUT: `size`³ output colours, red changing fastest, then green, then blue (the `.cube` order). */\nexport interface VideoLut {\n\ttitle?: string;\n\tsize: number;\n\t/** Input values mapped to the first and last lattice points, per channel (default 0 and 1). */\n\tdomainMin: [number, number, number];\n\tdomainMax: [number, number, number];\n\t/** `size³ × 3` output values. */\n\tdata: Float32Array;\n}\n\n/** Largest `LUT_3D_SIZE` read (129³ rows is about 2 million). */\nexport const VIDEO_LUT_MAX_SIZE = 129;\n\n/** Reads a `.cube` file's 3D table. Errors give the line and what is wrong. */\nexport function parseVideoCubeLut(text: string): VideoLut {\n\tlet size = 0;\n\tlet size1 = 0;\n\tlet title: string | undefined;\n\tconst domainMin: [number, number, number] = [0, 0, 0];\n\tconst domainMax: [number, number, number] = [1, 1, 1];\n\tlet data: Float32Array | null = null;\n\tlet rows = 0;\n\tconst lines = text.split(/\\r\\n|\\r|\\n/);\n\tconst fail = (line: number, message: string): never => {\n\t\tthrow new Error(`Line ${line + 1} of the .cube file: ${message}.`);\n\t};\n\tconst numbers = (parts: string[], line: number) =>\n\t\tparts.map((p) => {\n\t\t\tconst v = Number(p);\n\t\t\tif (!Number.isFinite(v)) fail(line, `\"${p}\" is not a number`);\n\t\t\treturn v;\n\t\t});\n\tfor (let i = 0; i < lines.length; i++) {\n\t\tconst line = lines[i].replace(/#.*/, '').trim();\n\t\tif (!line) continue;\n\t\tconst parts = line.split(/\\s+/);\n\t\tconst key = parts[0];\n\t\tif (/^[A-Za-z]/.test(key)) {\n\t\t\tif (rows) fail(i, `\"${key}\" comes after the table; keywords go before it`);\n\t\t\tif (key === 'TITLE') title = line.slice(5).trim().replace(/^\"|\"$/g, '');\n\t\t\telse if (key === 'LUT_3D_SIZE') {\n\t\t\t\tsize = Number(parts[1]);\n\t\t\t\tif (!Number.isInteger(size) || size < 2 || size > VIDEO_LUT_MAX_SIZE) fail(i, `LUT_3D_SIZE must be a whole number from 2 to ${VIDEO_LUT_MAX_SIZE}, not \"${parts[1] ?? ''}\"`);\n\t\t\t} else if (key === 'LUT_1D_SIZE') size1 = Number(parts[1]) || 1;\n\t\t\telse if (key === 'DOMAIN_MIN' || key === 'DOMAIN_MAX') {\n\t\t\t\tconst v = numbers(parts.slice(1), i);\n\t\t\t\tif (v.length !== 3) fail(i, `${key} needs 3 numbers`);\n\t\t\t\t(key === 'DOMAIN_MIN' ? domainMin : domainMax).splice(0, 3, ...v);\n\t\t\t} else if (key === 'LUT_3D_INPUT_RANGE') {\n\t\t\t\tconst v = numbers(parts.slice(1), i);\n\t\t\t\tif (v.length !== 2 || !(v[1] > v[0])) fail(i, 'LUT_3D_INPUT_RANGE needs a minimum and a larger maximum');\n\t\t\t\tdomainMin.fill(v[0]);\n\t\t\t\tdomainMax.fill(v[1]);\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (!size) fail(i, size1 ? 'this is a 1D LUT (LUT_1D_SIZE); only 3D LUTs (LUT_3D_SIZE) are supported' : 'the table starts before LUT_3D_SIZE');\n\t\tdata ??= new Float32Array(size * size * size * 3);\n\t\tconst v = numbers(parts, i);\n\t\tif (v.length !== 3) fail(i, `a table row needs 3 numbers, not ${v.length}`);\n\t\tif (rows >= size ** 3) fail(i, `the table has more than the ${size ** 3} rows LUT_3D_SIZE ${size} needs`);\n\t\tdata.set(v, rows * 3);\n\t\trows++;\n\t}\n\tif (!size) throw new Error(size1 ? 'The .cube file is a 1D LUT (LUT_1D_SIZE); only 3D LUTs (LUT_3D_SIZE) are supported.' : 'The .cube file has no LUT_3D_SIZE line, so it is not a 3D LUT.');\n\tif (rows !== size ** 3) throw new Error(`The .cube file has ${rows} table rows; LUT_3D_SIZE ${size} needs ${size ** 3}.`);\n\tfor (let c = 0; c < 3; c++) if (!(domainMax[c] > domainMin[c])) throw new Error('The .cube file\\'s DOMAIN_MAX must be larger than its DOMAIN_MIN on every channel.');\n\treturn { ...(title ? { title } : {}), size, domainMin, domainMax, data: data! };\n}\n\n/** A LUT of `size` points a side built from a colour function (each channel 0–1 in and out). */\nexport function videoLutFromFunction(size: number, fn: (rgb: [number, number, number]) => readonly [number, number, number], title?: string): VideoLut {\n\tconst n = size - 1;\n\tconst data = new Float32Array(size ** 3 * 3);\n\tlet i = 0;\n\tfor (let b = 0; b < size; b++)\n\t\tfor (let g = 0; g < size; g++)\n\t\t\tfor (let r = 0; r < size; r++) {\n\t\t\t\tdata.set(fn([r / n, g / n, b / n]), i);\n\t\t\t\ti += 3;\n\t\t\t}\n\treturn { ...(title ? { title } : {}), size, domainMin: [0, 0, 0], domainMax: [1, 1, 1], data };\n}\n\n/** A LUT as `.cube` text. */\nexport function videoLutToCube(lut: VideoLut): string {\n\tconst f = (v: number) => (Math.round(v * 1e6) / 1e6).toString();\n\tconst head = [...(lut.title ? [`TITLE \"${lut.title.replace(/\"/g, \"'\")}\"`] : []), `LUT_3D_SIZE ${lut.size}`];\n\tif (lut.domainMin.some((v) => v !== 0) || lut.domainMax.some((v) => v !== 1)) head.push(`DOMAIN_MIN ${lut.domainMin.map(f).join(' ')}`, `DOMAIN_MAX ${lut.domainMax.map(f).join(' ')}`);\n\tconst rows: string[] = [];\n\tfor (let i = 0; i < lut.data.length; i += 3) rows.push(`${f(lut.data[i])} ${f(lut.data[i + 1])} ${f(lut.data[i + 2])}`);\n\treturn `${head.join('\\n')}\\n${rows.join('\\n')}\\n`;\n}\n\nconst clamp01 = (v: number) => (v < 0 ? 0 : v > 1 ? 1 : v);\n\n/**\n * A colour (each channel 0–1) through a LUT with tetrahedral interpolation: the lattice cube\n * around the colour is split into six tetrahedra along its grey diagonal, and the colour is mixed\n * from the four corners of the one it falls in. Greys stay on the diagonal, unlike trilinear.\n */\nexport function applyVideoLut(lut: VideoLut, rgb: readonly [number, number, number], out: [number, number, number] = [0, 0, 0]): [number, number, number] {\n\tconst { size, data, domainMin, domainMax } = lut;\n\tconst n = size - 1;\n\tconst x = clamp01((rgb[0] - domainMin[0]) / (domainMax[0] - domainMin[0])) * n;\n\tconst y = clamp01((rgb[1] - domainMin[1]) / (domainMax[1] - domainMin[1])) * n;\n\tconst z = clamp01((rgb[2] - domainMin[2]) / (domainMax[2] - domainMin[2])) * n;\n\tconst r0 = Math.min(n - 1, Math.floor(x));\n\tconst g0 = Math.min(n - 1, Math.floor(y));\n\tconst b0 = Math.min(n - 1, Math.floor(z));\n\tconst fr = x - r0;\n\tconst fg = y - g0;\n\tconst fb = z - b0;\n\t// Offsets (in values) of a step along r, g and b.\n\tconst sr = 3;\n\tconst sg = 3 * size;\n\tconst sb = 3 * size * size;\n\tconst o = r0 * sr + g0 * sg + b0 * sb;\n\t// The path through the cube from (0,0,0) to (1,1,1) follows the largest fraction first.\n\tlet a: number, c: number, w0: number, w1: number, w2: number, w3: number;\n\tif (fr > fg) {\n\t\tif (fg > fb) [a, c, w0, w1, w2, w3] = [sr, sr + sg, 1 - fr, fr - fg, fg - fb, fb];\n\t\telse if (fr > fb) [a, c, w0, w1, w2, w3] = [sr, sr + sb, 1 - fr, fr - fb, fb - fg, fg];\n\t\telse [a, c, w0, w1, w2, w3] = [sb, sb + sr, 1 - fb, fb - fr, fr - fg, fg];\n\t} else if (fb > fg) [a, c, w0, w1, w2, w3] = [sb, sb + sg, 1 - fb, fb - fg, fg - fr, fr];\n\telse if (fb > fr) [a, c, w0, w1, w2, w3] = [sg, sg + sb, 1 - fg, fg - fb, fb - fr, fr];\n\telse [a, c, w0, w1, w2, w3] = [sg, sg + sr, 1 - fg, fg - fr, fr - fb, fb];\n\tconst d = sr + sg + sb;\n\tfor (let k = 0; k < 3; k++) out[k] = clamp01(w0 * data[o + k] + w1 * data[o + a + k] + w2 * data[o + c + k] + w3 * data[o + d + k]);\n\treturn out;\n}\n\n/** Runs RGBA pixels (0–255, as `ImageData` has them) through a LUT in place, mixed with the originals by `strength` (0–1). Transparent pixels are left alone. */\nexport function applyVideoLutToPixels(lut: VideoLut, data: { length: number; [i: number]: number }, strength = 1): void {\n\tconst s = clamp01(strength);\n\tif (!s) return;\n\tconst rgb: [number, number, number] = [0, 0, 0];\n\tconst out: [number, number, number] = [0, 0, 0];\n\tfor (let i = 0; i < data.length; i += 4) {\n\t\tif (!data[i + 3]) continue;\n\t\trgb[0] = data[i] / 255;\n\t\trgb[1] = data[i + 1] / 255;\n\t\trgb[2] = data[i + 2] / 255;\n\t\tapplyVideoLut(lut, rgb, out);\n\t\tfor (let k = 0; k < 3; k++) data[i + k] = Math.round((rgb[k] + (out[k] - rgb[k]) * s) * 255);\n\t}\n}\n\n/**\n * An SVG approximation of a LUT for SVG frames, which have no 3D tables: per-channel curves taken\n * along the LUT's grey axis (`feComponentTransfer` tables), then the colour matrix that best fits\n * the rest (least squares over the lattice). Exact for LUTs that are curves or a matrix; close for\n * most looks. The preview and the export apply the LUT itself.\n */\nexport interface VideoLutSvgApproximation {\n\t/** Per-channel curve tables (`tableValues`), each 0–1. */\n\ttables: [number[], number[], number[]];\n\t/** A 3 × 4 matrix (rows r, g, b; columns r, g, b, offset) applied after the curves. */\n\tmatrix: number[][];\n}\n\nconst approximations = new WeakMap<VideoLut, VideoLutSvgApproximation>();\n\nexport function videoLutSvgApproximation(lut: VideoLut): VideoLutSvgApproximation {\n\tconst cached = approximations.get(lut);\n\tif (cached) return cached;\n\tconst points = 17;\n\tconst tables: [number[], number[], number[]] = [[], [], []];\n\tfor (let i = 0; i < points; i++) {\n\t\tconst v = i / (points - 1);\n\t\tconst out = applyVideoLut(lut, [v, v, v]);\n\t\tfor (let k = 0; k < 3; k++) tables[k].push(out[k]);\n\t}\n\tconst curve = (k: number, v: number) => {\n\t\tconst x = clamp01(v) * (points - 1);\n\t\tconst i = Math.min(points - 2, Math.floor(x));\n\t\treturn tables[k][i] + (tables[k][i + 1] - tables[k][i]) * (x - i);\n\t};\n\t// Least squares: matrix rows minimising |M·[curve(x), 1] − lut(x)|² over a 9³ grid.\n\tconst ata = Array.from({ length: 4 }, () => [0, 0, 0, 0]);\n\tconst atb = Array.from({ length: 3 }, () => [0, 0, 0, 0]);\n\tconst grid = 9;\n\tfor (let b = 0; b < grid; b++)\n\t\tfor (let g = 0; g < grid; g++)\n\t\t\tfor (let r = 0; r < grid; r++) {\n\t\t\t\tconst x: [number, number, number] = [r / (grid - 1), g / (grid - 1), b / (grid - 1)];\n\t\t\t\tconst z = [curve(0, x[0]), curve(1, x[1]), curve(2, x[2]), 1];\n\t\t\t\tconst y = applyVideoLut(lut, x);\n\t\t\t\tfor (let i = 0; i < 4; i++) {\n\t\t\t\t\tfor (let j = 0; j < 4; j++) ata[i][j] += z[i] * z[j];\n\t\t\t\t\tfor (let k = 0; k < 3; k++) atb[k][i] += z[i] * y[k];\n\t\t\t\t}\n\t\t\t}\n\tconst matrix = atb.map((rhs) => solve4(ata, rhs));\n\tconst result = { tables, matrix };\n\tapproximations.set(lut, result);\n\treturn result;\n}\n\n/** Solves a 4 × 4 system by Gaussian elimination with partial pivoting (falls back to identity rows when singular). */\nfunction solve4(a: number[][], b: number[]): number[] {\n\tconst m = a.map((row, i) => [...row, b[i]]);\n\tfor (let col = 0; col < 4; col++) {\n\t\tlet pivot = col;\n\t\tfor (let r = col + 1; r < 4; r++) if (Math.abs(m[r][col]) > Math.abs(m[pivot][col])) pivot = r;\n\t\tif (Math.abs(m[pivot][col]) < 1e-12) continue;\n\t\t[m[col], m[pivot]] = [m[pivot], m[col]];\n\t\tfor (let r = 0; r < 4; r++) {\n\t\t\tif (r === col) continue;\n\t\t\tconst f = m[r][col] / m[col][col];\n\t\t\tfor (let c = col; c < 5; c++) m[r][c] -= f * m[col][c];\n\t\t}\n\t}\n\treturn m.map((row, i) => (Math.abs(row[i]) < 1e-12 ? 0 : row[4] / row[i]));\n}\n\n/** Where LUT files come from: their text for a `src` (default: `fetch`). */\nexport type VideoLutLoader = (src: string) => Promise<string | VideoLut>;\n\n/**\n * Loaded LUTs by `src`, read once and shared by the preview, SVG frames and agent tools\n * (`VideoEditorController.luts`). Listeners hear when one loads or fails.\n */\nexport class VideoLutCache {\n\tprivate readonly ready = new Map<string, VideoLut>();\n\tprivate readonly pending = new Map<string, Promise<VideoLut>>();\n\tprivate readonly failed = new Map<string, string>();\n\tprivate readonly listeners = new Set<() => void>();\n\n\tconstructor(\n\t\tprivate readonly loader: VideoLutLoader = async (src) => {\n\t\t\tconst res = await fetch(src);\n\t\t\tif (!res.ok) throw new Error(`${res.status} ${res.statusText}`.trim());\n\t\t\treturn res.text();\n\t\t}\n\t) {}\n\n\t/** The LUT if loaded, without starting to load it. */\n\tpeek(src: string): VideoLut | undefined {\n\t\treturn this.ready.get(src);\n\t}\n\n\t/** The LUT if loaded; otherwise `undefined`, and loading starts (once) unless it failed. */\n\tget(src: string): VideoLut | undefined {\n\t\tconst lut = this.ready.get(src);\n\t\tif (!lut && !this.failed.has(src)) void this.load(src).catch(() => {});\n\t\treturn lut;\n\t}\n\n\t/** Why loading a LUT failed, if it did. */\n\terror(src: string): string | undefined {\n\t\treturn this.failed.get(src);\n\t}\n\n\t/** The LUT, loading and reading it if needed. Rejects with a readable error. */\n\tload(src: string): Promise<VideoLut> {\n\t\tconst ready = this.ready.get(src);\n\t\tif (ready) return Promise.resolve(ready);\n\t\tconst failed = this.failed.get(src);\n\t\tif (failed) return Promise.reject(new Error(failed));\n\t\tlet pending = this.pending.get(src);\n\t\tif (!pending) {\n\t\t\tpending = Promise.resolve()\n\t\t\t\t.then(() => this.loader(src))\n\t\t\t\t.then((v) => (typeof v === 'string' ? parseVideoCubeLut(v) : v))\n\t\t\t\t.then(\n\t\t\t\t\t(lut) => {\n\t\t\t\t\t\tthis.pending.delete(src);\n\t\t\t\t\t\tthis.ready.set(src, lut);\n\t\t\t\t\t\tthis.emit();\n\t\t\t\t\t\treturn lut;\n\t\t\t\t\t},\n\t\t\t\t\t(e: unknown) => {\n\t\t\t\t\t\tthis.pending.delete(src);\n\t\t\t\t\t\tconst message = `The LUT \"${src}\" could not be read: ${e instanceof Error ? e.message : String(e)}`;\n\t\t\t\t\t\tthis.failed.set(src, message);\n\t\t\t\t\t\tthis.emit();\n\t\t\t\t\t\tthrow new Error(message);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\tthis.pending.set(src, pending);\n\t\t}\n\t\treturn pending;\n\t}\n\n\t/** Uses a LUT the host already has (`.cube` text or a parsed LUT), under `src`. */\n\tset(src: string, lut: VideoLut | string): VideoLut {\n\t\tconst parsed = typeof lut === 'string' ? parseVideoCubeLut(lut) : lut;\n\t\tthis.ready.set(src, parsed);\n\t\tthis.failed.delete(src);\n\t\tthis.emit();\n\t\treturn parsed;\n\t}\n\n\t/** Forgets a failure so the next `get` tries again. */\n\tretry(src: string): void {\n\t\tif (this.failed.delete(src)) this.emit();\n\t}\n\n\tsubscribe(fn: () => void): () => void {\n\t\tthis.listeners.add(fn);\n\t\treturn () => {\n\t\t\tthis.listeners.delete(fn);\n\t\t};\n\t}\n\n\tprivate emit() {\n\t\tfor (const l of [...this.listeners]) l();\n\t}\n}\n","import { applyVideoLut, videoLutSvgApproximation, type VideoLut } from './lut.js';\nimport type { VideoGrade, VideoGradeLut } from './types.js';\n\n/**\n * Colour correction as a fixed series of colour-matrix steps on gamma-encoded sRGB, each clamped\n * to 0–1, in the same order everywhere: exposure, contrast, saturation, hue, then white balance.\n * Every step is one the browser has (CSS `brightness`, `contrast`, `saturate`, `hue-rotate`; white\n * balance as an SVG `feColorMatrix`) and ffmpeg has (`lutrgb`, `colorchannelmixer`), with the same\n * formulas, so the preview, SVG frames and the export agree.\n */\n\n/** One slider of a grade: its range, default and step, for schemas, inspectors and clamping. */\n/** The numeric settings of a grade (everything but its LUT). */\nexport type VideoGradeSetting = Exclude<keyof VideoGrade, 'lut'>;\n\nexport interface VideoGradeControl {\n\tkey: VideoGradeSetting;\n\tlabel: string;\n\tmin: number;\n\tmax: number;\n\tstep: number;\n\t/** What the number means, for tool descriptions. */\n\tdescription: string;\n}\n\nexport const VIDEO_GRADE_CONTROLS: readonly VideoGradeControl[] = [\n\t{ key: 'exposure', label: 'Exposure', min: -3, max: 3, step: 0.1, description: 'Exposure in stops: +1 doubles every channel, -1 halves it (default 0).' },\n\t{ key: 'contrast', label: 'Contrast', min: -1, max: 1, step: 0.05, description: 'Contrast around mid grey, -1 (flat grey) to 1 (twice as steep); default 0.' },\n\t{ key: 'saturation', label: 'Saturation', min: -1, max: 1, step: 0.05, description: 'Saturation, -1 (black and white) to 1 (twice as saturated); default 0.' },\n\t{ key: 'hue', label: 'Hue', min: -180, max: 180, step: 1, description: 'Hue rotation in degrees (default 0).' },\n\t{ key: 'temperature', label: 'Temperature', min: -1, max: 1, step: 0.05, description: 'White balance, -1 (cool, bluer) to 1 (warm, more orange); default 0.' },\n\t{ key: 'tint', label: 'Tint', min: -1, max: 1, step: 0.05, description: 'White balance, -1 (greener) to 1 (more magenta); default 0.' }\n];\n\n/** Named looks. Apply them at a strength with `videoGradePreset`. */\nexport const VIDEO_GRADE_PRESETS = {\n\twarm: { temperature: 0.4, saturation: 0.1 },\n\tcool: { temperature: -0.4, tint: -0.05 },\n\tpunchy: { contrast: 0.25, saturation: 0.3 },\n\tfaded: { exposure: 0.15, contrast: -0.3, saturation: -0.3 },\n\t'black-and-white': { saturation: -1, contrast: 0.15 },\n\t'bleach-bypass': { saturation: -0.6, contrast: 0.4 },\n\t'day-for-night': { exposure: -1.5, saturation: -0.4, temperature: -0.6 }\n} as const satisfies Record<string, VideoGrade>;\nexport type VideoGradePreset = keyof typeof VIDEO_GRADE_PRESETS;\nexport const VIDEO_GRADE_PRESET_NAMES = Object.keys(VIDEO_GRADE_PRESETS) as VideoGradePreset[];\n\nconst clampTo = (c: VideoGradeControl, v: number) => Math.min(c.max, Math.max(c.min, v));\n\n/** A LUT setting with its strength clamped to 0–1 (and 1 left out); `undefined` without a `src` or at strength 0. */\nexport function normalizeVideoGradeLut(lut: VideoGradeLut | undefined): VideoGradeLut | undefined {\n\tif (!lut || typeof lut.src !== 'string' || !lut.src) return undefined;\n\tconst strength = typeof lut.strength === 'number' && Number.isFinite(lut.strength) ? Math.round(Math.min(1, Math.max(0, lut.strength)) * 1000) / 1000 : 1;\n\tif (!strength) return undefined;\n\treturn { src: lut.src, ...(strength !== 1 ? { strength } : {}), ...(lut.name ? { name: lut.name } : {}) };\n}\n\n/** A grade with every value clamped to its range and zero values left out; `undefined` when nothing is left. */\nexport function normalizeVideoGrade(grade: VideoGrade | undefined): VideoGrade | undefined {\n\tif (!grade) return undefined;\n\tconst out: VideoGrade = {};\n\tfor (const c of VIDEO_GRADE_CONTROLS) {\n\t\tconst v = grade[c.key];\n\t\tif (typeof v === 'number' && Number.isFinite(v) && v !== 0) out[c.key] = Math.round(clampTo(c, v) * 1000) / 1000;\n\t}\n\tconst lut = normalizeVideoGradeLut(grade.lut);\n\tif (lut) out.lut = lut;\n\treturn Object.keys(out).length ? out : undefined;\n}\n\n/** A preset at `amount` (0–1, default 1) of its strength. */\nexport function videoGradePreset(name: VideoGradePreset, amount = 1): VideoGrade | undefined {\n\tconst preset: Omit<VideoGrade, 'lut'> = VIDEO_GRADE_PRESETS[name];\n\tif (!preset) throw new Error(`There is no grade preset \"${name}\"; the presets are ${VIDEO_GRADE_PRESET_NAMES.join(', ')}.`);\n\tconst k = Math.min(1, Math.max(0, amount));\n\treturn normalizeVideoGrade(Object.fromEntries(Object.entries(preset).map(([key, v]) => [key, (v as number) * k])));\n}\n\n/** A preset look on a grade, keeping the grade's LUT (a look replaces only the settings). */\nexport function videoGradeLook(current: VideoGrade | undefined, name: VideoGradePreset, amount = 1): VideoGrade | undefined {\n\treturn normalizeVideoGrade({ ...videoGradePreset(name, amount), ...(current?.lut ? { lut: current.lut } : {}) });\n}\n\n/** One step of a grade. */\nexport type VideoGradeStep =\n\t| { kind: 'brightness'; amount: number }\n\t| { kind: 'contrast'; amount: number }\n\t| { kind: 'saturate'; amount: number }\n\t| { kind: 'hue-rotate'; degrees: number }\n\t| { kind: 'gains'; r: number; g: number; b: number };\n\n/** The steps a grade applies, in order, leaving out those that change nothing. */\nexport function videoGradeSteps(grade: VideoGrade | undefined): VideoGradeStep[] {\n\tconst g = normalizeVideoGrade(grade);\n\tif (!g) return [];\n\tconst steps: VideoGradeStep[] = [];\n\tif (g.exposure) steps.push({ kind: 'brightness', amount: 2 ** g.exposure });\n\tif (g.contrast) steps.push({ kind: 'contrast', amount: 1 + g.contrast });\n\tif (g.saturation) steps.push({ kind: 'saturate', amount: 1 + g.saturation });\n\tif (g.hue) steps.push({ kind: 'hue-rotate', degrees: g.hue });\n\tif (g.temperature || g.tint) {\n\t\tconst t = g.temperature ?? 0;\n\t\tsteps.push({ kind: 'gains', r: 1 + 0.25 * t, g: 1 - 0.25 * (g.tint ?? 0), b: 1 - 0.25 * t });\n\t}\n\treturn steps;\n}\n\n/**\n * A step as a 3 × 4 matrix (rows r, g, b; columns r, g, b, offset), with the coefficients the CSS\n * Filter Effects spec gives for `saturate` and `hue-rotate`.\n */\nexport function videoGradeStepMatrix(step: VideoGradeStep): number[][] {\n\tswitch (step.kind) {\n\t\tcase 'brightness':\n\t\t\treturn [\n\t\t\t\t[step.amount, 0, 0, 0],\n\t\t\t\t[0, step.amount, 0, 0],\n\t\t\t\t[0, 0, step.amount, 0]\n\t\t\t];\n\t\tcase 'contrast': {\n\t\t\tconst c = step.amount;\n\t\t\tconst o = 0.5 - 0.5 * c;\n\t\t\treturn [\n\t\t\t\t[c, 0, 0, o],\n\t\t\t\t[0, c, 0, o],\n\t\t\t\t[0, 0, c, o]\n\t\t\t];\n\t\t}\n\t\tcase 'gains':\n\t\t\treturn [\n\t\t\t\t[step.r, 0, 0, 0],\n\t\t\t\t[0, step.g, 0, 0],\n\t\t\t\t[0, 0, step.b, 0]\n\t\t\t];\n\t\tcase 'saturate': {\n\t\t\tconst s = step.amount;\n\t\t\treturn [\n\t\t\t\t[0.213 + 0.787 * s, 0.715 - 0.715 * s, 0.072 - 0.072 * s, 0],\n\t\t\t\t[0.213 - 0.213 * s, 0.715 + 0.285 * s, 0.072 - 0.072 * s, 0],\n\t\t\t\t[0.213 - 0.213 * s, 0.715 - 0.715 * s, 0.072 + 0.928 * s, 0]\n\t\t\t];\n\t\t}\n\t\tcase 'hue-rotate': {\n\t\t\tconst a = (step.degrees * Math.PI) / 180;\n\t\t\tconst cos = Math.cos(a);\n\t\t\tconst sin = Math.sin(a);\n\t\t\treturn [\n\t\t\t\t[0.213 + cos * 0.787 - sin * 0.213, 0.715 - cos * 0.715 - sin * 0.715, 0.072 - cos * 0.072 + sin * 0.928, 0],\n\t\t\t\t[0.213 - cos * 0.213 + sin * 0.143, 0.715 + cos * 0.285 + sin * 0.14, 0.072 - cos * 0.072 - sin * 0.283, 0],\n\t\t\t\t[0.213 - cos * 0.213 - sin * 0.787, 0.715 - cos * 0.715 + sin * 0.715, 0.072 + cos * 0.928 + sin * 0.072, 0]\n\t\t\t];\n\t\t}\n\t}\n}\n\n/**\n * An RGB colour (0–255 each) through a grade, as the preview and export draw it. A grade's LUT is\n * applied when its table is passed as `lut` (else it is left out).\n */\nexport function applyVideoGrade(grade: VideoGrade | undefined, rgb: readonly [number, number, number], lut?: VideoLut | null): [number, number, number] {\n\tlet v = rgb.map((x) => x / 255);\n\tfor (const step of videoGradeSteps(grade)) {\n\t\tconst m = videoGradeStepMatrix(step);\n\t\tv = m.map((row) => Math.min(1, Math.max(0, row[0] * v[0] + row[1] * v[1] + row[2] * v[2] + row[3])));\n\t}\n\tconst setting = normalizeVideoGradeLut(grade?.lut);\n\tif (setting && lut) {\n\t\tconst out = applyVideoLut(lut, v as [number, number, number]);\n\t\tconst s = setting.strength ?? 1;\n\t\tv = v.map((x, k) => x + (out[k] - x) * s);\n\t}\n\treturn v.map((x) => Math.round(x * 255)) as [number, number, number];\n}\n\nconst fmt = (v: number) => String(Math.round(v * 1e5) / 1e5);\n\n/** The `values` of an SVG `feColorMatrix type=\"matrix\"` for a step. */\nexport function videoGradeStepSvgValues(step: VideoGradeStep): string {\n\treturn videoGradeStepMatrix(step)\n\t\t.map((row) => [row[0], row[1], row[2], 0, row[3]].map(fmt).join(' '))\n\t\t.concat('0 0 0 1 0')\n\t\t.join(' ');\n}\n\n/**\n * SVG filter primitives approximating a LUT (see `videoLutSvgApproximation`) on the result of the\n * primitives before them, mixed with it by `strength`.\n */\nexport function videoLutSvgPrimitives(lut: VideoLut, strength = 1): string {\n\tconst { tables, matrix } = videoLutSvgApproximation(lut);\n\tconst table = (k: number) => tables[k].map(fmt).join(' ');\n\tconst values = matrix.map((row) => [row[0], row[1], row[2], 0, row[3]].map(fmt).join(' ')).concat('0 0 0 1 0').join(' ');\n\tconst s = Math.min(1, Math.max(0, strength));\n\treturn (\n\t\t'<feComponentTransfer result=\"lutIn\"><feFuncA type=\"identity\"/></feComponentTransfer>' +\n\t\t`<feComponentTransfer><feFuncR type=\"table\" tableValues=\"${table(0)}\"/><feFuncG type=\"table\" tableValues=\"${table(1)}\"/><feFuncB type=\"table\" tableValues=\"${table(2)}\"/></feComponentTransfer>` +\n\t\t`<feColorMatrix type=\"matrix\" values=\"${values}\"/>` +\n\t\t(s < 1 ? `<feComposite in2=\"lutIn\" operator=\"arithmetic\" k1=\"0\" k2=\"${fmt(s)}\" k3=\"${fmt(1 - s)}\" k4=\"0\"/>` : '')\n\t);\n}\n\n/**\n * An SVG `<filter>` applying a grade, steps in order (each clamps, as CSS filters do). With the\n * grade's LUT table (`lut`), an approximation of it follows (SVG has no 3D tables).\n */\nexport function videoGradeSvgFilter(id: string, grade: VideoGrade | undefined, lut?: VideoLut | null): string {\n\tconst steps = videoGradeSteps(grade);\n\tconst setting = normalizeVideoGradeLut(grade?.lut);\n\treturn `<filter id=\"${id}\" color-interpolation-filters=\"sRGB\" x=\"0\" y=\"0\" width=\"100%\" height=\"100%\">${steps.map((s) => `<feColorMatrix type=\"matrix\" values=\"${videoGradeStepSvgValues(s)}\"/>`).join('')}${setting && lut ? videoLutSvgPrimitives(lut, setting.strength) : ''}</filter>`;\n}\n\n/** Id of the SVG filter for a white-balance step: the same gains always get the same id. */\nexport const videoGradeGainsFilterId = (step: Extract<VideoGradeStep, { kind: 'gains' }>): string => `pixerate-wb-${[step.r, step.g, step.b].map((v) => Math.round(v * 1000)).join('-')}`;\n\n/**\n * A grade as a CSS / canvas `filter`: CSS functions for every step, and `url(#id)` for white balance,\n * which CSS has no function for (see `videoGradeGainsFilterId`; the host puts that filter in the page).\n * `''` when the grade changes nothing.\n */\nexport function videoGradeCssFilter(grade: VideoGrade | undefined): string {\n\treturn videoGradeSteps(grade)\n\t\t.map((s) => (s.kind === 'brightness' ? `brightness(${fmt(s.amount)})` : s.kind === 'contrast' ? `contrast(${fmt(s.amount)})` : s.kind === 'saturate' ? `saturate(${fmt(s.amount)})` : s.kind === 'hue-rotate' ? `hue-rotate(${fmt(s.degrees)}deg)` : `url(#${videoGradeGainsFilterId(s)})`))\n\t\t.join(' ');\n}\n\n/** The white-balance SVG filters a grade's CSS filter refers to, as `{ id, markup }`. */\nexport function videoGradeSvgDefs(grade: VideoGrade | undefined): { id: string; markup: string }[] {\n\treturn videoGradeSteps(grade)\n\t\t.filter((s): s is Extract<VideoGradeStep, { kind: 'gains' }> => s.kind === 'gains')\n\t\t.map((s) => {\n\t\t\tconst id = videoGradeGainsFilterId(s);\n\t\t\treturn { id, markup: `<filter id=\"${id}\" color-interpolation-filters=\"sRGB\"><feColorMatrix type=\"matrix\" values=\"${videoGradeStepSvgValues(s)}\"/></filter>` };\n\t\t});\n}\n\n/** A grade as ffmpeg filters on RGB, in order: `lutrgb` for exposure and contrast, `colorchannelmixer` for the rest. */\nexport function videoGradeFfmpegFilters(grade: VideoGrade | undefined): string[] {\n\treturn videoGradeSteps(grade).map((step) => {\n\t\tconst m = videoGradeStepMatrix(step);\n\t\tif (step.kind === 'brightness' || step.kind === 'contrast') {\n\t\t\tconst lut = (i: number) => `clip(val*${fmt(m[i][i])}+${fmt(m[i][3] * 255)},0,255)`;\n\t\t\treturn `lutrgb=r='${lut(0)}':g='${lut(1)}':b='${lut(2)}'`;\n\t\t}\n\t\tconst k = ['r', 'g', 'b'];\n\t\treturn `colorchannelmixer=${m.flatMap((row, i) => row.slice(0, 3).map((v, j) => `${k[i]}${k[j]}=${fmt(v)}`)).join(':')}`;\n\t});\n}\n","import type { VideoEdit } from './edit.js';\nimport { splitVideoAnimatable, videoEaseBezier, videoKeyframeBreakpoints, videoValueAt, type VideoEase, type VideoKey, type VideoKeyframes } from './keyframes.js';\nimport type { VideoClip, VideoMediaClip } from './types.js';\n\n/**\n * Speed ramps and freeze frames: a media clip's `timeRemap` keys map clip time to source time after\n * its in point. The slope between two keys is the speed there; equal values are a freeze; an eased\n * segment changes speed smoothly. These helpers read and build them.\n */\n\n/** Where in the source (ms) a media clip is at clip time `clipTime`, through its speed or its ramp. */\nexport function videoClipSourceTime(clip: VideoMediaClip, clipTime: number): number {\n\tconst base = clip.in ?? 0;\n\treturn clip.timeRemap ? base + videoValueAt(clip.timeRemap, clipTime, 0) : base + clipTime * (clip.speed ?? 1);\n}\n\n/** The speed a media clip plays at at clip time `clipTime` (0 in a freeze), measured over a millisecond. */\nexport function videoClipSpeedAt(clip: VideoClip, clipTime: number): number {\n\tif (clip.type !== 'media') return 1;\n\tif (!clip.timeRemap) return clip.speed ?? 1;\n\tconst t = Math.min(Math.max(clipTime, 0), Math.max(0, clip.duration - 1));\n\treturn Math.max(0, videoClipSourceTime(clip, t + 1) - videoClipSourceTime(clip, t));\n}\n\n/** One stretch of a ramp: `duration` ms of the clip at `speed`, or easing from `speed` to `toSpeed`. 0 is a freeze. */\nexport interface VideoSpeedSegment {\n\tduration: number;\n\tspeed: number;\n\t/** Ramp smoothly to this speed by the end of the stretch (default: stay at `speed`). */\n\ttoSpeed?: number;\n}\n\n/**\n * Remap keys for stretches of speed, from the clip's start: steady stretches are linear segments,\n * ramps a cubic-bezier ease that changes the speed evenly from one to the other (the source moves\n * the average of the two speeds over the stretch). Returns the keys and the source the clip plays.\n */\nexport function videoSpeedRampKeys(segments: readonly VideoSpeedSegment[]): { keys: VideoKey[]; duration: number; source: number } {\n\tif (!segments.length) throw new Error('Give at least one stretch { duration, speed }.');\n\tconst keys: VideoKey[] = [];\n\tlet t = 0;\n\tlet v = 0;\n\tsegments.forEach((s, i) => {\n\t\tif (!(s.duration > 0)) throw new Error(`Stretch ${i + 1} needs a duration above 0 ms.`);\n\t\tfor (const [name, x] of [['speed', s.speed], ['toSpeed', s.toSpeed]] as const)\n\t\t\tif (x !== undefined && !(x >= 0 && x <= 20)) throw new Error(`Stretch ${i + 1}'s ${name} must be from 0 (a freeze) to 20; got ${x}.`);\n\t\tconst a = s.speed;\n\t\tconst b = s.toSpeed ?? s.speed;\n\t\tconst avg = (a + b) / 2;\n\t\tlet ease: VideoEase = 'linear';\n\t\tif (a !== b && avg > 0) {\n\t\t\t// The source position is quadratic in time; as a cubic bezier its handles sit a third of the way along, at the end slopes.\n\t\t\tease = [1 / 3, (2 * a) / (3 * (a + b)), 2 / 3, 1 - (2 * b) / (3 * (a + b))].map((n) => Math.round(n * 1e6) / 1e6) as [number, number, number, number];\n\t\t}\n\t\tkeys.push({ t, v, ...(ease === 'linear' ? {} : { ease }) });\n\t\tt += s.duration;\n\t\tv += avg * s.duration;\n\t});\n\tkeys.push({ t, v });\n\treturn { keys: mergeLinear(keys), duration: t, source: v };\n}\n\n/** Drops keys in the middle of a straight line, so steady speed is one segment. */\nfunction mergeLinear(keys: VideoKey[]): VideoKey[] {\n\tconst out: VideoKey[] = [keys[0]];\n\tfor (let i = 1; i < keys.length; i++) {\n\t\tconst prev = out[out.length - 1];\n\t\tconst k = keys[i];\n\t\tconst before = out.length > 1 ? out[out.length - 2] : null;\n\t\t// prev sits on a straight line from before to k: drop it (k keeps its own ease onward).\n\t\tif (before && !before.ease && !prev.ease) {\n\t\t\tconst s1 = (prev.v - before.v) / (prev.t - before.t);\n\t\t\tconst s2 = (k.v - prev.v) / (k.t - prev.t);\n\t\t\tif (Math.abs(s1 - s2) < 1e-9) {\n\t\t\t\tout[out.length - 1] = k;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tout.push(k);\n\t}\n\treturn out;\n}\n\n/**\n * Checks remap keys: in time order and never going back in the source, eased segments included\n * (each is sampled, so a curve that overshoots and would play backwards is caught). Throws a\n * readable error.\n */\nexport function checkVideoTimeRemap(remap: VideoKeyframes, path = 'timeRemap'): void {\n\tconst { keys } = remap;\n\tif (!keys.length) throw new Error(`${path} needs at least one key.`);\n\tkeys.forEach((k, i) => {\n\t\tif (k.v < 0) throw new Error(`${path}.keys[${i}].v must be at least 0 (ms after the in point).`);\n\t\tconst next = keys[i + 1];\n\t\tif (!next) return;\n\t\tif (next.v < k.v - 1e-6) throw new Error(`${path}.keys[${i + 1}] goes back in the source (${next.v} ms after ${k.v} ms); a ramp only plays forwards, so make each value at least the one before.`);\n\t\tif (!videoEaseBezier(k.ease)) return;\n\t\tlet prev = k.v;\n\t\tfor (let n = 1; n <= 32; n++) {\n\t\t\tconst v = videoValueAt(remap, k.t + ((next.t - k.t) * n) / 32);\n\t\t\tif (v < prev - 1e-3) throw new Error(`${path}.keys[${i}].ease overshoots, which would play backwards; use a curve that only moves forwards (or linear).`);\n\t\t\tprev = v;\n\t\t}\n\t});\n}\n\n/** The stretch of source (ms, from the in point) a ramp plays: from its first key's value to its last's. */\nexport function videoTimeRemapSpan(remap: VideoKeyframes): { from: number; to: number } {\n\treturn { from: remap.keys[0].v, to: remap.keys[remap.keys.length - 1].v };\n}\n\n/** Clip time and source time pairs tracing a ramp as straight lines (eased stretches sampled every `step` ms), with freezes marked. */\nexport function videoTimeRemapBreakpoints(remap: VideoKeyframes, step: number): { t: number; v: number }[] {\n\tconst { points, holds } = videoKeyframeBreakpoints(remap, step);\n\tconst out: { t: number; v: number }[] = [];\n\tpoints.forEach(([t, v], i) => {\n\t\tout.push({ t, v });\n\t\t// A hold keeps its value up to the next key, then jumps forward.\n\t\tif (holds.has(i) && points[i + 1]) out.push({ t: points[i + 1][0], v });\n\t});\n\treturn out;\n}\n\n/** The edit that plays a media clip through stretches of speed from the moment it shows at its start (see `videoSpeedRampKeys`). */\nexport function videoSpeedRampEdit(clip: VideoMediaClip, segments: readonly VideoSpeedSegment[], ripple = true): VideoEdit {\n\tconst ramp = videoSpeedRampKeys(segments);\n\tconst offset = videoClipSourceTime(clip, 0) - (clip.in ?? 0);\n\treturn { op: 'set_time_remap', clip: clip.id, keys: ramp.keys.map((k) => ({ ...k, v: k.v + offset })), duration: ramp.duration, ripple };\n}\n\n/** The edit that holds the frame a media clip shows at clip time `at` for `duration` ms, then plays on (the clip gets longer). */\nexport function videoFreezeFrameEdit(clip: VideoMediaClip, at: number, duration: number, ripple = true): VideoEdit {\n\tif (at < 0 || at > clip.duration) throw new Error(`${Math.round(at)} ms is outside clip \"${clip.id}\" (0–${clip.duration} ms of clip time).`);\n\tconst remap: VideoKeyframes = clip.timeRemap ?? { keys: [{ t: 0, v: 0 }, { t: clip.duration, v: clip.duration * (clip.speed ?? 1) }] };\n\tconst [left, right] = splitVideoAnimatable(remap, at);\n\tconst keys: VideoKey[] = [...left.keys.slice(0, -1), { ...left.keys[left.keys.length - 1], ease: 'linear' }, ...right.keys.map((k) => ({ ...k, t: k.t + at + duration }))];\n\treturn { op: 'set_time_remap', clip: clip.id, keys, duration: clip.duration + duration, ripple };\n}\n\n/** A slow-motion ramp preset for a clip of `duration` ms: normal speed for half of it, a 500 ms glide down to 0.3×, then 1.5 s at 0.3×. */\nexport const videoSlowMotionRamp = (duration: number): VideoSpeedSegment[] => [\n\t{ duration: Math.max(1, duration / 2), speed: 1 },\n\t{ duration: 500, speed: 1, toSpeed: 0.3 },\n\t{ duration: 1500, speed: 0.3 }\n];\n","import type { VideoAsset, VideoClip, VideoProject, VideoSequence, VideoTrack } from './types.js';\n\n/** Clip edges closer than this (ms) count as touching: a cut, not a gap. */\nexport const VIDEO_TIME_EPSILON = 0.5;\n\nexport const videoClipEnd = (clip: VideoClip): number => clip.start + clip.duration;\n\n/** Whether a track moves with ripple edits on other tracks (`syncLocked`, default true). */\nexport const videoTrackSyncLocked = (track: VideoTrack): boolean => track.syncLocked !== false;\n\n/** Playback speed of a clip (1 for titles and colours). */\nexport const videoClipSpeed = (clip: VideoClip): number => (clip.type === 'media' ? (clip.speed ?? 1) : 1);\n\n/**\n * The stretch of source a media clip plays (ms), or of its sequence's time a compound plays; `null`\n * for titles and colours.\n */\nexport function videoClipSourceRange(clip: VideoClip): { in: number; out: number } | null {\n\tif (clip.type === 'sequence') return { in: clip.in ?? 0, out: (clip.in ?? 0) + clip.duration };\n\tif (clip.type !== 'media') return null;\n\tconst start = clip.in ?? 0;\n\t// A ramp plays from its first key's source to its last's (holding before and after).\n\tif (clip.timeRemap?.keys.length) return { in: start + clip.timeRemap.keys[0].v, out: start + clip.timeRemap.keys[clip.timeRemap.keys.length - 1].v };\n\treturn { in: start, out: start + clip.duration * videoClipSpeed(clip) };\n}\n\n/** Length of one frame (ms). */\nexport const videoFrameDuration = (fps: number): number => 1000 / fps;\n\n/** `time` moved to the nearest frame boundary. */\nexport function snapToVideoFrame(time: number, fps: number): number {\n\tconst frame = Math.round((time * fps) / 1000);\n\treturn Math.round(((frame * 1000) / fps) * 1000) / 1000;\n}\n\n/** Whole frames in `time` at `fps` (rounded). */\nexport const videoFrames = (time: number, fps: number): number => Math.round((time * fps) / 1000);\n\n/**\n * Whether `fps` is an NTSC rate that SMPTE counts in drop-frame timecode: 29.97 (30000/1001) or\n * 59.94 (60000/1001). Other fractional rates (23.976) have no drop-frame form.\n */\nexport function isVideoDropFrameRate(fps: number): boolean {\n\tconst nominal = Math.round(fps);\n\treturn (nominal === 30 || nominal === 60) && Math.abs(fps - (nominal * 1000) / 1001) < 0.005;\n}\n\n/** The exact rate behind a rounded NTSC rate (29.97 → 30000/1001); other rates unchanged. */\nconst exactVideoRate = (fps: number): number => {\n\tconst nominal = Math.round(fps);\n\treturn nominal !== fps && Math.abs(fps - (nominal * 1000) / 1001) < 0.005 ? (nominal * 1000) / 1001 : fps;\n};\n\n/** Frames elapsed in `time` (ms), counted at the exact rate behind a rounded NTSC rate. */\nexport const videoTimecodeFrames = (time: number, fps: number): number => Math.max(0, Math.round((time * exactVideoRate(fps)) / 1000));\n\n/**\n * SMPTE timecode for a time (ms): `HH:MM:SS:FF`, or `HH:MM:SS;FF` in drop-frame, which skips frame\n * numbers 0 and 1 (0–3 at 59.94) at the start of every minute except each tenth, so the clock keeps\n * up with real time at NTSC rates. `dropFrame` defaults to on at 29.97 and 59.94 and is ignored at\n * rates without a drop-frame form.\n */\nexport function formatVideoTimecode(time: number, fps: number, dropFrame = isVideoDropFrameRate(fps)): string {\n\treturn formatVideoTimecodeFrames(videoTimecodeFrames(time, fps), fps, dropFrame);\n}\n\n/** SMPTE timecode for a frame count (see `formatVideoTimecode`). */\nexport function formatVideoTimecodeFrames(frames: number, fps: number, dropFrame = isVideoDropFrameRate(fps)): string {\n\tconst base = Math.round(fps);\n\tlet total = Math.max(0, Math.round(frames));\n\tconst drop = dropFrame && isVideoDropFrameRate(fps);\n\tif (drop) {\n\t\tconst skip = base / 15; // 2 at 29.97, 4 at 59.94\n\t\tconst perMinute = base * 60 - skip;\n\t\tconst perTen = perMinute * 10 + skip;\n\t\tconst tens = Math.floor(total / perTen);\n\t\tconst rest = total % perTen;\n\t\ttotal += skip * 9 * tens + (rest > skip ? skip * Math.floor((rest - skip) / perMinute) : 0);\n\t}\n\tconst ff = total % base;\n\tconst secs = Math.floor(total / base);\n\tconst pad = (n: number) => String(n).padStart(2, '0');\n\treturn `${pad(Math.floor(secs / 3600))}:${pad(Math.floor(secs / 60) % 60)}:${pad(secs % 60)}${drop ? ';' : ':'}${pad(ff)}`;\n}\n\n/** Frames up to timecode `01:00:00:00` (`;00` in drop-frame), where record timecode usually starts. */\nexport const videoHourFrames = (fps: number, dropFrame = isVideoDropFrameRate(fps)): number => {\n\tconst base = Math.round(fps);\n\treturn dropFrame && isVideoDropFrameRate(fps) ? base * 3600 - (base / 15) * 54 : base * 3600;\n};\n\n/** Readable time for messages: `2.50 s`. */\nexport const formatVideoSeconds = (time: number): string => `${(time / 1000).toFixed(2)} s`;\n\n/** Whether an asset carries sound: audio, or video not marked `hasAudio: false`. */\nexport const videoAssetHasSound = (asset: VideoAsset | undefined): boolean => !!asset && (asset.kind === 'audio' || (asset.kind === 'video' && asset.hasAudio !== false));\n\nexport function videoAssetMap(project: VideoProject): Map<string, VideoAsset> {\n\treturn new Map(project.assets.map((a) => [a.id, a]));\n}\n\nexport function videoSequenceMap(project: VideoProject): Map<string, VideoSequence> {\n\treturn new Map((project.sequences ?? []).map((q) => [q.id, q]));\n}\n\n/** A sequence's length: the end of its last clip (ms). */\nexport function videoSequenceDuration(sequence: Pick<VideoSequence, 'tracks'>): number {\n\tlet end = 0;\n\tfor (const track of sequence.tracks) for (const clip of track.clips) end = Math.max(end, videoClipEnd(clip));\n\treturn end;\n}\n\n/** The sequences a sequence's compound clips play directly (ids, in order, without repeats). */\nexport const videoSequenceChildren = (sequence: Pick<VideoSequence, 'tracks'>): string[] => [...new Set(sequence.tracks.flatMap((t) => t.clips.flatMap((c) => (c.type === 'sequence' ? [c.sequence] : []))))];\n\n/**\n * A path of sequence ids that leads from `id` back to itself through compound clips (`[a, b, a]`),\n * or `null` when it contains no cycle. Evaluating and exporting skip a compound that would close\n * one, and `checkVideoProject` reports it.\n */\nexport function findVideoSequenceCycle(project: VideoProject, id: string): string[] | null {\n\tconst sequences = videoSequenceMap(project);\n\tconst walk = (at: string, path: string[]): string[] | null => {\n\t\tconst seq = sequences.get(at);\n\t\tif (!seq) return null;\n\t\tfor (const child of videoSequenceChildren(seq)) {\n\t\t\tif (child === id) return [...path, child];\n\t\t\tif (path.includes(child)) continue;\n\t\t\tconst found = walk(child, [...path, child]);\n\t\t\tif (found) return found;\n\t\t}\n\t\treturn null;\n\t};\n\treturn walk(id, [id]);\n}\n\n/** Every track with its sequence (`undefined` for the project's own), the project's first. */\nexport function allVideoTracks(project: VideoProject): { sequence?: string; track: VideoTrack }[] {\n\treturn [...project.tracks.map((track) => ({ track })), ...(project.sequences ?? []).flatMap((q) => q.tracks.map((track) => ({ sequence: q.id, track })))];\n}\n\n/** A track's clips in timeline order. */\nexport function sortedVideoClips(track: VideoTrack): VideoClip[] {\n\treturn [...track.clips].sort((a, b) => a.start - b.start || a.duration - b.duration);\n}\n\nexport interface VideoClipLocation {\n\ttrack: VideoTrack;\n\ttrackIndex: number;\n\tclip: VideoClip;\n\t/** Index in `track.clips`. */\n\tindex: number;\n}\n\nexport function findVideoClip(project: VideoProject, id: string): VideoClipLocation | null {\n\tfor (let trackIndex = 0; trackIndex < project.tracks.length; trackIndex++) {\n\t\tconst track = project.tracks[trackIndex];\n\t\tconst index = track.clips.findIndex((c) => c.id === id);\n\t\tif (index >= 0) return { track, trackIndex, clip: track.clips[index], index };\n\t}\n\treturn null;\n}\n\n/** Every clip id in the project, its sequences' clips included (ids are unique across them). */\nexport function allVideoClipIds(project: VideoProject): string[] {\n\treturn allVideoTracks(project).flatMap(({ track }) => track.clips.map((c) => c.id));\n}\n\n/** The sequence a clip inside a sequence belongs to, with its track; `null` for clips of the project's own tracks (or no clip). */\nexport function findVideoSequenceClip(project: VideoProject, id: string): { sequence: VideoSequence; track: VideoTrack; clip: VideoClip } | null {\n\tfor (const sequence of project.sequences ?? [])\n\t\tfor (const track of sequence.tracks) {\n\t\t\tconst clip = track.clips.find((c) => c.id === id);\n\t\t\tif (clip) return { sequence, track, clip };\n\t\t}\n\treturn null;\n}\n\n/** Total length: the end of the last clip (ms). */\nexport function videoProjectDuration(project: VideoProject): number {\n\tlet end = 0;\n\tfor (const track of project.tracks) for (const clip of track.clips) end = Math.max(end, videoClipEnd(clip));\n\treturn end;\n}\n\n/** The clip that ends where `clip` starts on its track (a cut), if any. */\nexport function videoClipBefore(track: VideoTrack, clip: VideoClip): VideoClip | null {\n\tlet best: VideoClip | null = null;\n\tfor (const c of track.clips) if (c !== clip && Math.abs(videoClipEnd(c) - clip.start) <= VIDEO_TIME_EPSILON) best = c;\n\treturn best;\n}\n\n/** The clip that starts where `clip` ends on its track (a cut), if any. */\nexport function videoClipAfter(track: VideoTrack, clip: VideoClip): VideoClip | null {\n\tfor (const c of track.clips) if (c !== clip && Math.abs(c.start - videoClipEnd(clip)) <= VIDEO_TIME_EPSILON) return c;\n\treturn null;\n}\n\n/**\n * Timeline time (ms) a clip can run past its edges into source media: before its in point\n * (`before`) and after its out point (`after`). Unlimited for stills, titles, colours and media\n * whose length is unknown. A compound's handles are its sequence's time before `in` and after its\n * out point (pass `sequences`; without them they count as unlimited).\n */\nexport function videoClipHandles(clip: VideoClip, assets: Map<string, VideoAsset>, sequences?: Map<string, VideoSequence>): { before: number; after: number } {\n\tif (clip.type === 'sequence') {\n\t\tconst seq = sequences?.get(clip.sequence);\n\t\tconst range = videoClipSourceRange(clip)!;\n\t\treturn { before: range.in, after: seq ? Math.max(0, videoSequenceDuration(seq) - range.out) : Infinity };\n\t}\n\tif (clip.type !== 'media') return { before: Infinity, after: Infinity };\n\tconst asset = assets.get(clip.asset);\n\tconst speed = videoClipSpeed(clip);\n\tconst range = videoClipSourceRange(clip)!;\n\tconst before = range.in / speed;\n\tif (!asset || asset.kind === 'image' || asset.duration === undefined) return { before: asset?.kind === 'image' ? Infinity : before, after: Infinity };\n\treturn { before, after: Math.max(0, (asset.duration - range.out) / speed) };\n}\n\n/**\n * How far a clip plays past each edge because of transitions: `lead` before its start (its own\n * transition in) and `tail` after its end (the next clip's transition in). Dips need neither.\n */\nexport function videoClipOverhang(track: VideoTrack, clip: VideoClip): { lead: number; tail: number } {\n\t// A dip cuts under its colour, so neither clip plays past the cut.\n\tconst lead = clip.transition && clip.transition.type !== 'dip' && videoClipBefore(track, clip) ? clip.transition.duration / 2 : 0;\n\tconst next = videoClipAfter(track, clip);\n\tconst tail = next?.transition && next.transition.type !== 'dip' ? next.transition.duration / 2 : 0;\n\treturn { lead, tail };\n}\n\nexport interface VideoSnapOptions {\n\t/** Clip ids whose edges are not snap targets (the ones being dragged). */\n\texclude?: Iterable<string>;\n\t/** Also snap to this time (usually the playhead). */\n\tplayhead?: number;\n}\n\n/** Times worth snapping to: 0, every clip edge, every marker and the playhead, ascending. */\nexport function videoSnapPoints(project: VideoProject, options: VideoSnapOptions = {}): number[] {\n\tconst exclude = new Set(options.exclude ?? []);\n\tconst points = new Set<number>([0]);\n\tfor (const track of project.tracks)\n\t\tfor (const clip of track.clips) {\n\t\t\tif (exclude.has(clip.id)) continue;\n\t\t\tpoints.add(clip.start);\n\t\t\tpoints.add(videoClipEnd(clip));\n\t\t}\n\tfor (const marker of project.markers ?? []) points.add(marker.time);\n\tif (options.playhead !== undefined) points.add(options.playhead);\n\treturn [...points].sort((a, b) => a - b);\n}\n\n/** The snap point nearest `time` if it is within `threshold` (ms), else `time`. */\nexport function snapVideoTime(time: number, points: readonly number[], threshold: number): { time: number; snapped: number | null } {\n\tlet best: number | null = null;\n\tfor (const p of points) if (Math.abs(p - time) <= threshold && (best === null || Math.abs(p - time) < Math.abs(best - time))) best = p;\n\treturn best === null ? { time, snapped: null } : { time: best, snapped: best };\n}\n\nexport interface VideoGap {\n\ttrack: string;\n\tstart: number;\n\tend: number;\n}\n\n/** Empty stretches between clips (and before the first) on each track, or one track. */\nexport function findVideoGaps(project: VideoProject, trackId?: string): VideoGap[] {\n\tconst gaps: VideoGap[] = [];\n\tfor (const track of project.tracks) {\n\t\tif (trackId !== undefined && track.id !== trackId) continue;\n\t\tlet at = 0;\n\t\tfor (const clip of sortedVideoClips(track)) {\n\t\t\tif (clip.start - at > VIDEO_TIME_EPSILON) gaps.push({ track: track.id, start: at, end: clip.start });\n\t\t\tat = Math.max(at, videoClipEnd(clip));\n\t\t}\n\t}\n\treturn gaps;\n}\n\n/** The first clip on `track` (other than `ignore`) that overlaps `[start, end)`, if any. */\nexport function videoOverlap(track: VideoTrack, start: number, end: number, ignore: ReadonlySet<string> = new Set()): VideoClip | null {\n\tfor (const c of sortedVideoClips(track)) {\n\t\tif (ignore.has(c.id)) continue;\n\t\tif (c.start < end - VIDEO_TIME_EPSILON && videoClipEnd(c) > start + VIDEO_TIME_EPSILON) return c;\n\t}\n\treturn null;\n}\n\n/** The first free stretch on `track` at or after `from` that fits `duration`. */\nexport function nextFreeVideoSlot(track: VideoTrack, from: number, duration: number, ignore: ReadonlySet<string> = new Set()): number {\n\tlet at = from;\n\tfor (const c of sortedVideoClips(track)) {\n\t\tif (ignore.has(c.id)) continue;\n\t\tif (videoClipEnd(c) <= at + VIDEO_TIME_EPSILON) continue;\n\t\tif (c.start >= at + duration - VIDEO_TIME_EPSILON) break;\n\t\tat = videoClipEnd(c);\n\t}\n\treturn at;\n}\n\n/** Clips under `time` (start inclusive, end exclusive), top track first. */\nexport function videoClipsAt(project: VideoProject, time: number): { track: string; clip: VideoClip }[] {\n\tconst out: { track: string; clip: VideoClip }[] = [];\n\tfor (const track of project.tracks) for (const clip of track.clips) if (time >= clip.start && time < videoClipEnd(clip)) out.push({ track: track.id, clip });\n\treturn out;\n}\n","import { isVideoKeyframes, type VideoAnimatable, type VideoEase, type VideoKey } from './keyframes.js';\nimport type { VideoClip, VideoClipAnimation, VideoClipAnimationEffect, VideoProject, VideoTransform } from './types.js';\n\n/** Default length of an entrance or exit animation (ms). */\nexport const VIDEO_CLIP_ANIMATION_DURATION = 500;\n\ninterface EffectSpec {\n\t/** Offset of the picture at the start of an entrance (end of an exit), as fractions of the frame. */\n\tx?: number;\n\ty?: number;\n\t/** Scale at the start of an entrance, as a factor of the clip's own. */\n\tscale?: number;\n\t/** Eases for an entrance and an exit. */\n\teaseIn: VideoEase;\n\teaseOut: VideoEase;\n}\n\nconst EFFECTS: Record<VideoClipAnimationEffect, EffectSpec> = {\n\tfade: { easeIn: 'linear', easeOut: 'linear' },\n\trise: { y: 0.06, easeIn: 'ease-out', easeOut: 'ease-in' },\n\tdrop: { y: -0.06, easeIn: 'ease-out', easeOut: 'ease-in' },\n\t'slide-left': { x: 0.15, easeIn: 'ease-out', easeOut: 'ease-in' },\n\t'slide-right': { x: -0.15, easeIn: 'ease-out', easeOut: 'ease-in' },\n\tzoom: { scale: 0.6, easeIn: 'ease-out', easeOut: 'ease-in' },\n\t// Overshoots past full size, then settles (a \"back\" curve).\n\tpop: { scale: 0.3, easeIn: [0.34, 1.56, 0.64, 1], easeOut: [0.36, 0, 0.66, -0.56] }\n};\n\nconst PROPS = ['opacity', 'x', 'y', 'scale'] as const;\ntype Prop = (typeof PROPS)[number];\n\n/** The properties an animation moves (each also fades: opacity is always one). */\nexport function videoClipAnimationProperties(animation: VideoClipAnimation): Prop[] {\n\tconst spec = EFFECTS[animation.effect];\n\treturn PROPS.filter((p) => p === 'opacity' || spec[p as 'x' | 'y' | 'scale'] !== undefined);\n}\n\n/** Entrance and exit lengths (ms), shortened in proportion when together they are longer than the clip. */\nexport function videoClipAnimationSpans(clip: VideoClip): { in: number; out: number } {\n\tconst a = clip.animateIn ? (clip.animateIn.duration ?? VIDEO_CLIP_ANIMATION_DURATION) : 0;\n\tconst b = clip.animateOut ? (clip.animateOut.duration ?? VIDEO_CLIP_ANIMATION_DURATION) : 0;\n\tconst k = a + b > clip.duration ? clip.duration / (a + b) : 1;\n\treturn { in: a * k, out: b * k };\n}\n\n/**\n * The clip with its entrance and exit animations written out as keyframes on opacity, x, y and\n * scale, so previews, SVG frames and the ffmpeg export all play them the same way. A property the\n * clip already keys itself is left alone (`checkVideoProject` notes it). Returns the clip unchanged\n * when it has no animations.\n */\nexport function videoClipAnimated(clip: VideoClip, project: Pick<VideoProject, 'width' | 'height'>): VideoClip {\n\tif (!clip.animateIn && !clip.animateOut) return clip;\n\tconst spans = videoClipAnimationSpans(clip);\n\tconst out: VideoClip = { ...clip, transform: { ...clip.transform } };\n\tfor (const prop of PROPS) {\n\t\tconst current: VideoAnimatable | undefined = prop === 'opacity' ? clip.opacity : clip.transform?.[prop];\n\t\tif (isVideoKeyframes(current)) continue;\n\t\tconst base = current ?? (prop === 'opacity' || prop === 'scale' ? 1 : 0);\n\t\tconst away = (spec: EffectSpec): number | undefined => {\n\t\t\tif (prop === 'opacity') return 0;\n\t\t\tconst v = spec[prop];\n\t\t\tif (v === undefined) return undefined;\n\t\t\treturn prop === 'scale' ? base * v : base + v * (prop === 'x' ? project.width : project.height);\n\t\t};\n\t\tconst keys: VideoKey[] = [];\n\t\tif (clip.animateIn) {\n\t\t\tconst spec = EFFECTS[clip.animateIn.effect];\n\t\t\tconst from = away(spec);\n\t\t\tif (from !== undefined) keys.push({ t: 0, v: from, ease: spec.easeIn }, { t: spans.in, v: base });\n\t\t}\n\t\tif (clip.animateOut) {\n\t\t\tconst spec = EFFECTS[clip.animateOut.effect];\n\t\t\tconst to = away(spec);\n\t\t\tif (to !== undefined) {\n\t\t\t\tconst start = clip.duration - spans.out;\n\t\t\t\tif (!keys.length || keys[keys.length - 1].t < start) keys.push({ t: start, v: base, ease: spec.easeOut });\n\t\t\t\telse keys[keys.length - 1] = { ...keys[keys.length - 1], ease: spec.easeOut };\n\t\t\t\tkeys.push({ t: clip.duration, v: to });\n\t\t\t}\n\t\t}\n\t\tif (!keys.length) continue;\n\t\tif (prop === 'opacity') out.opacity = { keys };\n\t\telse (out.transform as VideoTransform)[prop] = { keys };\n\t}\n\treturn out;\n}\n","import { videoClipAnimated } from './clip-animation.js';\nimport { videoClipSourceTime, videoClipSpeedAt } from './remap.js';\nimport { normalizeVideoGrade } from './grade.js';\nimport { videoValueAt } from './keyframes.js';\nimport { sortedVideoClips, videoAssetMap, videoClipAfter, videoClipBefore, videoClipEnd, videoClipSpeed, videoAssetHasSound, videoSequenceMap } from './timeline.js';\nimport { videoTransitionAudioCurve } from './types.js';\nimport type { VideoAsset, VideoBlendMode, VideoGrade, VideoClip, VideoFadeCurve, VideoFit, VideoProject, VideoSequence, VideoTransition, VideoTextClip, VideoTrack, VideoWipeDirection } from './types.js';\n\n/** A rectangle in frame pixels. */\nexport interface VideoRect {\n\tx: number;\n\ty: number;\n\twidth: number;\n\theight: number;\n}\n\n/** One picture in a frame, in draw order (first is at the back). */\nexport interface VideoLayer {\n\t/**\n\t * The clip it comes from, or `transition:<clip>` for a dip's colour. Inside a compound clip it is\n\t * the path of clip ids from the project's own track (`compound/inner`), so the same sequence\n\t * played twice gives distinct layers.\n\t */\n\tclip: string;\n\t/** The track it is on (inside a compound: the sequence's track). */\n\ttrack: string;\n\ttype: VideoClip['type'];\n\t/** For media: the asset, its kind and `src`, and the moment of the source to show (ms). */\n\tasset?: string;\n\tassetKind?: VideoAsset['kind'];\n\tsrc?: string;\n\t/** For media: the moment of the source to show (ms); for a compound: the moment of its sequence. */\n\tsourceTime?: number;\n\t/** For a compound: the sequence it plays. */\n\tsequence?: string;\n\t/**\n\t * For a compound: the sequence's frame at `sourceTime`, back to front in the sequence's own frame\n\t * (the project's size, transparent where nothing covers it). They are drawn together as one\n\t * picture, which this layer's rect, rotation, opacity, blend, grade, wipe and iris then apply to.\n\t */\n\tlayers?: VideoLayer[];\n\t/** 0–1, after fades and transitions. */\n\topacity: number;\n\t/** Where the fitted picture sits before rotation (its centre is the rotation centre). */\n\trect: VideoRect;\n\t/** Degrees clockwise about the rect's centre. */\n\trotation: number;\n\t/** For a wipe: the part shown is the `progress` (0–1) of the rect from the edge opposite `direction`. */\n\twipe?: { direction: VideoWipeDirection; progress: number };\n\t/** For an iris: only a circle on the frame's centre shows, its radius `progress` (0–1) of the way to the frame's corners. */\n\tiris?: { progress: number };\n\t/** For text: what to draw. */\n\ttext?: { text: string; color: string; fontSize: number; fontFamily: string; fontWeight: number; background?: string };\n\t/** For colour clips and dips. */\n\tcolor?: string;\n\t/** How it mixes with the layers beneath (absent = normal). */\n\tblend?: VideoBlendMode;\n\t/** Colour correction (absent = none). */\n\tgrade?: VideoGrade;\n}\n\n/** One sound playing at a moment. */\nexport interface VideoAudioSource {\n\t/** The clip it comes from (inside a compound: the path of clip ids, `compound/inner`). */\n\tclip: string;\n\t/** The track it is on (inside a compound: the sequence's track). */\n\ttrack: string;\n\tasset: string;\n\tsrc: string;\n\t/** The moment of the source playing (ms). */\n\tsourceTime: number;\n\t/** Gain after clip and track volume, fades and transitions, and those of any compound it plays in (0 = silent). */\n\tgain: number;\n\tspeed: number;\n}\n\nexport interface VideoFrame {\n\ttime: number;\n\twidth: number;\n\theight: number;\n\tbackground: string;\n\tlayers: VideoLayer[];\n\taudio: VideoAudioSource[];\n}\n\n/** A transform's values at clip-relative time `clipTime` (ms), keyframes resolved and defaults filled in. */\nexport function videoTransformAt(transform: VideoClip['transform'], clipTime = 0): { x: number; y: number; scale: number; rotation: number } {\n\treturn { x: videoValueAt(transform?.x, clipTime, 0), y: videoValueAt(transform?.y, clipTime, 0), scale: videoValueAt(transform?.scale, clipTime, 1), rotation: videoValueAt(transform?.rotation, clipTime, 0) };\n}\n\n/** Places a picture of `size` in the frame by `fit`, then the clip's transform at clip-relative `clipTime` (ms). */\nexport function placeVideoRect(frame: { width: number; height: number }, size: { width: number; height: number }, fit: VideoFit = 'contain', transform: VideoClip['transform'] = {}, clipTime = 0): VideoRect {\n\tlet w = size.width;\n\tlet h = size.height;\n\tif (fit === 'fill') {\n\t\tw = frame.width;\n\t\th = frame.height;\n\t} else if (fit !== 'none') {\n\t\tconst k = fit === 'cover' ? Math.max(frame.width / w, frame.height / h) : Math.min(frame.width / w, frame.height / h);\n\t\tw *= k;\n\t\th *= k;\n\t}\n\tconst t = videoTransformAt(transform, clipTime);\n\tw *= t.scale;\n\th *= t.scale;\n\tconst cx = frame.width / 2 + t.x;\n\tconst cy = frame.height / 2 + t.y;\n\treturn { x: cx - w / 2, y: cy - h / 2, width: w, height: h };\n}\n\n/** A title's text and style with the defaults filled in. */\nexport function videoTextStyle(clip: VideoTextClip): NonNullable<VideoLayer['text']> {\n\treturn { text: clip.text, color: clip.color ?? '#ffffff', fontSize: clip.fontSize ?? 64, fontFamily: clip.fontFamily ?? 'sans-serif', fontWeight: clip.fontWeight ?? 700, ...(clip.background ? { background: clip.background } : {}) };\n}\n\n/**\n * A frame holding only one title, fully opaque on a transparent background, placed as the preview\n * places it: draw it with `drawVideoFrame` and save the canvas as a PNG to give the ffmpeg export\n * titles without `drawtext` (`VideoFfmpegOptions.titleImage`). Fades and opacity are left to the export.\n * A keyframed transform is placed as it is at `clipTime` (the export passes titles with keyframed\n * transforms without them, and moves the image itself).\n */\nexport function videoTitleFrame(project: VideoProject, clip: VideoTextClip, clipTime = 0): VideoFrame {\n\tconst layer: VideoLayer = { clip: clip.id, track: '', type: 'text', opacity: 1, rect: placeVideoRect(project, project, 'fill', clip.transform, clipTime), rotation: videoTransformAt(clip.transform, clipTime).rotation, text: videoTextStyle(clip) };\n\treturn { time: clip.start, width: project.width, height: project.height, background: 'rgba(0,0,0,0)', layers: [layer], audio: [] };\n}\n\nconst clamp01 = (v: number) => Math.min(1, Math.max(0, v));\n\n/** How far a push or slide has moved at `progress` (0–1): eased in and out, (1 − cos πp) / 2. */\nexport const videoTransitionEase = (progress: number): number => (1 - Math.cos(Math.PI * clamp01(progress))) / 2;\n\n/** Gain of a fade shape `x` of the way up (0–1); a fade out uses the time left, so it mirrors the fade in. */\nexport function videoFadeCurveGain(curve: VideoFadeCurve | undefined, x: number): number {\n\tconst t = clamp01(x);\n\tswitch (curve) {\n\t\tcase 'equal-power':\n\t\t\treturn Math.sin((t * Math.PI) / 2);\n\t\tcase 's-curve':\n\t\t\treturn (1 - Math.cos(t * Math.PI)) / 2;\n\t\tcase 'exponential':\n\t\t\treturn t * t * t;\n\t\tcase 'logarithmic':\n\t\t\treturn 1 - (1 - t) * (1 - t);\n\t\tdefault:\n\t\t\treturn t;\n\t}\n}\n\n/** Fade-in / fade-out multiplier for a clip at timeline `time`: linear for pictures, shaped for sound. */\nfunction fadeGain(clip: VideoClip, time: number, sound = false): number {\n\tlet g = 1;\n\tconst shape = sound && (clip.type === 'media' || clip.type === 'sequence') ? clip : undefined;\n\tif (clip.fadeIn) g *= videoFadeCurveGain(shape?.fadeInCurve, (time - clip.start) / clip.fadeIn);\n\tif (clip.fadeOut) g *= videoFadeCurveGain(shape?.fadeOutCurve, (videoClipEnd(clip) - time) / clip.fadeOut);\n\treturn g;\n}\n\n/**\n * A media or compound clip's own gain at clip time `clipTime` (ms): its volume (or volume keyframes) times its\n * shaped fades. Leaves out track volume and transitions, which depend on the timeline around it.\n */\nexport function videoClipSoundGain(clip: VideoClip, clipTime: number): number {\n\tconst volume = clip.type === 'media' || clip.type === 'sequence' ? videoValueAt(clip.volume, clipTime, 1) : 1;\n\treturn volume * fadeGain(clip, clip.start + Math.min(Math.max(clipTime, 0), clip.duration), true);\n}\n\ninterface Active {\n\tclip: VideoClip;\n\t/** 0–1 mix through a transition (1 = fully this clip); undefined outside one. */\n\tincoming?: { progress: number; type: NonNullable<VideoClip['transition']>['type']; transition: NonNullable<VideoClip['transition']> };\n\toutgoing?: { progress: number; type: NonNullable<VideoClip['transition']>['type']; next: VideoClip };\n}\n\n/** The clips of a track playing at `time`, with any transition they are in (outgoing first). */\nfunction activeOnTrack(track: VideoTrack, time: number): Active[] {\n\tconst out: Active[] = [];\n\tfor (const clip of sortedVideoClips(track)) {\n\t\tconst before = clip.transition ? videoClipBefore(track, clip) : null;\n\t\tconst lead = before ? clip.transition!.duration / 2 : 0;\n\t\tconst next = videoClipAfter(track, clip);\n\t\tconst tail = next?.transition ? next.transition.duration / 2 : 0;\n\t\tif (time < clip.start - lead || time >= videoClipEnd(clip) + tail) continue;\n\t\tconst a: Active = { clip };\n\t\tif (lead && time < clip.start + lead) a.incoming = { progress: clamp01((time - (clip.start - lead)) / (2 * lead)), type: clip.transition!.type, transition: clip.transition! };\n\t\tif (tail && time >= videoClipEnd(clip) - tail) a.outgoing = { progress: clamp01((time - (videoClipEnd(clip) - tail)) / (2 * tail)), type: next!.transition!.type, next: next! };\n\t\tout.push(a);\n\t}\n\treturn out;\n}\n\nconst sourceTimeAt = (clip: VideoClip, time: number) => (clip.type === 'media' ? videoClipSourceTime(clip, time - clip.start) : 0);\n\n/**\n * What plays at `time` (ms): the pictures to draw, back to front, with their placement, opacity\n * and the moment of source each shows, and the sounds with their gain. A pure function of the\n * project and the time, so previews, exporters and agents all agree on every frame. A compound\n * clip is one layer holding its sequence's frame (`layers`), and its sounds are mixed in with the\n * compound's volume, fades and transitions.\n */\nexport function videoFrameAt(project: VideoProject, time: number): VideoFrame {\n\tconst { layers, audio } = tracksAt(project, project.tracks, time, { assets: videoAssetMap(project), sequences: videoSequenceMap(project), within: [], prefix: '' });\n\treturn { time, width: project.width, height: project.height, background: project.background ?? '#000000', layers, audio };\n}\n\ninterface Scope {\n\tassets: Map<string, VideoAsset>;\n\tsequences: Map<string, VideoSequence>;\n\t/** The sequences being evaluated around this one, outermost first (a compound of one of them would loop). */\n\twithin: string[];\n\t/** Prepended to clip ids: the compound clips around, `a/b/`. */\n\tprefix: string;\n}\n\n/** The layers and sounds of `tracks` at `time` (in their own timeline). */\nfunction tracksAt(project: VideoProject, tracks: readonly VideoTrack[], time: number, scope: Scope): { layers: VideoLayer[]; audio: VideoAudioSource[] } {\n\tconst { assets, prefix } = scope;\n\tconst layers: VideoLayer[] = [];\n\tconst audio: VideoAudioSource[] = [];\n\t// Later tracks are further back, so draw from the last track to the first.\n\tfor (let ti = tracks.length - 1; ti >= 0; ti--) {\n\t\tconst track = tracks[ti];\n\t\tfor (const { clip, incoming, outgoing } of activeOnTrack(track, time)) {\n\t\t\t// A dip plays the outgoing clip down into its colour and this one up out of it, so neither\n\t\t\t// runs past the cut (and needs no handles).\n\t\t\tif (incoming?.type === 'dip' && incoming.progress < 0.5) continue;\n\t\t\tif (outgoing?.type === 'dip' && outgoing.progress >= 0.5) continue;\n\t\t\tconst inside = Math.min(Math.max(time, clip.start), videoClipEnd(clip));\n\t\t\tconst fade = fadeGain(clip, inside);\n\t\t\tconst level = (t: { type: string; progress: number }, transition: VideoTransition, into: boolean) =>\n\t\t\t\tvideoFadeCurveGain(videoTransitionAudioCurve(transition), t.type === 'dip' ? Math.abs(1 - 2 * t.progress) : into ? t.progress : 1 - t.progress);\n\t\t\t// Sound crossfades through a crossfade or wipe (equal power by default), and dips with the picture.\n\t\t\tconst mix = (incoming ? level(incoming, incoming.transition, true) : 1) * (outgoing ? level(outgoing, outgoing.next.transition!, false) : 1);\n\t\t\tconst asset = clip.type === 'media' ? assets.get(clip.asset) : undefined;\n\t\t\tconst sourceTime = clip.type === 'sequence' ? (clip.in ?? 0) + time - clip.start : sourceTimeAt(clip, time);\n\t\t\t// Keyframes are in clip time, held before the first key and after the last.\n\t\t\tconst clipTime = time - clip.start;\n\t\t\tlet nested: { layers: VideoLayer[]; audio: VideoAudioSource[] } | null = null;\n\t\t\tif (clip.type === 'sequence') {\n\t\t\t\tconst seq = scope.sequences.get(clip.sequence);\n\t\t\t\t// A missing sequence, or one that would contain itself, plays nothing (checkVideoProject reports both).\n\t\t\t\tif (!seq || scope.within.includes(seq.id)) continue;\n\t\t\t\tnested = tracksAt(project, seq.tracks, sourceTime, { ...scope, within: [...scope.within, seq.id], prefix: `${prefix}${clip.id}/` });\n\t\t\t}\n\t\t\tconst audible = videoAssetHasSound(asset);\n\t\t\tif (audible && clip.type === 'media' && !clip.muted && !track.muted) {\n\t\t\t\tconst gain = videoValueAt(clip.volume, clipTime, 1) * (track.volume ?? 1) * fadeGain(clip, inside, true) * mix;\n\t\t\t\taudio.push({ clip: prefix + clip.id, track: track.id, asset: asset!.id, src: asset!.src, sourceTime, gain, speed: videoClipSpeedAt(clip, clipTime) });\n\t\t\t}\n\t\t\tif (nested && clip.type === 'sequence' && !clip.muted && !track.muted) {\n\t\t\t\tconst gain = videoValueAt(clip.volume, clipTime, 1) * (track.volume ?? 1) * fadeGain(clip, inside, true) * mix;\n\t\t\t\tfor (const a of nested.audio) audio.push({ ...a, gain: a.gain * gain });\n\t\t\t}\n\t\t\tif (track.kind !== 'video' || track.hidden) continue;\n\t\t\tif (clip.type === 'media' && (!asset || asset.kind === 'audio')) continue;\n\t\t\tif (nested && !nested.layers.length) continue;\n\t\t\t// Entrance and exit animations are keyframes on the picture's opacity and transform.\n\t\t\tconst shown = videoClipAnimated(clip, project);\n\t\t\tlet opacity = videoValueAt(shown.opacity, clipTime, 1) * fade;\n\t\t\tlet wipe: VideoLayer['wipe'];\n\t\t\tlet dip: { color: string; opacity: number } | null = null;\n\t\t\tlet iris: VideoLayer['iris'];\n\t\t\t// Push and slide move whole pictures by a frame, eased in and out.\n\t\t\tlet shift = 0;\n\t\t\tlet shiftDirection: VideoWipeDirection = 'right';\n\t\t\tif (incoming) {\n\t\t\t\tif (incoming.type === 'crossfade') opacity *= incoming.progress;\n\t\t\t\telse if (incoming.type === 'wipe') wipe = { direction: incoming.transition.direction ?? 'right', progress: incoming.progress };\n\t\t\t\telse if (incoming.type === 'iris') iris = { progress: incoming.progress };\n\t\t\t\telse if (incoming.type === 'push' || incoming.type === 'slide') {\n\t\t\t\t\tshiftDirection = incoming.transition.direction ?? 'right';\n\t\t\t\t\tshift = videoTransitionEase(incoming.progress) - 1;\n\t\t\t\t} else dip = { color: incoming.transition.color ?? '#000000', opacity: (1 - incoming.progress) * 2 };\n\t\t\t}\n\t\t\tif (outgoing?.type === 'dip') dip = { color: outgoing.next.transition!.color ?? '#000000', opacity: outgoing.progress * 2 };\n\t\t\tif (outgoing?.type === 'push') {\n\t\t\t\tshiftDirection = outgoing.next.transition!.direction ?? 'right';\n\t\t\t\tshift = videoTransitionEase(outgoing.progress);\n\t\t\t}\n\t\t\t// A compound's picture is its sequence's whole frame, the project's size.\n\t\t\tconst size = clip.type === 'media' ? { width: asset!.width ?? project.width, height: asset!.height ?? project.height } : { width: project.width, height: project.height };\n\t\t\tconst fit = clip.fit ?? (clip.type === 'media' || clip.type === 'sequence' ? 'contain' : 'fill');\n\t\t\tconst placed = placeVideoRect(project, size, clip.type === 'text' ? 'fill' : fit, shown.transform, clipTime);\n\t\t\tconst across = shiftDirection === 'left' || shiftDirection === 'right';\n\t\t\tconst sign = shiftDirection === 'left' || shiftDirection === 'up' ? -1 : 1;\n\t\t\tconst rect = shift ? { ...placed, ...(across ? { x: placed.x + sign * shift * project.width } : { y: placed.y + sign * shift * project.height }) } : placed;\n\t\t\tconst layer: VideoLayer = { clip: prefix + clip.id, track: track.id, type: clip.type, opacity: clamp01(opacity), rect, rotation: videoValueAt(shown.transform?.rotation, clipTime, 0) };\n\t\t\tif (wipe) layer.wipe = wipe;\n\t\t\tif (iris) layer.iris = iris;\n\t\t\tif (clip.blend && clip.blend !== 'normal') layer.blend = clip.blend;\n\t\t\tconst grade = normalizeVideoGrade(clip.grade);\n\t\t\tif (grade) layer.grade = grade;\n\t\t\tif (clip.type === 'media') Object.assign(layer, { asset: asset!.id, assetKind: asset!.kind, src: asset!.src, sourceTime });\n\t\t\tif (clip.type === 'sequence') Object.assign(layer, { sequence: clip.sequence, sourceTime, layers: nested!.layers });\n\t\t\tif (clip.type === 'text') layer.text = videoTextStyle(clip);\n\t\t\tif (clip.type === 'color') layer.color = clip.color;\n\t\t\tif (layer.opacity > 0) layers.push(layer);\n\t\t\tif (dip && dip.opacity > 0) layers.push({ clip: `transition:${prefix}${incoming ? clip.id : outgoing!.next.id}`, track: track.id, type: 'color', color: dip.color, opacity: clamp01(dip.opacity), rect: { x: 0, y: 0, width: project.width, height: project.height }, rotation: 0 });\n\t\t}\n\t}\n\treturn { layers, audio };\n}\n\n/**\n * Every layer of a frame that draws a picture of its own, compounds opened up (each compound's\n * layers in place of it), back to front. Hosts use it to find the media a frame needs.\n */\nexport function videoFrameLeafLayers(layers: readonly VideoLayer[]): VideoLayer[] {\n\treturn layers.flatMap((l) => (l.layers ? videoFrameLeafLayers(l.layers) : [l]));\n}\n","import { videoFrameAt, type VideoFrame, type VideoLayer, type VideoRect } from './evaluate.js';\nimport { videoGradeCssFilter, videoGradeSvgDefs, videoGradeSvgFilter } from './grade.js';\nimport { applyVideoLutToPixels, type VideoLut } from './lut.js';\nimport { formatVideoTimecode } from './timeline.js';\nimport type { VideoProject } from './types.js';\n\nconst esc = (s: string) => s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\nconst n = (v: number) => String(Math.round(v * 100) / 100);\nconst n4 = (v: number) => String(Math.round(v * 10000) / 10000);\n\n/** Radius of an iris `progress` (0–1) open: from nothing to the frame's corners. */\nexport const videoIrisRadius = (frame: { width: number; height: number }, progress: number): number => progress * Math.hypot(frame.width / 2, frame.height / 2);\n\n/** The part of a rect a wipe shows. */\nexport function videoWipeRect(rect: VideoRect, wipe: NonNullable<VideoLayer['wipe']>): VideoRect {\n\tconst { direction, progress } = wipe;\n\tconst w = rect.width * progress;\n\tconst h = rect.height * progress;\n\tif (direction === 'right') return { ...rect, width: w };\n\tif (direction === 'left') return { ...rect, x: rect.x + rect.width - w, width: w };\n\tif (direction === 'down') return { ...rect, height: h };\n\treturn { ...rect, y: rect.y + rect.height - h, height: h };\n}\n\nexport interface VideoSvgOptions {\n\t/**\n\t * The picture for a media layer: return an href (URL or data URL) to draw, or `null` for a\n\t * labelled placeholder. Default: images use `src`, videos their `poster`, else a placeholder.\n\t */\n\timageFor?: (layer: VideoLayer, frame: VideoFrame) => string | null;\n\t/** Frame rate for the timecode on placeholders (default 30). */\n\tfps?: number;\n\t/** The loaded table of a grade's LUT `src`; drawn as an approximation (curves and a matrix). Without it LUTs are left out. */\n\tlutFor?: (src: string) => VideoLut | null | undefined;\n}\n\n/**\n * A frame as standalone SVG: images and posters as `<image>`, video without one as a labelled box.\n * A compound clip is a `<g>` (isolated, so blends inside it mix only with its own layers) holding\n * its sequence's layers scaled into its rect, with its opacity, blend, grade filter and clips on it.\n */\nexport function videoFrameToSvg(frame: VideoFrame, options: VideoSvgOptions = {}, assets: VideoProject['assets'] = []): string {\n\tconst defs: string[] = [];\n\tconst posters = new Map(assets.map((a) => [a.id, a.poster]));\n\tconst draw = (layers: readonly VideoLayer[], prefix: string): string =>\n\t\tlayers\n\t\t\t.map((layer, index) => {\n\t\t\t\tconst i = `${prefix}${index}`;\n\t\t\t\tconst { rect } = layer;\n\t\t\t\tconst attrs: string[] = [];\n\t\t\t\tconst style: string[] = [];\n\t\t\t\tif (layer.opacity < 1) attrs.push(`opacity=\"${n(layer.opacity)}\"`);\n\t\t\t\tif (layer.blend) style.push(`mix-blend-mode:${layer.blend === 'add' ? 'plus-lighter' : layer.blend}`);\n\t\t\t\tif (layer.layers) style.push('isolation:isolate');\n\t\t\t\tif (style.length) attrs.push(`style=\"${style.join(';')}\"`);\n\t\t\t\tif (layer.grade) {\n\t\t\t\t\tdefs.push(videoGradeSvgFilter(`g${i}`, layer.grade, layer.grade.lut ? options.lutFor?.(layer.grade.lut.src) : null));\n\t\t\t\t\tattrs.push(`filter=\"url(#g${i})\"`);\n\t\t\t\t}\n\t\t\t\tif (layer.rotation) attrs.push(`transform=\"rotate(${n(layer.rotation)} ${n(rect.x + rect.width / 2)} ${n(rect.y + rect.height / 2)})\"`);\n\t\t\t\tif (layer.wipe) {\n\t\t\t\t\tconst r = videoWipeRect(rect, layer.wipe);\n\t\t\t\t\tdefs.push(`<clipPath id=\"w${i}\"><rect x=\"${n(r.x)}\" y=\"${n(r.y)}\" width=\"${n(r.width)}\" height=\"${n(r.height)}\"/></clipPath>`);\n\t\t\t\t\tattrs.push(`clip-path=\"url(#w${i})\"`);\n\t\t\t\t}\n\t\t\t\tconst box = `x=\"${n(rect.x)}\" y=\"${n(rect.y)}\" width=\"${n(rect.width)}\" height=\"${n(rect.height)}\"`;\n\t\t\t\tlet inner = '';\n\t\t\t\tif (layer.layers) {\n\t\t\t\t\t// The sequence's frame is the project's size: scale it into the compound's rect.\n\t\t\t\t\tinner = `<g transform=\"translate(${n(rect.x)} ${n(rect.y)}) scale(${n4(rect.width / frame.width)} ${n4(rect.height / frame.height)})\">${draw(layer.layers, `${i}-`)}</g>`;\n\t\t\t\t} else if (layer.type === 'color') inner = `<rect ${box} fill=\"${esc(layer.color ?? '#000000')}\"/>`;\n\t\t\t\telse if (layer.type === 'text' && layer.text) {\n\t\t\t\t\tconst t = layer.text;\n\t\t\t\t\tconst lines = t.text.split('\\n');\n\t\t\t\t\tconst lh = t.fontSize * 1.2;\n\t\t\t\t\tconst cx = rect.x + rect.width / 2;\n\t\t\t\t\tconst cy = rect.y + rect.height / 2;\n\t\t\t\t\tconst top = cy - (lh * (lines.length - 1)) / 2;\n\t\t\t\t\tif (t.background) {\n\t\t\t\t\t\tconst w = Math.max(...lines.map((l) => l.length)) * t.fontSize * 0.6 + t.fontSize;\n\t\t\t\t\t\tconst h = lh * lines.length + t.fontSize * 0.4;\n\t\t\t\t\t\tinner += `<rect x=\"${n(cx - w / 2)}\" y=\"${n(cy - h / 2)}\" width=\"${n(w)}\" height=\"${n(h)}\" fill=\"${esc(t.background)}\"/>`;\n\t\t\t\t\t}\n\t\t\t\t\tinner += `<text x=\"${n(cx)}\" text-anchor=\"middle\" dominant-baseline=\"central\" font-family=\"${esc(t.fontFamily)}\" font-size=\"${n(t.fontSize)}\" font-weight=\"${t.fontWeight}\" fill=\"${esc(t.color)}\">${lines.map((l, k) => `<tspan x=\"${n(cx)}\" y=\"${n(top + k * lh)}\">${esc(l)}</tspan>`).join('')}</text>`;\n\t\t\t\t} else {\n\t\t\t\t\tconst href = options.imageFor ? options.imageFor(layer, frame) : layer.assetKind === 'image' ? (layer.src ?? null) : (posters.get(layer.asset ?? '') ?? null);\n\t\t\t\t\tif (href) inner = `<image href=\"${esc(href)}\" ${box} preserveAspectRatio=\"none\"/>`;\n\t\t\t\t\telse {\n\t\t\t\t\t\tconst label = `${layer.asset ?? layer.clip} · ${formatVideoTimecode(layer.sourceTime ?? 0, options.fps ?? 30)}`;\n\t\t\t\t\t\tconst size = Math.max(10, Math.min(rect.height / 8, rect.width / Math.max(8, label.length * 0.6)));\n\t\t\t\t\t\tinner = `<rect ${box} fill=\"#334155\" stroke=\"#94a3b8\" stroke-width=\"2\"/><text x=\"${n(rect.x + rect.width / 2)}\" y=\"${n(rect.y + rect.height / 2)}\" text-anchor=\"middle\" dominant-baseline=\"central\" font-family=\"sans-serif\" font-size=\"${n(size)}\" fill=\"#e2e8f0\">${esc(label)}</text>`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlet item = attrs.length ? `<g ${attrs.join(' ')}>${inner}</g>` : inner;\n\t\t\t\tif (layer.iris) {\n\t\t\t\t\t// Outside the layer's own transform, so the circle stays on the frame's centre.\n\t\t\t\t\tdefs.push(`<clipPath id=\"i${i}\"><circle cx=\"${n(frame.width / 2)}\" cy=\"${n(frame.height / 2)}\" r=\"${n(videoIrisRadius(frame, layer.iris.progress))}\"/></clipPath>`);\n\t\t\t\t\titem = `<g clip-path=\"url(#i${i})\">${item}</g>`;\n\t\t\t\t}\n\t\t\t\treturn item;\n\t\t\t})\n\t\t\t.join('');\n\tconst body = draw(frame.layers, '');\n\treturn `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${n(frame.width)} ${n(frame.height)}\" width=\"${n(frame.width)}\" height=\"${n(frame.height)}\">${defs.length ? `<defs>${defs.join('')}</defs>` : ''}<rect width=\"100%\" height=\"100%\" fill=\"${esc(frame.background)}\"/>${body}</svg>`;\n}\n\n/** The project at `time` as SVG. */\nexport function videoProjectSvg(project: VideoProject, time: number, options: VideoSvgOptions = {}): string {\n\treturn videoFrameToSvg(videoFrameAt(project, time), { fps: project.fps, ...options }, project.assets);\n}\n\n/** Several moments in one labelled picture, `columns` a row, each frame scaled to `width` pixels. */\nexport function videoContactSheetSvg(project: VideoProject, times: readonly number[], options: VideoSvgOptions & { columns?: number; width?: number } = {}): string {\n\tconst columns = options.columns ?? Math.ceil(Math.sqrt(times.length));\n\tconst w = options.width ?? 320;\n\tconst h = (w * project.height) / project.width;\n\tconst label = 18;\n\tconst gap = 8;\n\tconst rows = Math.ceil(times.length / columns);\n\tconst W = columns * w + (columns + 1) * gap;\n\tconst H = rows * (h + label) + (rows + 1) * gap;\n\tconst cells = times.map((t, i) => {\n\t\tconst x = gap + (i % columns) * (w + gap);\n\t\tconst y = gap + Math.floor(i / columns) * (h + label + gap);\n\t\tconst svg = videoProjectSvg(project, t, options).replace(/^<svg xmlns=\"http:\\/\\/www.w3.org\\/2000\\/svg\"/, `<svg x=\"${n(x)}\" y=\"${n(y)}\" width=\"${n(w)}\" height=\"${n(h)}\"`).replace(/ width=\"[\\d.]+\" height=\"[\\d.]+\">/, '>');\n\t\treturn `${svg}<text x=\"${n(x)}\" y=\"${n(y + h + 14)}\" font-family=\"sans-serif\" font-size=\"12\" fill=\"#0f172a\">${(t / 1000).toFixed(2)} s · ${formatVideoTimecode(t, project.fps)}</text>`;\n\t});\n\treturn `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${n(W)} ${n(H)}\" width=\"${n(W)}\" height=\"${n(H)}\"><rect width=\"100%\" height=\"100%\" fill=\"#f8fafc\"/>${cells.join('')}</svg>`;\n}\n\n/** The subset of `CanvasRenderingContext2D` `drawVideoFrame` uses (so tests and workers can pass their own). */\nexport type VideoCanvasContext = Pick<\n\tCanvasRenderingContext2D,\n\t'save' | 'restore' | 'fillRect' | 'drawImage' | 'translate' | 'rotate' | 'beginPath' | 'rect' | 'arc' | 'clip' | 'fillText' | 'measureText' | 'setTransform'\n> & { globalAlpha: number; globalCompositeOperation: GlobalCompositeOperation; filter?: string; fillStyle: string | CanvasGradient | CanvasPattern; font: string; textAlign: CanvasTextAlign; textBaseline: CanvasTextBaseline; strokeStyle: string | CanvasGradient | CanvasPattern; lineWidth: number; strokeRect(x: number, y: number, w: number, h: number): void };\n\n/**\n * An offscreen canvas `drawVideoFrame` draws on: a compound clip's layers before laying them on the\n * frame as one picture, or a LUT-graded layer before running its pixels through the LUT.\n */\nexport interface VideoScratchCanvas {\n\tcanvas: CanvasImageSource;\n\tctx: VideoCanvasContext & Pick<CanvasRenderingContext2D, 'getImageData' | 'putImageData' | 'clearRect'>;\n}\n\nexport interface VideoDrawOptions {\n\t/** Puts an SVG filter (white balance) in the page, so the canvas's `filter: url(#id)` finds it. */\n\tdefineSvgFilter?: (id: string, markup: string) => void;\n\t/** The loaded table of a grade's LUT `src`, or nothing while it loads (the layer is drawn without it). */\n\tlutFor?: (src: string) => VideoLut | null | undefined;\n\t/**\n\t * An offscreen canvas of the given canvas-pixel size, for compound clips and LUT layers; `slot`\n\t * numbers the ones in use at once (a compound inside a compound needs its own), so return the\n\t * same canvas for the same slot and a different one for each slot. Without it LUTs are left out\n\t * and a compound's layers are drawn straight onto the frame, without its opacity, blend and grade.\n\t */\n\tscratch?: (width: number, height: number, slot: number) => VideoScratchCanvas | null;\n}\n\n/** Draws one layer's picture (clip shapes, grade filter, rotation and content), without its opacity or blend. */\nfunction paintVideoLayer(ctx: VideoCanvasContext, frame: VideoFrame, layer: VideoLayer, sourceFor: (layer: VideoLayer) => CanvasImageSource | null, options: VideoDrawOptions) {\n\tconst { rect } = layer;\n\tif (layer.iris) {\n\t\tctx.beginPath();\n\t\tctx.arc(frame.width / 2, frame.height / 2, videoIrisRadius(frame, layer.iris.progress), 0, 2 * Math.PI);\n\t\tctx.clip();\n\t}\n\tif (layer.grade) {\n\t\tconst defs = videoGradeSvgDefs(layer.grade);\n\t\tif (options.defineSvgFilter) for (const d of defs) options.defineSvgFilter(d.id, d.markup);\n\t\tconst css = videoGradeCssFilter(layer.grade);\n\t\tctx.filter = options.defineSvgFilter ? css || 'none' : css.replace(/\\s*url\\([^)]*\\)/g, '').trim() || 'none';\n\t}\n\tif (layer.rotation) {\n\t\tctx.translate(rect.x + rect.width / 2, rect.y + rect.height / 2);\n\t\tctx.rotate((layer.rotation * Math.PI) / 180);\n\t\tctx.translate(-(rect.x + rect.width / 2), -(rect.y + rect.height / 2));\n\t}\n\tif (layer.wipe) {\n\t\tconst r = videoWipeRect(rect, layer.wipe);\n\t\tctx.beginPath();\n\t\tctx.rect(r.x, r.y, r.width, r.height);\n\t\tctx.clip();\n\t}\n\tif (layer.type === 'color') {\n\t\tctx.fillStyle = layer.color ?? '#000000';\n\t\tctx.fillRect(rect.x, rect.y, rect.width, rect.height);\n\t} else if (layer.type === 'text' && layer.text) {\n\t\tconst t = layer.text;\n\t\tconst lines = t.text.split('\\n');\n\t\tconst lh = t.fontSize * 1.2;\n\t\tconst cx = rect.x + rect.width / 2;\n\t\tconst top = rect.y + rect.height / 2 - (lh * (lines.length - 1)) / 2;\n\t\tctx.font = `${t.fontWeight} ${t.fontSize}px ${t.fontFamily}`;\n\t\tctx.textAlign = 'center';\n\t\tctx.textBaseline = 'middle';\n\t\tif (t.background) {\n\t\t\tconst w = Math.max(...lines.map((l) => ctx.measureText(l).width)) + t.fontSize;\n\t\t\tconst h = lh * lines.length + t.fontSize * 0.4;\n\t\t\tctx.fillStyle = t.background;\n\t\t\tctx.fillRect(cx - w / 2, rect.y + rect.height / 2 - h / 2, w, h);\n\t\t}\n\t\tctx.fillStyle = t.color;\n\t\tlines.forEach((l, k) => ctx.fillText(l, cx, top + k * lh));\n\t} else {\n\t\tconst source = sourceFor(layer);\n\t\tif (source) ctx.drawImage(source, rect.x, rect.y, rect.width, rect.height);\n\t\telse {\n\t\t\tctx.fillStyle = '#334155';\n\t\t\tctx.fillRect(rect.x, rect.y, rect.width, rect.height);\n\t\t\tctx.strokeStyle = '#94a3b8';\n\t\t\tctx.lineWidth = 2;\n\t\t\tctx.strokeRect(rect.x, rect.y, rect.width, rect.height);\n\t\t}\n\t}\n}\n\n/**\n * Draws a frame on a 2D canvas scaled by `scale` (canvas pixels per frame pixel). `sourceFor`\n * returns what to draw for a media layer (a `<video>` seeked to `layer.sourceTime`, an `<img>`,\n * an `ImageBitmap`…) or `null` for a placeholder box. Grades become the context's `filter`; white\n * balance there refers to an SVG filter, which `options.defineSvgFilter` is given to put in the page\n * (without it, white balance is left out of the canvas). A grade's LUT needs `options.lutFor` and\n * `options.scratch`: the layer is drawn on the scratch canvas, its pixels run through the LUT, and\n * the result is laid on the frame with the layer's opacity and blend. A compound clip's layers are\n * drawn on a scratch canvas of their own (transparent), which is then drawn like a picture.\n */\nexport function drawVideoFrame(ctx: VideoCanvasContext, frame: VideoFrame, sourceFor: (layer: VideoLayer) => CanvasImageSource | null, scale = 1, options: VideoDrawOptions = {}): void {\n\tctx.save();\n\tctx.setTransform(scale, 0, 0, scale, 0, 0);\n\tctx.globalAlpha = 1;\n\tctx.fillStyle = frame.background;\n\tctx.fillRect(0, 0, frame.width, frame.height);\n\tdrawVideoLayers(ctx, frame, frame.layers, sourceFor, scale, options, 0);\n\tctx.restore();\n}\n\n/** Draws layers back to front; `depth` is how many compounds they are inside (it picks the scratch slots). */\nfunction drawVideoLayers(ctx: VideoCanvasContext, frame: VideoFrame, layers: readonly VideoLayer[], sourceFor: (layer: VideoLayer) => CanvasImageSource | null, scale: number, options: VideoDrawOptions, depth: number): void {\n\tconst cw = Math.max(1, Math.round(frame.width * scale));\n\tconst ch = Math.max(1, Math.round(frame.height * scale));\n\tfor (const layer of layers) {\n\t\tlet source = sourceFor;\n\t\tif (layer.layers) {\n\t\t\tconst group = options.scratch?.(cw, ch, 2 * depth);\n\t\t\tif (!group) {\n\t\t\t\tdrawVideoLayers(ctx, frame, layer.layers, sourceFor, scale, options, depth + 1);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst g = group.ctx;\n\t\t\tg.save();\n\t\t\tg.setTransform(1, 0, 0, 1, 0, 0);\n\t\t\tg.clearRect(0, 0, cw, ch);\n\t\t\tg.setTransform(scale, 0, 0, scale, 0, 0);\n\t\t\tg.globalAlpha = 1;\n\t\t\tg.globalCompositeOperation = 'source-over';\n\t\t\tdrawVideoLayers(g, frame, layer.layers, sourceFor, scale, options, depth + 1);\n\t\t\tg.restore();\n\t\t\tsource = (l) => (l === layer ? group.canvas : sourceFor(l));\n\t\t}\n\t\tconst setting = layer.grade?.lut;\n\t\tconst lut = setting ? options.lutFor?.(setting.src) : null;\n\t\tconst scratch = lut ? options.scratch?.(cw, ch, 2 * depth + 1) : null;\n\t\tctx.save();\n\t\tctx.setTransform(scale, 0, 0, scale, 0, 0);\n\t\tif (lut && scratch) {\n\t\t\tconst s = scratch.ctx;\n\t\t\ts.save();\n\t\t\ts.setTransform(1, 0, 0, 1, 0, 0);\n\t\t\ts.clearRect(0, 0, cw, ch);\n\t\t\ts.setTransform(scale, 0, 0, scale, 0, 0);\n\t\t\ts.globalAlpha = 1;\n\t\t\ts.globalCompositeOperation = 'source-over';\n\t\t\tpaintVideoLayer(s, frame, layer, source, options);\n\t\t\ts.restore();\n\t\t\tconst img = s.getImageData(0, 0, cw, ch);\n\t\t\tapplyVideoLutToPixels(lut, img.data, setting!.strength ?? 1);\n\t\t\ts.putImageData(img, 0, 0);\n\t\t\tctx.setTransform(1, 0, 0, 1, 0, 0);\n\t\t\tctx.globalAlpha = layer.opacity;\n\t\t\tif (layer.blend && layer.blend !== 'normal') ctx.globalCompositeOperation = layer.blend === 'add' ? 'lighter' : layer.blend;\n\t\t\tctx.drawImage(scratch.canvas, 0, 0, cw, ch);\n\t\t} else {\n\t\t\tctx.globalAlpha = layer.opacity;\n\t\t\tif (layer.blend && layer.blend !== 'normal') ctx.globalCompositeOperation = layer.blend === 'add' ? 'lighter' : layer.blend;\n\t\t\tpaintVideoLayer(ctx, frame, layer, source, options);\n\t\t}\n\t\tctx.restore();\n\t}\n}\n","import { videoClipAnimated } from './clip-animation.js';\nimport { placeVideoRect } from './evaluate.js';\nimport { videoIrisRadius } from './render.js';\nimport { videoTimeRemapBreakpoints, videoTimeRemapSpan } from './remap.js';\nimport { normalizeVideoGradeLut, videoGradeFfmpegFilters } from './grade.js';\nimport { isVideoKeyframes, VIDEO_TRANSFORM_PROPERTIES, videoKeyframeFfmpegExpr, type VideoAnimatable, type VideoKeyframes } from './keyframes.js';\nimport { allVideoTracks, formatVideoTimecode, formatVideoTimecodeFrames, isVideoDropFrameRate, videoHourFrames, videoTimecodeFrames, sortedVideoClips, videoAssetMap, videoClipBefore, videoClipEnd, videoClipOverhang, videoClipSpeed, videoProjectDuration, videoAssetHasSound, videoSequenceDuration, videoSequenceMap } from './timeline.js';\nimport { videoTransitionAudioCurve } from './types.js';\nimport type { VideoWipeDirection, VideoAsset, VideoBlendMode, VideoClip, VideoFadeCurve, VideoProject, VideoTextClip, VideoTrack } from './types.js';\n\n// ---------------------------------------------------------------------------------------------\n// CMX 3600 EDL\n// ---------------------------------------------------------------------------------------------\n\nexport interface VideoEdlOptions {\n\t/** Track to export (default: the bottom video track, V1 in most NLEs). */\n\ttrack?: string;\n\t/** Record timecode of the timeline's start (ms; default timecode 01:00:00:00, the usual start). */\n\trecordStart?: number;\n\t/** Title line (default: the project's name). */\n\ttitle?: string;\n\t/** Drop-frame timecode (default on at 29.97 and 59.94 fps, where it is the norm; ignored at other rates). */\n\tdropFrame?: boolean;\n}\n\n/** Reel names are at most 8 characters, letters and digits. */\nconst reelName = (asset: VideoAsset | undefined) => (asset?.name ?? asset?.id ?? 'AX').replace(/\\.[a-z0-9]+$/i, '').replace(/[^A-Za-z0-9]/g, '').toUpperCase().slice(0, 8) || 'AX';\n\n/**\n * One track as a CMX 3600 edit decision list, for conforming in another NLE: an event per clip with\n * source and record timecode at the project's frame rate (drop-frame at 29.97 and 59.94), dissolves (`D`) for crossfades, dips and\n * wipes (`W001`), `M2` lines for speed changes, and `* FROM CLIP NAME` comments. Titles, colour\n * clips and compound clips (not flattened yet) become black (`BL`) events.\n */\nexport function toVideoEdl(project: VideoProject, options: VideoEdlOptions = {}): string {\n\tconst track = options.track !== undefined ? project.tracks.find((t) => t.id === options.track) : [...project.tracks].reverse().find((t) => t.kind === 'video');\n\tif (!track) throw new Error(options.track !== undefined ? `There is no track \"${options.track}\".` : 'The project has no video track.');\n\tconst fps = project.fps;\n\tconst dropFrame = (options.dropFrame ?? true) && isVideoDropFrameRate(fps);\n\tconst tc = (ms: number) => formatVideoTimecode(ms, fps, dropFrame);\n\t// Record time counts from a timecode, not a clock time: an hour of 29.97 frames is not 01:00:00:00 in non-drop.\n\tconst rec0 = options.recordStart !== undefined ? videoTimecodeFrames(options.recordStart, fps) : videoHourFrames(fps, dropFrame);\n\tconst rtc = (ms: number) => formatVideoTimecodeFrames(rec0 + videoTimecodeFrames(ms, fps), fps, dropFrame);\n\tconst assets = videoAssetMap(project);\n\tconst channel = track.kind === 'video' ? 'V' : 'A';\n\tconst lines = [`TITLE: ${(options.title ?? project.name ?? 'Untitled').toUpperCase()}`, `FCM: ${dropFrame ? 'DROP FRAME' : 'NON-DROP FRAME'}`, ''];\n\tlet event = 0;\n\tconst num = () => String(++event).padStart(3, '0');\n\tconst sourceAt = (clip: VideoClip, time: number) => (clip.type === 'media' ? (clip.in ?? 0) + (time - clip.start) * videoClipSpeed(clip) : time - clip.start);\n\tconst row = (n: string, reel: string, kind: string, srcIn: number, srcOut: number, recIn: number, recOut: number) =>\n\t\t`${n} ${reel.padEnd(8)} ${channel.padEnd(5)} ${kind.padEnd(8)} ${tc(srcIn)} ${tc(srcOut)} ${rtc(recIn)} ${rtc(recOut)}`;\n\tfor (const clip of sortedVideoClips(track)) {\n\t\tconst asset = clip.type === 'media' ? assets.get(clip.asset) : undefined;\n\t\tconst reel = clip.type === 'media' ? reelName(asset) : 'BL';\n\t\tconst end = videoClipEnd(clip);\n\t\tconst before = clip.transition ? videoClipBefore(track, clip) : null;\n\t\t// The cut moves to where the transition starts; this clip's event begins there.\n\t\tconst half = before && clip.transition!.type !== 'dip' ? clip.transition!.duration / 2 : 0;\n\t\tconst next = sortedVideoClips(track).find((c) => c !== clip && Math.abs(c.start - end) < 0.5 && c.transition && c.transition.type !== 'dip');\n\t\tconst recOut = next ? end - next.transition!.duration / 2 : end;\n\t\tconst recIn = clip.start - half;\n\t\tconst n = num();\n\t\tif (before) {\n\t\t\tconst t = clip.transition!;\n\t\t\tconst frames = String(Math.round((t.duration * fps) / 1000)).padStart(3, '0');\n\t\t\tconst outReel = before.type === 'media' ? reelName(assets.get(before.asset)) : 'BL';\n\t\t\tconst at = sourceAt(before, recIn);\n\t\t\tlines.push(row(n, outReel, 'C', at, at, recIn, recIn));\n\t\t\tlines.push(row(n, reel, `${t.type === 'crossfade' || t.type === 'dip' ? 'D' : 'W001'} ${frames}`, sourceAt(clip, recIn), sourceAt(clip, recOut), recIn, recOut));\n\t\t} else lines.push(row(n, reel, 'C', sourceAt(clip, recIn), sourceAt(clip, recOut), recIn, recOut));\n\t\tif (clip.type === 'media' && videoClipSpeed(clip) !== 1) lines.push(`M2 ${reel.padEnd(8)} ${(videoClipSpeed(clip) * fps).toFixed(1).padStart(6)} ${tc(sourceAt(clip, recIn))}`);\n\t\tif (clip.type === 'media') lines.push(`* FROM CLIP NAME: ${asset?.name ?? asset?.src ?? clip.asset}`);\n\t\tif (clip.type === 'text') lines.push(`* TITLE: ${clip.text.replace(/\\n/g, ' ')}`);\n\t\tif (clip.type === 'color') lines.push(`* COLOR: ${clip.color}`);\n\t\t// CMX 3600 has no nesting: a compound clip stands in as black, named, until EDLs flatten them.\n\t\tif (clip.type === 'sequence') lines.push(`* COMPOUND CLIP: ${clip.name ?? clip.sequence} (sequence ${clip.sequence} from ${tc(clip.in ?? 0)}, not flattened)`);\n\t\tlines.push('');\n\t}\n\treturn lines.join('\\n');\n}\n\n// ---------------------------------------------------------------------------------------------\n// ffmpeg\n// ---------------------------------------------------------------------------------------------\n\nexport interface VideoFfmpegOptions {\n\t/** Output file (default `output.mp4`). */\n\toutput?: string;\n\t/** The path or URL ffmpeg should open for an asset (default its `src`). */\n\tresolve?: (asset: VideoAsset) => string;\n\t/** The path ffmpeg's `lut3d` should read for a grade's LUT `src` (default the `src`; it must be a local file). */\n\tresolveLut?: (src: string) => string;\n\t/** Default `libx264`. */\n\tvideoCodec?: string;\n\t/** Default `aac`. */\n\taudioCodec?: string;\n\t/** x264 quality (default 18). */\n\tcrf?: number;\n\t/** A font file for titles (drawtext's `fontfile`); default the system's font for the family. */\n\tfontFile?: string;\n\t/**\n\t * Titles as images instead of `drawtext` (which needs an ffmpeg built with libfreetype; Homebrew's\n\t * is not): return the path or URL of a transparent PNG the size of the frame showing the title as\n\t * the preview draws it (`videoTitleFrame` + `drawVideoFrame`). It is overlaid like a still, with\n\t * the title's opacity and fades.\n\t */\n\ttitleImage?: (clip: VideoTextClip, size: { width: number; height: number }) => string;\n\t/** Normalise the mix's loudness with ffmpeg's `loudnorm` (EBU R128). */\n\tloudness?: VideoLoudnessTarget;\n}\n\n/** A loudness to normalise the mix to (`loudnorm`'s I, TP and LRA). */\nexport interface VideoLoudnessTarget {\n\t/** Integrated loudness, in LUFS (default -14, as streaming services play; -16 for podcasts, -23 for EBU R128 broadcast). */\n\tintegrated?: number;\n\t/** Highest true peak, in dBTP (default -1). */\n\ttruePeak?: number;\n\t/** Loudness range, in LU (default 11). */\n\trange?: number;\n\t/**\n\t * The mix as a first pass measured it (`toVideoLoudnessMeasure` then\n\t * `parseVideoLoudnessMeasurement`). With it the second pass applies one fixed gain where it can\n\t * (linear), so the dynamics are kept; without it `loudnorm` adjusts as it goes in one pass.\n\t */\n\tmeasured?: VideoLoudnessMeasurement;\n}\n\n/** What a measuring pass found (`loudnorm`'s input_i, input_tp, input_lra, input_thresh and target_offset). */\nexport interface VideoLoudnessMeasurement {\n\t/** Integrated loudness (LUFS). */\n\tintegrated: number;\n\t/** True peak (dBTP). */\n\ttruePeak: number;\n\t/** Loudness range (LU). */\n\trange: number;\n\t/** Gating threshold (LUFS). */\n\tthreshold: number;\n\t/** Offset for the second pass (LU). */\n\toffset: number;\n}\n\n/** `loudnorm` with a target, measuring (`print_format=json`) or applying a measurement; then back to 48 kHz (it outputs 192 kHz). */\nfunction loudnormFilter(target: VideoLoudnessTarget = {}, measure = false): string {\n\tconst I = target.integrated ?? -14;\n\tconst TP = target.truePeak ?? -1;\n\tconst LRA = target.range ?? 11;\n\tif (!(I >= -70 && I <= -5)) throw new Error(`The loudness target must be between -70 and -5 LUFS (got ${I}); -14 suits streaming, -23 broadcast.`);\n\tif (!(TP >= -9 && TP <= 0)) throw new Error(`The true peak ceiling must be between -9 and 0 dBTP (got ${TP}); -1 is usual.`);\n\tif (!(LRA >= 1 && LRA <= 50)) throw new Error(`The loudness range must be between 1 and 50 LU (got ${LRA}).`);\n\tconst parts = [`loudnorm=I=${I}:TP=${TP}:LRA=${LRA}`];\n\tconst m = target.measured;\n\tif (m && !measure) {\n\t\tfor (const [k, v] of Object.entries(m)) if (!Number.isFinite(v)) throw new Error(`The measured ${k} is not a number (${v}); measure again, or leave \"measured\" out for a one-pass normalisation.`);\n\t\tparts.push(`measured_I=${m.integrated}:measured_TP=${m.truePeak}:measured_LRA=${m.range}:measured_thresh=${m.threshold}:offset=${m.offset}:linear=true`);\n\t}\n\tif (measure) parts.push('print_format=json');\n\treturn `${parts.join(':')},aresample=48000`;\n}\n\n/**\n * Reads the loudness a measuring pass printed (the JSON `loudnorm` writes to stderr at the end of\n * `toVideoLoudnessMeasure`'s command). Throws when there is none, or when the mix is silent.\n */\nexport function parseVideoLoudnessMeasurement(output: string): VideoLoudnessMeasurement {\n\tconst blocks = output.match(/\\{[^{}]*\"input_i\"[^{}]*\\}/g);\n\tif (!blocks) throw new Error('No loudness measurement found: pass the stderr of the command from toVideoLoudnessMeasure.');\n\tconst json = JSON.parse(blocks[blocks.length - 1]) as Record<string, string>;\n\tconst n = (k: string) => Number(json[k]);\n\tconst m = { integrated: n('input_i'), truePeak: n('input_tp'), range: n('input_lra'), threshold: n('input_thresh'), offset: n('target_offset') };\n\tif (!Number.isFinite(m.integrated)) throw new Error('The mix is silent, so its loudness cannot be normalised.');\n\treturn m;\n}\n\nexport interface VideoFfmpegExport {\n\t/** Arguments after `ffmpeg` (pass to `spawn('ffmpeg', args)`; no shell quoting needed). */\n\targs: string[];\n\t/** The same as one shell command line, quoted for a POSIX shell. */\n\tcommand: string;\n\t/** The `-filter_complex` graph on its own. */\n\tfilterComplex: string;\n\t/** Length rendered (ms). */\n\tduration: number;\n\t/** Anything the render only approximates. */\n\tnotes: string[];\n}\n\nconst sec = (ms: number) => String(Math.round(ms) / 1000);\n/** A number for an expression, to a hundredth. */\nconst fmtMs = (v: number) => String(Math.round(v * 100) / 100);\n/** ffmpeg `blend` modes for the blend modes. */\nconst FFMPEG_BLEND: Record<Exclude<VideoBlendMode, 'normal'>, string> = {\n\tmultiply: 'multiply',\n\tscreen: 'screen',\n\toverlay: 'overlay',\n\tdarken: 'darken',\n\tlighten: 'lighten',\n\t'color-dodge': 'dodge',\n\t'color-burn': 'burn',\n\t'hard-light': 'hardlight',\n\t'soft-light': 'softlight',\n\tdifference: 'difference',\n\texclusion: 'exclusion',\n\tadd: 'addition'\n};\n/** `afade`'s curve for a fade shape (the same formulas as `videoFadeCurveGain`); nothing for linear, its default. */\nconst AFADE_CURVES: Record<VideoFadeCurve, string> = { linear: 'tri', 'equal-power': 'qsin', 's-curve': 'hsin', exponential: 'cub', logarithmic: 'ipar' };\nconst afadeCurve = (curve: VideoFadeCurve | undefined) => (curve && curve !== 'linear' ? `:curve=${AFADE_CURVES[curve]}` : '');\nconst even = (v: number) => Math.max(2, 2 * Math.round(v / 2));\n/** Escapes a value for a filter option inside a filtergraph (option level, then graph level). */\nexport const ffmpegFilterValue = (s: string): string =>\n\ts\n\t\t.replace(/[\\\\':%]/g, (c) => `\\\\${c}`)\n\t\t.replace(/[\\\\'[\\],;]/g, (c) => `\\\\${c}`);\nconst color = (c: string) => {\n\tconst hex = /^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.exec(c);\n\tif (!hex) return c.replace(/[^A-Za-z0-9@.]/g, '');\n\tconst h = hex[1].length === 3 ? [...hex[1]].map((x) => x + x).join('') : hex[1];\n\treturn `0x${h.slice(0, 6)}${h.length === 8 ? `@${(parseInt(h.slice(6), 16) / 255).toFixed(3)}` : ''}`;\n};\n/** Quotes an argument for a POSIX shell when it needs it. */\nexport const videoShellQuote = (s: string) => (/^[\\w@%+=:,./-]+$/.test(s) ? s : `'${s.replace(/'/g, `'\\\\''`)}'`);\n\n/** `atempo` only takes 0.5–2 (100 in newer builds), so larger changes chain several. */\nfunction atempo(speed: number): string[] {\n\tconst out: string[] = [];\n\tlet s = speed;\n\twhile (s > 2) {\n\t\tout.push('atempo=2');\n\t\ts /= 2;\n\t}\n\twhile (s < 0.5) {\n\t\tout.push('atempo=0.5');\n\t\ts /= 0.5;\n\t}\n\tif (Math.abs(s - 1) > 1e-6) out.push(`atempo=${Math.round(s * 1e6) / 1e6}`);\n\treturn out;\n}\n\n/**\n * The project as an ffmpeg command: each clip an input trimmed to what it plays (plus transition\n * overlap), scaled and placed as `videoFrameAt` places it, faded, and overlaid on a background in\n * track order between its start and end; titles with `drawtext`; sound delayed into place, faded,\n * mixed and trimmed to the project's length. Render on a server or with ffmpeg.wasm.\n */\nexport function toVideoFfmpeg(project: VideoProject, options: VideoFfmpegOptions = {}): VideoFfmpegExport {\n\treturn buildFfmpeg(project, options, false);\n}\n\n/**\n * The first pass of a two-pass loudness normalisation: an ffmpeg command that mixes only the sound,\n * as `toVideoFfmpeg` would, and prints its loudness as JSON on stderr instead of writing a file.\n * Read it with `parseVideoLoudnessMeasurement` and pass it as `loudness.measured` to\n * `toVideoFfmpeg`. Throws when nothing on the timeline makes a sound.\n */\nexport function toVideoLoudnessMeasure(project: VideoProject, options: Pick<VideoFfmpegOptions, 'resolve' | 'loudness'> = {}): VideoFfmpegExport {\n\treturn buildFfmpeg(project, { ...options, loudness: { ...options.loudness, measured: undefined } }, true);\n}\n\nfunction buildFfmpeg(project: VideoProject, options: VideoFfmpegOptions, measure: boolean): VideoFfmpegExport {\n\tconst notes: string[] = [];\n\tconst assets = videoAssetMap(project);\n\tconst sequences = videoSequenceMap(project);\n\tconst D = videoProjectDuration(project);\n\tif (D <= 0) throw new Error('The project has no clips, so there is nothing to render.');\n\tconst W = even(project.width);\n\tconst H = even(project.height);\n\tconst fps = project.fps;\n\tconst inputs: string[][] = [];\n\tconst graph: string[] = measure ? [] : [`color=c=${color(project.background ?? '#000000')}:s=${W}x${H}:r=${fps}:d=${sec(D)},format=yuva420p[base]`];\n\tlet usesDrawtext = false;\n\tconst animated = new Set<string>();\n\tconst ramped = new Set<'sound'>();\n\t/**\n\t * A ramped picture: each source frame moved to the clip time where the ramp first shows it (the\n\t * ramp's inverse, as straight lines), `fps` repeating frames through slow stretches and freezes,\n\t * and `tpad` holding the first and last frames before and after the ramp (and through handles).\n\t */\n\tconst rampedPicture = (remap: VideoKeyframes, lead: number, end: number): string[] => {\n\t\tconst pts = videoTimeRemapBreakpoints(remap, 2000 / fps);\n\t\tconst first = pts[0];\n\t\tconst last = pts[pts.length - 1];\n\t\tconst s = `(T*1000+${fmtMs(first.v)})`;\n\t\tlet e = fmtMs(last.t - first.t);\n\t\tfor (let i = pts.length - 2; i >= 0; i--) {\n\t\t\tconst a = pts[i];\n\t\t\tconst b = pts[i + 1];\n\t\t\tif (b.v - a.v < 1e-6) continue; // a freeze: its frames come from the next stretch\n\t\t\te = `if(lt(${s},${fmtMs(b.v)}),${fmtMs(a.t - first.t)}+(${s}-${fmtMs(a.v)})*${fmtMs((b.t - a.t) / (b.v - a.v))},${e})`;\n\t\t}\n\t\tconst before = lead + first.t;\n\t\tconst after = Math.max(0, end - last.t);\n\t\treturn ['setpts=PTS-STARTPTS', `setpts='(${e})/1000/TB'`, `fps=${fps}`, ...(before > 0.5 || after > 0.5 ? [`tpad=start_mode=clone:start_duration=${sec(before)}:stop_mode=clone:stop_duration=${sec(after + 1000 / fps)}`] : [`tpad=stop_mode=clone:stop_duration=${sec(1000 / fps)}`]), `trim=duration=${sec(lead + end)}`];\n\t};\n\t/**\n\t * Ramped sound: the ramp cut into straight stretches, each played at its own speed with\n\t * `atempo` (silence where it is frozen or slower than a tenth), joined with `concat`, with silence\n\t * for the handles and holds around it. Gliding speed changes become small steps.\n\t */\n\tconst rampedSound = (remap: VideoKeyframes, input: string, output: string, lead: number, end: number): string[] => {\n\t\tconst pts = videoTimeRemapBreakpoints(remap, Math.max(80, 2000 / fps));\n\t\tconst first = pts[0];\n\t\tconst last = pts[pts.length - 1];\n\t\tconst n = ak;\n\t\tconst fmtA = 'aformat=sample_fmts=fltp:sample_rates=48000:channel_layouts=stereo';\n\t\tconst silence = (ms: number) => `anullsrc=r=48000:cl=stereo,atrim=duration=${sec(ms)},${fmtA}`;\n\t\tconst pieces: string[] = [];\n\t\tconst out: string[] = [];\n\t\tconst parts: string[] = [];\n\t\tif (lead + first.t > 0.5) parts.push(silence(lead + first.t));\n\t\tconst played: { from: number; to: number; speed: number }[] = [];\n\t\tfor (let i = 0; i + 1 < pts.length; i++) {\n\t\t\tconst dt = pts[i + 1].t - pts[i].t;\n\t\t\tif (dt < 0.5) continue;\n\t\t\tconst speed = (pts[i + 1].v - pts[i].v) / dt;\n\t\t\tif (speed < 0.1) parts.push(silence(dt));\n\t\t\telse {\n\t\t\t\tplayed.push({ from: pts[i].v - first.v, to: pts[i + 1].v - first.v, speed });\n\t\t\t\tparts.push(`#${played.length - 1}`);\n\t\t\t}\n\t\t}\n\t\tif (end - last.t > 0.5) parts.push(silence(end - last.t));\n\t\tif (played.length) out.push(`[${input}]asplit=${played.length}${played.map((_, k) => `[r${n}s${k}]`).join('')}`);\n\t\tparts.forEach((p, k) => {\n\t\t\tconst label = `[r${n}p${k}]`;\n\t\t\tif (p.startsWith('#')) {\n\t\t\t\tconst piece = played[Number(p.slice(1))];\n\t\t\t\tout.push(`[r${n}s${p.slice(1)}]atrim=start=${sec(piece.from)}:end=${sec(piece.to)},asetpts=PTS-STARTPTS,${atempo(piece.speed).join(',') || 'anull'},${fmtA}${label}`);\n\t\t\t} else out.push(`${p}${label}`);\n\t\t\tpieces.push(label);\n\t\t});\n\t\tout.push(`${pieces.join('')}concat=n=${pieces.length}:v=0:a=1${output}`);\n\t\treturn out;\n\t};\n\tconst blended = new Set<VideoBlendMode>();\n\tlet k = 0;\n\t// Keyframes become piecewise-linear expressions; eased segments get a breakpoint every two frames.\n\tconst step = 2000 / fps;\n\tconst expr = (prop: VideoAnimatable | undefined, clipTime: string, fallback: number, what: string) => {\n\t\tif (isVideoKeyframes(prop)) animated.add(what);\n\t\treturn videoKeyframeFfmpegExpr(prop, clipTime, fallback, step);\n\t};\n\tconst input = (clip: VideoClip & { type: 'media' }, asset: VideoAsset, lead: number, tail: number) => {\n\t\tconst speed = videoClipSpeed(clip);\n\t\tconst src = options.resolve ? options.resolve(asset) : asset.src;\n\t\tconst span = clip.duration + lead + tail;\n\t\tif (asset.kind === 'image') inputs.push(['-loop', '1', '-framerate', String(fps), '-t', sec(span), '-i', src]);\n\t\telse if (clip.timeRemap) {\n\t\t\t// A ramp reads just the source it plays (plus a frame); it holds its ends for any handles.\n\t\t\tconst { from, to } = videoTimeRemapSpan(clip.timeRemap);\n\t\t\tinputs.push(['-ss', sec((clip.in ?? 0) + from), '-t', sec(to - from + 1000 / fps), '-i', src]);\n\t\t} else inputs.push(['-ss', sec((clip.in ?? 0) - lead * speed), '-t', sec(span * speed), '-i', src]);\n\t\treturn inputs.length - 1;\n\t};\n\tlet ak = 0;\n\tlet q = 0;\n\t/**\n\t * Lays `tracks` back to front on the stream `base` (`length` ms long, in the tracks' own time; none\n\t * when no picture is needed) and makes each clip's sound, delayed into place in that time. A\n\t * compound clip builds its sequence the same way, one level in.\n\t */\n\tconst compose = (tracks: readonly VideoTrack[], base: string | null, length: number, scope: { within: string[]; picture: boolean; sound: boolean }): { video: string | null; audio: string[] } => {\n\t\tlet cur = base;\n\t\tconst sounds: string[] = [];\n\t\t// Back to front: later tracks are further back.\n\t\tfor (const track of [...tracks].reverse()) {\n\t\t\tfor (const raw of sortedVideoClips(track)) {\n\t\t\t\t// Entrance and exit animations go out as keyframes on opacity and the transform.\n\t\t\t\tconst clip = videoClipAnimated(raw, project);\n\t\t\t\tconst { lead, tail } = videoClipOverhang(track, clip);\n\t\t\t\tconst t0 = clip.start - lead;\n\t\t\t\tconst span = clip.duration + lead + tail;\n\t\t\t\tconst end = videoClipEnd(clip);\n\t\t\t\tconst asset = clip.type === 'media' ? assets.get(clip.asset) : undefined;\n\t\t\t\tif (clip.type === 'media' && !asset) {\n\t\t\t\t\tnotes.push(`Clip \"${clip.id}\" was left out: its asset \"${clip.asset}\" is missing.`);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst shows = scope.picture && track.kind === 'video' && !track.hidden;\n\t\t\t\t// A compound is its sequence built as a sub-graph: the picture on a transparent full frame\n\t\t\t\t// and the sound as one mix, both cut to what the compound plays (plus transition overlap).\n\t\t\t\tlet compound: { picture: string | null; sound: string | null } | null = null;\n\t\t\t\tif (clip.type === 'sequence') {\n\t\t\t\t\tconst seq = sequences.get(clip.sequence);\n\t\t\t\t\tif (!seq || scope.within.includes(seq.id)) {\n\t\t\t\t\t\tnotes.push(`Compound clip \"${clip.id}\" was left out: its sequence \"${clip.sequence}\" ${seq ? 'contains itself' : 'is missing'}.`);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst from = (clip.in ?? 0) - lead;\n\t\t\t\t\tif (from < -0.5) notes.push(`Compound clip \"${clip.id}\"'s transition needs ${Math.round(-from)} ms of sequence \"${seq.id}\" before its start, which is not there; it shows nothing then.`);\n\t\t\t\t\tconst length = Math.max(videoSequenceDuration(seq), from + span);\n\t\t\t\t\tconst hears = scope.sound && !clip.muted && !track.muted;\n\t\t\t\t\tconst n = q++;\n\t\t\t\t\tconst nestedBase = shows ? `nb${n}` : null;\n\t\t\t\t\tif (nestedBase) graph.push(`color=c=black@0:s=${W}x${H}:r=${fps}:d=${sec(length)},format=yuva420p[${nestedBase}]`);\n\t\t\t\t\tconst sub = compose(seq.tracks, nestedBase, length, { within: [...scope.within, seq.id], picture: shows, sound: hears });\n\t\t\t\t\tcompound = { picture: null, sound: null };\n\t\t\t\t\tif (sub.video) {\n\t\t\t\t\t\tgraph.push(`[${sub.video}]trim=start=${sec(Math.max(0, from))}:duration=${sec(span)},setpts=PTS-STARTPTS[sq${n}]`);\n\t\t\t\t\t\tcompound.picture = `[sq${n}]`;\n\t\t\t\t\t}\n\t\t\t\t\tif (sub.audio.length) {\n\t\t\t\t\t\tgraph.push(`${sub.audio.join('')}amix=inputs=${sub.audio.length}:normalize=0:duration=longest,apad,atrim=start=${sec(Math.max(0, from))}:end=${sec(from + span)}[sm${n}]`);\n\t\t\t\t\t\tcompound.sound = `[sm${n}]`;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlet index: number | undefined;\n\t\t\t\tif (shows && asset && asset.kind !== 'audio') index = input(clip as VideoClip & { type: 'media' }, asset, lead, tail);\n\t\t\t\tconst audible = clip.type === 'sequence' ? !!compound?.sound : videoAssetHasSound(asset);\n\t\t\t\tif (scope.sound && audible && (clip.type === 'media' || clip.type === 'sequence') && !clip.muted && !track.muted) {\n\t\t\t\t\tconst trackGain = track.volume ?? 1;\n\t\t\t\t\tconst volume = isVideoKeyframes(clip.volume) ? `volume='${trackGain}*(${expr(clip.volume, `(t*1000${lead ? `-${Math.round(lead)}` : ''})`, 1, 'volume')})':eval=frame` : `volume=${(clip.volume ?? 1) * trackGain}`;\n\t\t\t\t\tconst ramp = clip.type === 'media' ? clip.timeRemap : undefined;\n\t\t\t\t\tconst ai = compound ? -1 : (index ?? input(clip as VideoClip & { type: 'media' }, asset!, lead, tail));\n\t\t\t\t\tlet source = compound?.sound ?? `[${ai}:a]`;\n\t\t\t\t\tif (ramp) {\n\t\t\t\t\t\tsource = `[r${ak}]`;\n\t\t\t\t\t\tgraph.push(...rampedSound(ramp, `${ai}:a`, source, lead, clip.duration + tail));\n\t\t\t\t\t\tramped.add('sound');\n\t\t\t\t\t}\n\t\t\t\t\tconst chain = [...(ramp ? [] : ['asetpts=PTS-STARTPTS', ...atempo(videoClipSpeed(clip))]), volume];\n\t\t\t\t\tconst before = clip.transition ? videoClipBefore(track, clip) : null;\n\t\t\t\t\tconst next = sortedVideoClips(track).find((c) => c !== clip && Math.abs(c.start - end) < 0.5 && c.transition);\n\t\t\t\t\tconst inCurve = clip.transition ? afadeCurve(videoTransitionAudioCurve(clip.transition)) : '';\n\t\t\t\t\tconst outCurve = next ? afadeCurve(videoTransitionAudioCurve(next.transition!)) : '';\n\t\t\t\t\tif (lead) chain.push(`afade=t=in:st=0:d=${sec(2 * lead)}${inCurve}`);\n\t\t\t\t\tif (tail) chain.push(`afade=t=out:st=${sec(span - 2 * tail)}:d=${sec(2 * tail)}${outCurve}`);\n\t\t\t\t\tif (before && clip.transition!.type === 'dip') chain.push(`afade=t=in:st=0:d=${sec(clip.transition!.duration / 2)}${inCurve}`);\n\t\t\t\t\tif (next?.transition!.type === 'dip') chain.push(`afade=t=out:st=${sec(span - next.transition!.duration / 2)}:d=${sec(next.transition!.duration / 2)}${outCurve}`);\n\t\t\t\t\tif (clip.fadeIn) chain.push(`afade=t=in:st=${sec(lead)}:d=${sec(clip.fadeIn)}${afadeCurve(clip.fadeInCurve)}`);\n\t\t\t\t\tif (clip.fadeOut) chain.push(`afade=t=out:st=${sec(lead + clip.duration - clip.fadeOut)}:d=${sec(clip.fadeOut)}${afadeCurve(clip.fadeOutCurve)}`);\n\t\t\t\t\tchain.push(`adelay=${Math.round(t0)}:all=1`);\n\t\t\t\t\tgraph.push(`${source}${chain.join(',')}[a${ak}]`);\n\t\t\t\t\tsounds.push(`[a${ak++}]`);\n\t\t\t\t}\n\t\t\t\tif (!shows || (compound && !compound.picture)) continue;\n\t\t\t\tconst enable = `enable='between(t,${sec(t0)},${sec(t0 + span)})'`;\n\t\t\t\tconst next = `v${k++}`;\n\t\t\t\t// Clip time (ms) in a filter's `t`: timeline time on the composite, time from t0 on the clip's own chain.\n\t\t\t\tconst onTimeline = `(t*1000-${Math.round(clip.start)})`;\n\t\t\t\tconst onChain = (v: string) => `(${v}*1000${lead ? `-${Math.round(lead)}` : ''})`;\n\t\t\t\tconst tf = clip.transform;\n\t\t\t\tconst moving = VIDEO_TRANSFORM_PROPERTIES.some((p) => isVideoKeyframes(tf?.[p]));\n\t\t\t\tif (clip.type === 'text' && options.titleImage) {\n\t\t\t\t\t// A title image has its transform baked in, unless the transform moves: then the image is drawn unplaced and moved here.\n\t\t\t\t\tinputs.push(['-loop', '1', '-framerate', String(fps), '-t', sec(span), '-i', options.titleImage(moving ? { ...clip, transform: undefined } : clip, { width: project.width, height: project.height })]);\n\t\t\t\t\tindex = inputs.length - 1;\n\t\t\t\t} else if (clip.type === 'text') {\n\t\t\t\t\tusesDrawtext = true;\n\t\t\t\t\tif (scope.within.length) notes.push(`Title \"${clip.id}\" is inside a compound clip and drawn with drawtext, which leaves the sequence's transparent areas transparent, so it shows only over pictures in the sequence; pass titleImage to draw it anywhere.`);\n\t\t\t\t\tconst op = isVideoKeyframes(clip.opacity) ? `clip(${expr(clip.opacity, onTimeline, 1, 'opacity')},0,1)` : String(clip.opacity ?? 1);\n\t\t\t\t\tconst alpha = [op, clip.fadeIn ? `min(1,(t-${sec(clip.start)})/${sec(clip.fadeIn)})` : '', clip.fadeOut ? `min(1,(${sec(end)}-t)/${sec(clip.fadeOut)})` : ''].filter(Boolean).join('*');\n\t\t\t\t\tconst coord = (axis: 'x' | 'y') => {\n\t\t\t\t\t\tconst v = tf?.[axis];\n\t\t\t\t\t\tconst base = `(${axis === 'x' ? 'w-text_w' : 'h-text_h'})/2`;\n\t\t\t\t\t\treturn isVideoKeyframes(v) ? `${axis}='${base}+(${expr(v, onTimeline, 0, 'position')})'` : `${axis}=${base}+${v ?? 0}`;\n\t\t\t\t\t};\n\t\t\t\t\tconst fontSize = clip.fontSize ?? 64;\n\t\t\t\t\tconst opts = [\n\t\t\t\t\t\t`text=${ffmpegFilterValue(clip.text)}`,\n\t\t\t\t\t\toptions.fontFile ? `fontfile=${ffmpegFilterValue(options.fontFile)}` : `font=${ffmpegFilterValue(clip.fontFamily ?? 'sans-serif')}`,\n\t\t\t\t\t\tisVideoKeyframes(tf?.scale) ? `fontsize='${fontSize}*(${expr(tf.scale, onTimeline, 1, 'scale')})'` : `fontsize=${Math.round(fontSize * ((tf?.scale as number | undefined) ?? 1))}`,\n\t\t\t\t\t\t`fontcolor=${color(clip.color ?? '#ffffff')}`,\n\t\t\t\t\t\tcoord('x'),\n\t\t\t\t\t\tcoord('y'),\n\t\t\t\t\t\t`alpha='${alpha}'`,\n\t\t\t\t\t\t...(clip.background ? ['box=1', `boxcolor=${color(clip.background)}`, `boxborderw=${Math.round((clip.fontSize ?? 64) / 2)}`] : []),\n\t\t\t\t\t\t`enable='between(t,${sec(clip.start)},${sec(end)})'`\n\t\t\t\t\t];\n\t\t\t\t\tif (tf?.rotation) notes.push(`Title \"${clip.id}\" is drawn without its rotation (drawtext cannot rotate).`);\n\t\t\t\t\tif (videoGradeFfmpegFilters(clip.grade).length || normalizeVideoGradeLut(clip.grade?.lut)) notes.push(`Title \"${clip.id}\" is drawn without its grade (drawtext draws straight onto the picture); pass titleImage to grade titles.`);\n\t\t\t\t\tif (clip.blend && clip.blend !== 'normal') notes.push(`Title \"${clip.id}\" is drawn without its blend mode (drawtext draws straight onto the picture); pass titleImage to blend titles.`);\n\t\t\t\t\tgraph.push(`[${cur}]drawtext=${opts.join(':')}[${next}]`);\n\t\t\t\t\tcur = next;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t// A compound's picture is its sequence's whole frame, the project's size.\n\t\t\t\tconst size = asset ? { width: asset.width ?? project.width, height: asset.height ?? project.height } : { width: project.width, height: project.height };\n\t\t\t\t// A title image already has the title placed (and turned) in a full frame, unless its transform moves.\n\t\t\t\tconst placed = clip.type === 'text' && !moving ? undefined : tf;\n\t\t\t\t// Keyframed fields are left out of the fitted rect and animated by the filters below.\n\t\t\t\tconst still = Object.fromEntries(Object.entries(placed ?? {}).filter(([, v]) => !isVideoKeyframes(v)));\n\t\t\t\tconst rect = placeVideoRect(project, size, clip.type === 'text' ? 'fill' : (clip.fit ?? (clip.type === 'media' || clip.type === 'sequence' ? 'contain' : 'fill')), still);\n\t\t\t\tconst chain: string[] = [];\n\t\t\t\tlet source: string;\n\t\t\t\tif (clip.type === 'color') source = `color=c=${color(clip.color)}:s=${even(rect.width)}x${even(rect.height)}:r=${fps}:d=${sec(span)}`;\n\t\t\t\telse if (compound?.picture) {\n\t\t\t\t\tsource = compound.picture;\n\t\t\t\t\tchain.push(`scale=${even(rect.width)}:${even(rect.height)}`);\n\t\t\t\t} else {\n\t\t\t\t\tsource = `[${index}:v]`;\n\t\t\t\t\tif (clip.type === 'media' && clip.timeRemap) chain.push(...rampedPicture(clip.timeRemap, lead, clip.duration + tail), `scale=${even(rect.width)}:${even(rect.height)}`);\n\t\t\t\t\telse chain.push(`setpts=${videoClipSpeed(clip) !== 1 ? `(PTS-STARTPTS)/${videoClipSpeed(clip)}` : 'PTS-STARTPTS'}`, `fps=${fps}`, `scale=${even(rect.width)}:${even(rect.height)}`);\n\t\t\t\t}\n\t\t\t\tconst grade = videoGradeFfmpegFilters(clip.grade);\n\t\t\t\tif (grade.length) chain.push('format=rgba', ...grade);\n\t\t\t\tconst lut = normalizeVideoGradeLut(clip.grade?.lut);\n\t\t\t\tif (lut) {\n\t\t\t\t\t// The LUT runs on planar RGB after the other steps; at part strength the graded picture is\n\t\t\t\t\t// split and the LUT's result laid over it at that opacity (a straight mix).\n\t\t\t\t\tchain.push('format=gbrap');\n\t\t\t\t\tconst path = options.resolveLut ? options.resolveLut(lut.src) : lut.src;\n\t\t\t\t\tif (/^(blob|data|https?):/i.test(path)) notes.push(`ffmpeg's lut3d reads only local files, and clip \"${clip.id}\"'s LUT is \"${path.slice(0, 80)}\"; save it and pass resolveLut to give its path.`);\n\t\t\t\t\tconst file = ffmpegFilterValue(path);\n\t\t\t\t\tconst into = `q${next}`;\n\t\t\t\t\tgraph.push(`${source.startsWith('[') ? source : `${source},`}${chain.join(',')}[${into}]`);\n\t\t\t\t\tconst lut3d = `lut3d=file=${file}:interp=tetrahedral`;\n\t\t\t\t\tif ((lut.strength ?? 1) >= 1) graph.push(`[${into}]${lut3d}[r${next}]`);\n\t\t\t\t\telse graph.push(`[${into}]split[o${next}][p${next}]`, `[p${next}]${lut3d}[s${next}]`, `[s${next}][o${next}]blend=all_mode=normal:all_opacity=${lut.strength}[r${next}]`);\n\t\t\t\t\tsource = `[r${next}]`;\n\t\t\t\t\tchain.length = 0;\n\t\t\t\t}\n\t\t\t\tchain.push('format=yuva420p');\n\t\t\t\tif (isVideoKeyframes(clip.opacity)) chain.push(`geq=lum='lum(X,Y)':cb='cb(X,Y)':cr='cr(X,Y)':a='alpha(X,Y)*clip(${expr(clip.opacity, onChain('T'), 1, 'opacity')},0,1)'`);\n\t\t\t\telse if (clip.opacity !== undefined && clip.opacity < 1) chain.push(`colorchannelmixer=aa=${clip.opacity}`);\n\t\t\t\tif (clip.fadeIn) chain.push(`fade=t=in:st=${sec(lead)}:d=${sec(clip.fadeIn)}:alpha=1`);\n\t\t\t\tif (clip.fadeOut) chain.push(`fade=t=out:st=${sec(lead + clip.duration - clip.fadeOut)}:d=${sec(clip.fadeOut)}:alpha=1`);\n\t\t\t\tif (lead && clip.transition!.type === 'crossfade') chain.push(`fade=t=in:st=0:d=${sec(2 * lead)}:alpha=1`);\n\t\t\t\tif (lead && clip.transition!.type === 'wipe') {\n\t\t\t\t\tconst d = sec(2 * lead);\n\t\t\t\t\tconst p = `min(1,T/${d})`;\n\t\t\t\t\tconst dir = clip.transition!.direction ?? 'right';\n\t\t\t\t\tconst test = dir === 'right' ? `lt(X,W*${p})` : dir === 'left' ? `gt(X,W*(1-${p}))` : dir === 'down' ? `lt(Y,H*${p})` : `gt(Y,H*(1-${p}))`;\n\t\t\t\t\tchain.push(`geq=lum='lum(X,Y)':cb='cb(X,Y)':cr='cr(X,Y)':a='if(${test},alpha(X,Y),0)'`);\n\t\t\t\t}\n\t\t\t\tif (lead && clip.transition!.type === 'iris') {\n\t\t\t\t\t// The circle is on the frame's centre: in the picture's own pixels, offset by where it sits.\n\t\t\t\t\tconst r = videoIrisRadius({ width: W, height: H }, 1);\n\t\t\t\t\tchain.push(`geq=lum='lum(X,Y)':cb='cb(X,Y)':cr='cr(X,Y)':a='if(lte(hypot(X+${Math.round(rect.x)}-${W / 2},Y+${Math.round(rect.y)}-${H / 2}),${Math.round(r)}*min(1,T/${sec(2 * lead)})),alpha(X,Y),0)'`);\n\t\t\t\t}\n\t\t\t\tconst rotation = placed?.rotation;\n\t\t\t\tif (isVideoKeyframes(rotation)) chain.push(`rotate=a='(${expr(rotation, onChain('t'), 0, 'rotation')})*PI/180':c=black@0:ow='hypot(iw,ih)':oh=ow`);\n\t\t\t\telse if (rotation) chain.push(`rotate=${rotation}*PI/180:c=black@0:ow=rotw(${rotation}*PI/180):oh=roth(${rotation}*PI/180)`);\n\t\t\t\t// Animated scale goes last: geq and rotate keep the frame size they first see, so a size that\n\t\t\t\t// changes before them is frozen. Scaling the turned picture by iw / ih gives the same result.\n\t\t\t\tif (isVideoKeyframes(placed?.scale)) {\n\t\t\t\t\tconst s = expr(placed.scale, onChain('t'), 1, 'scale');\n\t\t\t\t\tchain.push(`scale=w='max(2,trunc(iw*(${s})/2)*2)':h='max(2,trunc(ih*(${s})/2)*2)':eval=frame`);\n\t\t\t\t}\n\t\t\t\tchain.push(`setpts=PTS+${sec(t0)}/TB`);\n\t\t\t\tconst cx = rect.x + rect.width / 2;\n\t\t\t\tconst cy = rect.y + rect.height / 2;\n\t\t\t\t// Push and slide move the whole picture by a frame, eased as videoTransitionEase does.\n\t\t\t\tconst shifts: Record<'x' | 'y', string[]> = { x: [], y: [] };\n\t\t\t\tconst shiftBy = (direction: VideoWipeDirection | undefined, from: number, d: number, entering: boolean) => {\n\t\t\t\t\tconst dir = direction ?? 'right';\n\t\t\t\t\tconst axis = dir === 'left' || dir === 'right' ? 'x' : 'y';\n\t\t\t\t\tconst size = axis === 'x' ? W : H;\n\t\t\t\t\tconst sign = dir === 'left' || dir === 'up' ? -1 : 1;\n\t\t\t\t\tconst ease = `(1-cos(PI*clip((t-${sec(from)})/${sec(d)},0,1)))/2`;\n\t\t\t\t\tshifts[axis].push(`${sign * size}*(${ease}${entering ? '-1' : ''})`);\n\t\t\t\t};\n\t\t\t\tconst into = lead ? clip.transition!.type : undefined;\n\t\t\t\tif (into === 'push' || into === 'slide') shiftBy(clip.transition!.direction, clip.start - lead, 2 * lead, true);\n\t\t\t\tconst after = tail ? sortedVideoClips(track).find((c) => c !== clip && Math.abs(c.start - end) < 0.5 && c.transition) : undefined;\n\t\t\t\tif (after?.transition!.type === 'push') shiftBy(after.transition!.direction, end - tail, 2 * tail, false);\n\t\t\t\tconst at = (axis: 'x' | 'y', c: number) => {\n\t\t\t\t\tconst v = placed?.[axis];\n\t\t\t\t\tconst extra = shifts[axis].map((s) => `+${s}`).join('');\n\t\t\t\t\treturn isVideoKeyframes(v) ? `${axis}='${Math.round(axis === 'x' ? project.width / 2 : project.height / 2)}+(${expr(v, onTimeline, 0, 'position')})-${axis === 'x' ? 'w' : 'h'}/2${extra}'` : `${axis}='${Math.round(c)}-${axis === 'x' ? 'w' : 'h'}/2${extra}'`;\n\t\t\t\t};\n\t\t\t\tgraph.push(`${source.startsWith('[') ? source : `${source},`}${chain.join(',')}[l${next}]`);\n\t\t\t\tif (clip.blend && clip.blend !== 'normal') {\n\t\t\t\t\t// Place the layer on a transparent full frame, blend that with the composite in RGB, then\n\t\t\t\t\t// lay the blend over the composite through the layer's own alpha (its opacity and fades).\n\t\t\t\t\tgraph.push(`color=c=black@0:s=${W}x${H}:r=${fps}:d=${sec(length)},format=yuva420p[t${next}]`);\n\t\t\t\t\t// Inside a sequence the backdrop can be transparent, and where it is the layer shows\n\t\t\t\t\t// unblended (CSS: (1 − backdrop alpha) × layer + backdrop alpha × blend).\n\t\t\t\t\tconst clear = scope.within.length > 0;\n\t\t\t\t\tgraph.push(`[t${next}][l${next}]overlay=${at('x', cx)}:${at('y', cy)}:eof_action=pass:${enable},format=gbrap,split${clear ? `=3` : ''}[f${next}][g${next}]${clear ? `[h${next}]` : ''}`);\n\t\t\t\t\tgraph.push(`[${cur}]format=gbrap,split${clear ? `=3` : ''}[c${next}][d${next}]${clear ? `[e${next}]` : ''}`);\n\t\t\t\t\t// ffmpeg's dodge and burn divide by the first (\"top\") input, the others test it: measured against\n\t\t\t\t\t// the CSS formulas, dodge and burn match with the layer first, the rest with the composite first.\n\t\t\t\t\tconst layerFirst = clip.blend === 'color-dodge' || clip.blend === 'color-burn';\n\t\t\t\t\tgraph.push(`${layerFirst ? `[f${next}][c${next}]` : `[c${next}][f${next}]`}blend=all_mode=${FFMPEG_BLEND[clip.blend]}[b${next}]`);\n\t\t\t\t\tgraph.push(`[g${next}]alphaextract[m${next}]`);\n\t\t\t\t\tif (clear) {\n\t\t\t\t\t\tgraph.push(`[e${next}]alphaextract[ea${next}]`);\n\t\t\t\t\t\tgraph.push(`[b${next}][ea${next}]alphamerge[bb${next}]`);\n\t\t\t\t\t\tgraph.push(`[h${next}]format=gbrp[ho${next}]`);\n\t\t\t\t\t\tgraph.push(`[ho${next}][bb${next}]overlay=format=gbrp[bm${next}]`);\n\t\t\t\t\t\tgraph.push(`[bm${next}][m${next}]alphamerge[x${next}]`);\n\t\t\t\t\t} else graph.push(`[b${next}][m${next}]alphamerge[x${next}]`);\n\t\t\t\t\tgraph.push(`[d${next}][x${next}]overlay=format=gbrp,format=yuva420p[${next}]`);\n\t\t\t\t\tblended.add(clip.blend);\n\t\t\t\t} else graph.push(`[${cur}][l${next}]overlay=${at('x', cx)}:${at('y', cy)}:eof_action=pass:${enable}[${next}]`);\n\t\t\t\tcur = next;\n\t\t\t\tconst before = clip.transition ? videoClipBefore(track, clip) : null;\n\t\t\t\tif (before && clip.transition!.type === 'dip') {\n\t\t\t\t\tconst d = clip.transition!.duration;\n\t\t\t\t\tconst dip = `d${k}`;\n\t\t\t\t\tgraph.push(`color=c=${color(clip.transition!.color ?? '#000000')}:s=${W}x${H}:r=${fps}:d=${sec(d)},format=yuva420p,fade=t=in:st=0:d=${sec(d / 2)}:alpha=1,fade=t=out:st=${sec(d / 2)}:d=${sec(d / 2)}:alpha=1,setpts=PTS+${sec(clip.start - d / 2)}/TB[l${dip}]`);\n\t\t\t\t\tgraph.push(`[${cur}][l${dip}]overlay=eof_action=pass:enable='between(t,${sec(clip.start - d / 2)},${sec(clip.start + d / 2)})'[${dip}]`);\n\t\t\t\t\tcur = dip;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn { video: cur, audio: sounds };\n\t};\n\tconst top = compose(project.tracks, measure ? null : 'base', D, { within: [], picture: !measure, sound: true });\n\tconst audio = top.audio;\n\tconst cur = top.video;\n\tif (!measure) graph.push(`[${cur}]format=yuv420p[vout]`);\n\tif (measure && !audio.length) throw new Error('Nothing on the timeline makes a sound, so there is no loudness to measure.');\n\tconst loudness = options.loudness || measure ? `,${loudnormFilter(options.loudness, measure)}` : '';\n\tif (audio.length) graph.push(`${audio.join('')}amix=inputs=${audio.length}:normalize=0:duration=longest,apad,atrim=0:${sec(D)}${loudness}[aout]`);\n\tif (options.loudness && !audio.length) notes.push('Nothing makes a sound, so there was no loudness to normalise.');\n\telse if (options.loudness && !options.loudness.measured)\n\t\tnotes.push('Loudness is normalised in one pass, which adjusts the level as it goes; for a fixed gain that keeps the dynamics, run toVideoLoudnessMeasure first and pass its result as loudness.measured.');\n\tif (allVideoTracks(project).some(({ track: t }) => t.clips.some((c) => c.type === 'media' && assets.get(c.asset)?.kind === 'video' && assets.get(c.asset)?.hasAudio === undefined)))\n\t\tnotes.push('Video assets are assumed to have sound; set \"hasAudio\": false on any that do not, or ffmpeg will stop at a missing audio stream.');\n\tif (animated.size)\n\t\tnotes.push(`Keyframed ${[...animated].sort().join(', ')} ${animated.size > 1 ? 'are' : 'is'} rendered as straight lines between keys, with eased segments sampled every two frames${animated.has('scale') ? '; animated scale needs ffmpeg 5 or later (scale with eval=frame)' : ''}.`);\n\tif (blended.has('soft-light')) notes.push(\"ffmpeg's soft-light blend uses a slightly different formula from the browser's, so the render can differ a little from the preview.\");\n\tif (ramped.has('sound')) notes.push('Sound through a speed ramp plays each stretch at its own speed, so a gliding change is heard in small steps (about every 80 ms), and freezes are silent.');\n\tif (usesDrawtext) notes.push('Titles use drawtext, which needs an ffmpeg built with libfreetype (Homebrew\\'s is not: check `ffmpeg -filters | grep drawtext`); pass titleImage to render them as images instead.');\n\tconst filterComplex = graph.join(';');\n\tif (measure) {\n\t\tconst args = ['-hide_banner', '-nostats', ...inputs.flat(), '-filter_complex', filterComplex, '-map', '[aout]', '-f', 'null', '-'];\n\t\treturn { args, command: ['ffmpeg', ...args].map(videoShellQuote).join(' '), filterComplex, duration: D, notes };\n\t}\n\tconst args = [\n\t\t'-y',\n\t\t...inputs.flat(),\n\t\t'-filter_complex',\n\t\tfilterComplex,\n\t\t'-map',\n\t\t'[vout]',\n\t\t...(audio.length ? ['-map', '[aout]', '-c:a', options.audioCodec ?? 'aac'] : ['-an']),\n\t\t'-c:v',\n\t\toptions.videoCodec ?? 'libx264',\n\t\t...((options.videoCodec ?? 'libx264') === 'libx264' ? ['-crf', String(options.crf ?? 18), '-preset', 'medium'] : []),\n\t\t'-pix_fmt',\n\t\t'yuv420p',\n\t\t'-r',\n\t\tString(fps),\n\t\t'-t',\n\t\tsec(D),\n\t\toptions.output ?? 'output.mp4'\n\t];\n\treturn { args, command: ['ffmpeg', ...args].map(videoShellQuote).join(' '), filterComplex, duration: D, notes };\n}\n"],"mappings":"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","names":["n","v","n","fmt","n","n","range","clamp01","n","input","k","cur","length","source","chain","before","next","base","into","size","args"]}