@bendyline/squisq 2.11.7 → 2.11.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{Doc-BkxT7G80.d.ts → Doc-CynsGqL4.d.ts} +208 -1
- package/dist/{ImageEditDoc-C8ZB54Vv.d.ts → ImageEditDoc-BVZe_5y4.d.ts} +1 -1
- package/dist/{chunk-SKKBRLLM.js → chunk-5FBI3ZW4.js} +7 -42
- package/dist/{chunk-YGGYYBJS.js → chunk-JJO6JFNZ.js} +1 -1
- package/dist/{chunk-SOIV7KDO.js → chunk-JM2QARY2.js} +42 -10
- package/dist/chunk-JSGIWW35.js +70 -0
- package/dist/{chunk-IYZTF4VO.js → chunk-KFZOCWPK.js} +2 -2
- package/dist/chunk-L7QZORLB.js +230 -0
- package/dist/chunk-NEWNNLWN.js +64 -0
- package/dist/{chunk-6ECMNUIP.js → chunk-OU5FYBOB.js} +170 -4
- package/dist/{chunk-3YNFMFNK.js → chunk-RMCUZDW5.js} +17 -8
- package/dist/{chunk-XJXBI3N5.js → chunk-XZVBR5BP.js} +1 -1
- package/dist/{chunk-GAZKTT4R.js → chunk-YNO6JV36.js} +96 -33
- package/dist/{chunk-EF353KGH.js → chunk-ZEONJCP3.js} +1 -1
- package/dist/doc/index.d.ts +5 -5
- package/dist/doc/index.js +22 -20
- package/dist/fence/index.d.ts +1 -1
- package/dist/generate/index.d.ts +1 -1
- package/dist/imageEdit/index.d.ts +47 -4
- package/dist/imageEdit/index.js +5 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +48 -39
- package/dist/jsonForm/index.d.ts +1 -1
- package/dist/jsonForm/index.js +4 -2
- package/dist/markdown/index.js +3 -3
- package/dist/{materializePageSection-Dp2aHFbc.d.ts → materializePageSection-CAJoa8fh.d.ts} +1 -1
- package/dist/mediaEdit/index.d.ts +467 -0
- package/dist/mediaEdit/index.js +990 -0
- package/dist/narration/index.d.ts +20 -12
- package/dist/narration/index.js +6 -4
- package/dist/schemas/index.d.ts +4 -4
- package/dist/schemas/index.js +7 -3
- package/dist/{themeLibrary-BbSjnGmd.d.ts → themeLibrary-z7t3x5CU.d.ts} +1 -1
- package/dist/timing/index.d.ts +1 -1
- package/dist/transform/index.d.ts +2 -2
- package/dist/transform/index.js +6 -5
- package/package.json +6 -1
- package/dist/{chunk-CW24CH7I.js → chunk-HUXK7EOT.js} +3 -3
|
@@ -1,5 +1,158 @@
|
|
|
1
1
|
import { a3 as Transition, a5 as TransitionType, M as MarkdownBlockNode, r as MarkdownHeading } from './types-Be6sBUBx.js';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Media-edit recipes — the non-destructive edit list a media reference carries.
|
|
5
|
+
*
|
|
6
|
+
* A recipe lives in the markdown, as parameters on the `{[audio|video …]}`
|
|
7
|
+
* annotation or `data-squisq-{audio|video}-*` attributes on a standalone
|
|
8
|
+
* `<audio>` / `<video>` tag. The source file is never modified: timeline ops
|
|
9
|
+
* (`cuts`, `gain`, `fadeIn`, `fadeOut`, `crop`) are applied at playback and
|
|
10
|
+
* export, and the signal chain (`fx`) is rendered into a derived, time-aligned
|
|
11
|
+
* audio file (see `renderStore.ts`). Undo is therefore the editor's ordinary
|
|
12
|
+
* undo, and a reference with no recipe behaves exactly as before.
|
|
13
|
+
*
|
|
14
|
+
* Pure and dependency-free: runs in the browser and in Node.
|
|
15
|
+
*/
|
|
16
|
+
/** Signal operations, in the FIXED order the chain applies them. */
|
|
17
|
+
declare const MEDIA_FX_ORDER: readonly ["highpass", "denoise", "debreath", "loudness"];
|
|
18
|
+
type MediaFxOpId = (typeof MEDIA_FX_ORDER)[number];
|
|
19
|
+
interface MediaFxOpSpec {
|
|
20
|
+
/** Value used when the token carries none (`denoise` ≡ `denoise:0.8`). */
|
|
21
|
+
defaultValue: number;
|
|
22
|
+
min: number;
|
|
23
|
+
max: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Parameter contract per op. Values are clamped into range on parse, so a
|
|
27
|
+
* recipe always describes something the engine can render.
|
|
28
|
+
*
|
|
29
|
+
* - `highpass` — corner frequency in Hz.
|
|
30
|
+
* - `denoise` — wet/dry strength, 0…1.
|
|
31
|
+
* - `debreath` — attenuation applied to detected breaths, in dB (≤ 0).
|
|
32
|
+
* - `loudness` — integrated loudness target in LUFS.
|
|
33
|
+
*/
|
|
34
|
+
declare const MEDIA_FX_SPECS: Readonly<Record<MediaFxOpId, MediaFxOpSpec>>;
|
|
35
|
+
interface MediaFxOp {
|
|
36
|
+
id: MediaFxOpId;
|
|
37
|
+
value: number;
|
|
38
|
+
}
|
|
39
|
+
interface MediaFxChain {
|
|
40
|
+
/** Known ops, de-duplicated (last wins) and in {@link MEDIA_FX_ORDER}. */
|
|
41
|
+
ops: MediaFxOp[];
|
|
42
|
+
/**
|
|
43
|
+
* Tokens this engine does not understand, preserved verbatim so a recipe
|
|
44
|
+
* written by a newer engine survives a round-trip through an older one.
|
|
45
|
+
* They are never rendered.
|
|
46
|
+
*/
|
|
47
|
+
unknown: string[];
|
|
48
|
+
}
|
|
49
|
+
/** A removed range of the SOURCE file, in seconds (`start < end`). */
|
|
50
|
+
interface MediaCut {
|
|
51
|
+
start: number;
|
|
52
|
+
end: number;
|
|
53
|
+
}
|
|
54
|
+
/** A crop rectangle, normalized to the source frame (0…1 on each axis). */
|
|
55
|
+
interface MediaCrop {
|
|
56
|
+
x: number;
|
|
57
|
+
y: number;
|
|
58
|
+
w: number;
|
|
59
|
+
h: number;
|
|
60
|
+
}
|
|
61
|
+
/** The complete recipe a media reference can carry. Every field is optional. */
|
|
62
|
+
interface MediaEdits {
|
|
63
|
+
fx?: MediaFxChain;
|
|
64
|
+
/** Normalized: sorted, merged, non-overlapping. */
|
|
65
|
+
cuts?: MediaCut[];
|
|
66
|
+
/** Clip gain in dB. */
|
|
67
|
+
gain?: number;
|
|
68
|
+
/** Fade-in length in seconds, at the start of the played clip. */
|
|
69
|
+
fadeIn?: number;
|
|
70
|
+
/** Fade-out length in seconds, at the end of the played clip. */
|
|
71
|
+
fadeOut?: number;
|
|
72
|
+
crop?: MediaCrop;
|
|
73
|
+
/**
|
|
74
|
+
* Links companion clips (a screen + camera capture, a narration audio +
|
|
75
|
+
* video pair). Editors propagate cuts, trims and `fx` across a group.
|
|
76
|
+
*/
|
|
77
|
+
group?: string;
|
|
78
|
+
}
|
|
79
|
+
/** Raw string values of a recipe, keyed by {@link MediaEditParamKey}. */
|
|
80
|
+
type MediaEditParamValues = Partial<Record<MediaEditParamKey, string>>;
|
|
81
|
+
type MediaEditParamKey = 'fx' | 'cuts' | 'gain' | 'fadeIn' | 'fadeOut' | 'crop' | 'group';
|
|
82
|
+
/**
|
|
83
|
+
* Every recipe parameter with its two spellings: the annotation key
|
|
84
|
+
* (`fadeIn=0.3`) and the HTML attribute suffix, appended to the per-kind
|
|
85
|
+
* prefix (`data-squisq-video-fade-in="0.3"`). The order is the canonical
|
|
86
|
+
* serialization order.
|
|
87
|
+
*/
|
|
88
|
+
declare const MEDIA_EDIT_PARAMS: ReadonlyArray<{
|
|
89
|
+
key: MediaEditParamKey;
|
|
90
|
+
htmlSuffix: string;
|
|
91
|
+
}>;
|
|
92
|
+
/** `data-squisq-video-fade-in` for (`video`, `fadeIn`). */
|
|
93
|
+
declare function mediaEditHtmlAttribute(kind: 'audio' | 'video', key: MediaEditParamKey): string;
|
|
94
|
+
/** Compact, stable decimal: at most `digits` fraction digits, no `-0`. */
|
|
95
|
+
declare function formatMediaNumber(value: number, digits?: number): string;
|
|
96
|
+
/**
|
|
97
|
+
* Parse an `fx` value (`"highpass:80 denoise debreath:-15"`). Tokens split on
|
|
98
|
+
* whitespace or commas. A known op with a missing value gets its default; a
|
|
99
|
+
* known op with an unparseable value is kept verbatim in `unknown` rather
|
|
100
|
+
* than guessed at. `debreath:15` is read as −15 dB (attenuation is the only
|
|
101
|
+
* meaningful direction). Returns null when the value holds no tokens.
|
|
102
|
+
*/
|
|
103
|
+
declare function parseMediaFx(raw: string | undefined): MediaFxChain | null;
|
|
104
|
+
/**
|
|
105
|
+
* Canonical `fx` string: known ops in chain order with explicit values, then
|
|
106
|
+
* unknown tokens in their authored order. Explicit values keep a recipe's
|
|
107
|
+
* meaning stable even if a later engine changes a default.
|
|
108
|
+
*/
|
|
109
|
+
declare function serializeMediaFx(chain: MediaFxChain): string;
|
|
110
|
+
/** True when the chain would render anything (it has at least one known op). */
|
|
111
|
+
declare function hasRenderableFx(chain: MediaFxChain | undefined): chain is MediaFxChain;
|
|
112
|
+
/**
|
|
113
|
+
* Sort, merge overlapping or touching ranges, and drop empty ones. When a
|
|
114
|
+
* `[windowStart, windowEnd]` source window is given (the clip's trim), cuts
|
|
115
|
+
* are clamped into it and anything outside is dropped.
|
|
116
|
+
*/
|
|
117
|
+
declare function normalizeMediaCuts(cuts: readonly MediaCut[], windowStart?: number, windowEnd?: number): MediaCut[];
|
|
118
|
+
/**
|
|
119
|
+
* Parse `"12.4-13.1 40.2-41"` (also `1:02-1:04.5`, comma separated). Invalid
|
|
120
|
+
* ranges are dropped. Returns null when nothing valid remains.
|
|
121
|
+
*/
|
|
122
|
+
declare function parseMediaCuts(raw: string | undefined): MediaCut[] | null;
|
|
123
|
+
declare function serializeMediaCuts(cuts: readonly MediaCut[]): string;
|
|
124
|
+
/**
|
|
125
|
+
* Parse `"x y w h"` (fractions of the source frame). The rectangle is clamped
|
|
126
|
+
* inside the frame. A full-frame rectangle means "no crop" and returns null.
|
|
127
|
+
*/
|
|
128
|
+
declare function parseMediaCrop(raw: string | undefined): MediaCrop | null;
|
|
129
|
+
/** Clamp a crop rectangle into the frame; null when it covers the whole frame. */
|
|
130
|
+
declare function normalizeMediaCrop(crop: MediaCrop): MediaCrop | null;
|
|
131
|
+
declare function serializeMediaCrop(crop: MediaCrop): string;
|
|
132
|
+
/**
|
|
133
|
+
* Parse a recipe from raw parameter values. Invalid fields are dropped
|
|
134
|
+
* (never guessed); neutral values (`gain=0`, `fadeIn=0`, full-frame crop)
|
|
135
|
+
* are dropped too. Returns undefined when nothing remains, so callers can
|
|
136
|
+
* leave `MediaClip.edits` unset for an unedited reference.
|
|
137
|
+
*/
|
|
138
|
+
declare function parseMediaEdits(values: MediaEditParamValues): MediaEdits | undefined;
|
|
139
|
+
/**
|
|
140
|
+
* Serialize a recipe to raw parameter values. A key maps to `null` when its
|
|
141
|
+
* field is absent, so a writer can remove a stale attribute with the same
|
|
142
|
+
* call that sets the others.
|
|
143
|
+
*/
|
|
144
|
+
declare function serializeMediaEdits(edits: MediaEdits | undefined): Record<MediaEditParamKey, string | null>;
|
|
145
|
+
/** Read recipe values from annotation params (`fx=…`, `fadeIn=…`). */
|
|
146
|
+
declare function mediaEditValuesFromParams(params: Record<string, string>): MediaEditParamValues;
|
|
147
|
+
/** Read recipe values from HTML attributes (`data-squisq-video-fade-in=…`). */
|
|
148
|
+
declare function mediaEditValuesFromAttributes(kind: 'audio' | 'video', attributes: Record<string, string>): MediaEditParamValues;
|
|
149
|
+
/**
|
|
150
|
+
* Stable key naming the render of `src` under `fx`. Only the known, canonical
|
|
151
|
+
* ops take part — unknown tokens are not rendered, so they must not force a
|
|
152
|
+
* re-render (the render manifest records them instead). 12 hex digits.
|
|
153
|
+
*/
|
|
154
|
+
declare function mediaRenderKey(src: string, fx: MediaFxChain): string;
|
|
155
|
+
|
|
3
156
|
/**
|
|
4
157
|
* Media-clip timing model.
|
|
5
158
|
*
|
|
@@ -76,6 +229,11 @@ interface MediaClip {
|
|
|
76
229
|
* timed relative to the document start and able to span every block.
|
|
77
230
|
*/
|
|
78
231
|
anchor: 'block' | 'document';
|
|
232
|
+
/**
|
|
233
|
+
* Non-destructive edit recipe (`fx`, `cuts`, `gain`, fades, `crop`,
|
|
234
|
+
* `group`). Absent for an unedited reference. See `@bendyline/squisq/mediaEdit`.
|
|
235
|
+
*/
|
|
236
|
+
edits?: MediaEdits;
|
|
79
237
|
/**
|
|
80
238
|
* 1-based source line of the authoring annotation, when derived from
|
|
81
239
|
* markdown. Enables round-tripping edits (e.g. the timeline editor rewriting
|
|
@@ -128,6 +286,36 @@ interface ScheduledClip {
|
|
|
128
286
|
blockId?: string;
|
|
129
287
|
/** 1-based source line of the authoring annotation, when known. */
|
|
130
288
|
sourceLine?: number;
|
|
289
|
+
/** Clip gain in dB (from the recipe). */
|
|
290
|
+
gain?: number;
|
|
291
|
+
/** Fade-in seconds at this entry's start (first segment of a cut clip only). */
|
|
292
|
+
fadeIn?: number;
|
|
293
|
+
/** Fade-out seconds at this entry's end (last segment of a cut clip only). */
|
|
294
|
+
fadeOut?: number;
|
|
295
|
+
/** Normalized crop rectangle for a video clip. */
|
|
296
|
+
crop?: MediaCrop;
|
|
297
|
+
/**
|
|
298
|
+
* True when a video's own audio track must stay silent because a processed
|
|
299
|
+
* companion audio entry (see {@link ScheduledClip.derivedFrom}) plays in its place.
|
|
300
|
+
*/
|
|
301
|
+
audioMuted?: boolean;
|
|
302
|
+
/**
|
|
303
|
+
* Set on the processed companion audio entry emitted for an edited video:
|
|
304
|
+
* the id of the clip whose audio it replaces. Timeline UIs hide these.
|
|
305
|
+
*/
|
|
306
|
+
derivedFrom?: string;
|
|
307
|
+
/** The source reference before processed-audio substitution. */
|
|
308
|
+
originalSrc?: string;
|
|
309
|
+
/**
|
|
310
|
+
* Present when a clip with cuts was expanded into contiguous entries, one
|
|
311
|
+
* per kept source range. `groupId` is the authored clip's id; entries of
|
|
312
|
+
* one group play the same source back to back.
|
|
313
|
+
*/
|
|
314
|
+
segment?: {
|
|
315
|
+
groupId: string;
|
|
316
|
+
index: number;
|
|
317
|
+
count: number;
|
|
318
|
+
};
|
|
131
319
|
}
|
|
132
320
|
/** Options for {@link resolveMediaSchedule} / {@link getDocPlaybackDuration}. */
|
|
133
321
|
interface MediaScheduleOptions {
|
|
@@ -146,7 +334,26 @@ interface MediaScheduleOptions {
|
|
|
146
334
|
* block by design.
|
|
147
335
|
*/
|
|
148
336
|
intrinsicDuration?: (clip: MediaClip) => number | undefined;
|
|
337
|
+
/**
|
|
338
|
+
* Optional lookup of a clip's processed (rendered `fx`) audio. When it
|
|
339
|
+
* returns a path, an audio clip plays that path instead of its source, and a
|
|
340
|
+
* video clip keeps its picture but mutes its own audio while a companion
|
|
341
|
+
* audio entry plays the processed track with identical timing. Renders are
|
|
342
|
+
* sample-aligned with the source, so no timing changes.
|
|
343
|
+
*
|
|
344
|
+
* Return undefined when no current render exists (the default when no
|
|
345
|
+
* lookup is wired): the clip then plays its original audio.
|
|
346
|
+
*/
|
|
347
|
+
processedAudio?: (clip: MediaClip) => string | undefined;
|
|
149
348
|
}
|
|
349
|
+
/**
|
|
350
|
+
* Schedule one clip that occupies `[start, end)` on the doc timeline, honoring
|
|
351
|
+
* its recipe (cuts → contiguous segment entries, gain/fades/crop, processed
|
|
352
|
+
* audio). {@link resolveMediaSchedule} uses this for every annotated clip;
|
|
353
|
+
* hosts that schedule media from other sources (body-embedded `<audio>` /
|
|
354
|
+
* `<video>` tags) call it so edits behave identically there.
|
|
355
|
+
*/
|
|
356
|
+
declare function scheduleMediaClip(clip: MediaClip, start: number, end: number, anchor: 'block' | 'document', blockId?: string, opts?: MediaScheduleOptions): ScheduledClip[];
|
|
150
357
|
/**
|
|
151
358
|
* Flatten every block clip and document clip into absolute-timed
|
|
152
359
|
* `ScheduledClip`s. Pure — depends only on `doc` (plus the optional intrinsic
|
|
@@ -2847,4 +3054,4 @@ declare function getBlockAtTime(blocks: Block[], time: number): Block | null;
|
|
|
2847
3054
|
*/
|
|
2848
3055
|
declare function getCaptionAtTime(captions: CaptionTrack | undefined, time: number): CaptionPhrase | null;
|
|
2849
3056
|
|
|
2850
|
-
export { type ImageLayer as $, type AccentImage as A, type BarChartInput as B, type CaptionPhrase as C, DARK_SURFACE as D, DEFAULT_DOC_FONT as E, DEFAULT_TITLE_FONT as F, type DataTableInput as G, type DateEventInput as H, type DeepPartial as I, type DefinitionCardInput as J, type DiagramBlockInput as K, type DiagramEdgeAnchor as L, type DiagramTemplateEdge as M, type DiagramTemplateNode as N, type Doc as O, type DocBlock as P, type DocDiagnostic as Q, type DonutChartInput as R, type DrawingBlockInput as S, FRONTMATTER_CUSTOM_TEMPLATES_KEY as T, FRONTMATTER_CUSTOM_THEMES_KEY as U, type FactCardInput as V, type FontFamily as W, type FontFamilyKind as X, type FullBleedQuoteInput as Y, type GradientBackgroundConfig as Z, type ImageBackgroundConfig as _, type AccentPosition as a, type
|
|
3057
|
+
export { type ImageLayer as $, type AccentImage as A, type BarChartInput as B, type CaptionPhrase as C, DARK_SURFACE as D, DEFAULT_DOC_FONT as E, DEFAULT_TITLE_FONT as F, type DataTableInput as G, type DateEventInput as H, type DeepPartial as I, type DefinitionCardInput as J, type DiagramBlockInput as K, type DiagramEdgeAnchor as L, type DiagramTemplateEdge as M, type DiagramTemplateNode as N, type Doc as O, type DocBlock as P, type DocDiagnostic as Q, type DonutChartInput as R, type DrawingBlockInput as S, FRONTMATTER_CUSTOM_TEMPLATES_KEY as T, FRONTMATTER_CUSTOM_THEMES_KEY as U, type FactCardInput as V, type FontFamily as W, type FontFamilyKind as X, type FullBleedQuoteInput as Y, type GradientBackgroundConfig as Z, type ImageBackgroundConfig as _, type AccentPosition as a, type RenderStyle as a$, type ImageTreatment as a0, type ImageWithCaptionInput as a1, LIGHT_SURFACE as a2, type Layer as a3, type LayerRepeat as a4, type LayoutHints as a5, type LeftFeatureInput as a6, type LineChartInput as a7, type LinearGradient as a8, type ListBlockInput as a9, PAGE_SECTION_KINDS as aA, PAGE_SECTION_SPACINGS as aB, PAGE_SHADOWS as aC, type PageAccentRotation as aD, type PageBackground as aE, type PageDesignFamily as aF, type PageEmphasis as aG, type PageHeadingTreatment as aH, type PageSectionKind as aI, type PageSectionOverride as aJ, type PageTokens as aK, type PathLayer as aL, type PatternBackgroundConfig as aM, type PersistentLayer as aN, type PersistentLayerConfig as aO, type PersistentLayerTemplate as aP, type PersistentLayerTemplateConfig as aQ, type PersistentLayerTemplateType as aR, type PhotoGridInput as aS, type PieChartInput as aT, type PipStyle as aU, type Position as aV, type ProgressIndicatorConfig as aW, type PromotedBodyAnnotation as aX, type PullQuoteInput as aY, type QuoteBlockInput as aZ, type RawLayersInput as a_, type MapBlockInput as aa, type MapLayer as ab, type MapMarker as ac, type MapTileStyle as ad, type MarkerStyle as ae, type MediaClip as af, type MediaCrop as ag, type MediaCut as ah, type MediaEdits as ai, type MediaScheduleOptions as aj, type MermaidLayer as ak, PAGE_ACCENT_STRATEGIES as al, PAGE_BACKGROUNDS as am, PAGE_BACKGROUND_RHYTHMS as an, PAGE_DESIGN_FAMILIES as ao, PAGE_DIVIDERS as ap, PAGE_EMPHASES as aq, PAGE_EYEBROWS as ar, PAGE_HEADING_CASES as as, PAGE_HEADING_SCALES as at, PAGE_HEADING_UNDERLINES as au, PAGE_HERO_STYLES as av, PAGE_IMAGE_FRAMINGS as aw, PAGE_NUMERAL_STYLES as ax, PAGE_PATTERNS as ay, PAGE_QUOTE_MARKS as az, type AmbientGradientConfig as b, getCaptionAtTime as b$, type RightFeatureInput as b0, type ScatterChartInput as b1, type ScheduledClip as b2, type SectionHeaderInput as b3, type ShapeFilter as b4, type ShapeLayer as b5, type ShapePattern as b6, type SolidBackgroundConfig as b7, type StartBlockConfig as b8, type StatHighlightInput as b9, type TreeBlockInput as bA, type TreeLayer as bB, type TreeLayerItem as bC, type TreeLayerStyle as bD, type TreeTemplateItem as bE, type TwoColumnInput as bF, VIEWPORT_PRESETS as bG, type VideoLayer as bH, type VideoPipPosition as bI, type VideoPipShape as bJ, type VideoPipSize as bK, type VideoPlacement as bL, type VideoPresentation as bM, type VideoPullQuoteInput as bN, type VideoWithCaptionInput as bO, type ViewportConfig as bP, type ViewportOrientation as bQ, type ViewportPreset as bR, type VignetteConfig as bS, applySurface as bT, calculateDuration as bU, calculateFontScale as bV, createTemplateContext as bW, createTheme as bX, createThemeRegistry as bY, getAspectRatioString as bZ, getBlockAtTime as b_, type SurfaceScheme as ba, THEME_SCHEMA_VERSION as bb, type TableLayer as bc, type TableLayerStyle as bd, type TemplateBlock as be, type TemplateContext as bf, type TemplateFunction as bg, type TemplateRegistry as bh, type TextLayer as bi, type TextStyle as bj, type Theme as bk, type ThemeColorPalette as bl, type ThemeColorScheme as bm, type ThemePageStyle as bn, type ThemeRegistry as bo, type ThemeSchemaVersion as bp, type ThemeSeedColors as bq, type ThemeStyle as br, type ThemeTypography as bs, type TimelineBlockInput as bt, type TimelineTemplateEvent as bu, type TimelineTemplateLink as bv, type TimelineTemplateTrack as bw, type TitleBlockInput as bx, type TitleCaptionConfig as by, type TranscriptBlockInput as bz, type Animation as c, getDocPlaybackDuration as c0, getLayoutHints as c1, getSafeTextBounds as c2, getSegmentAtTime as c3, getTwoColumnPositions as c4, getViewport as c5, getViewportOrientation as c6, isCustomTemplateDefinition as c7, isPersistentLayerTemplate as c8, isTemplateBlock as c9, serializeMediaCuts as cA, serializeMediaEdits as cB, serializeMediaFx as cC, scaledFontSize$1 as ca, resolveMediaSchedule as cb, scaledFontSize as cc, scheduleMediaClip as cd, validateCustomTemplateDefinition as ce, type MediaFxOpId as cf, type MediaFxChain as cg, MEDIA_EDIT_PARAMS as ch, MEDIA_FX_ORDER as ci, MEDIA_FX_SPECS as cj, type MediaEditParamKey as ck, type MediaEditParamValues as cl, type MediaFxOp as cm, formatMediaNumber as cn, hasRenderableFx as co, mediaEditHtmlAttribute as cp, mediaEditValuesFromAttributes as cq, mediaEditValuesFromParams as cr, mediaRenderKey as cs, normalizeMediaCrop as ct, normalizeMediaCuts as cu, parseMediaCrop as cv, parseMediaCuts as cw, parseMediaEdits as cx, parseMediaFx as cy, serializeMediaCrop as cz, type AnimationType as d, type AreaChartInput as e, type AudioBookmark as f, type AudioSegment as g, type AudioTimingData as h, type AudioTrack as i, type BigTextInput as j, type Block as k, type BlockConnection as l, type BorderStyle as m, type CaptionTrack as n, type CaptionWord as o, type ChartBaseFields as p, type ChartTemplateInput as q, type ColorScheme as r, type ColumnChartInput as s, type ComparisonBarInput as t, type ContentBlockInput as u, type CornerBrandingConfig as v, type CustomTemplateDefinition as w, type CustomTemplateLayer as x, type CustomTemplateValidationError as y, type CustomTemplateValidationResult as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as ImageLayer,
|
|
1
|
+
import { $ as ImageLayer, bi as TextLayer, b5 as ShapeLayer, aL as PathLayer } from './Doc-CynsGqL4.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* ImageEditDoc — JSON document describing a layered, editable image.
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
biquadRun,
|
|
3
|
+
highpassCoeffs,
|
|
4
|
+
lowpassCoeffs
|
|
5
|
+
} from "./chunk-NEWNNLWN.js";
|
|
1
6
|
import {
|
|
2
7
|
buildNarrationScript,
|
|
3
8
|
expectedSyllablesAt,
|
|
4
9
|
wordPosAtExpectedSyllables
|
|
5
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-ZEONJCP3.js";
|
|
6
11
|
import {
|
|
7
12
|
flattenRenderableBlocks
|
|
8
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-RMCUZDW5.js";
|
|
9
14
|
|
|
10
15
|
// src/narration/types.ts
|
|
11
16
|
var DEFAULT_FEATURE_CONFIG = Object.freeze({
|
|
@@ -71,32 +76,6 @@ var DEFAULT_ALIGN_CONFIG = Object.freeze({
|
|
|
71
76
|
});
|
|
72
77
|
|
|
73
78
|
// src/narration/features.ts
|
|
74
|
-
function highpassCoeffs(sampleRate, freqHz) {
|
|
75
|
-
const w0 = 2 * Math.PI * freqHz / sampleRate;
|
|
76
|
-
const cosW0 = Math.cos(w0);
|
|
77
|
-
const alpha = Math.sin(w0) / (2 * Math.SQRT1_2);
|
|
78
|
-
const a0 = 1 + alpha;
|
|
79
|
-
return {
|
|
80
|
-
b0: (1 + cosW0) / 2 / a0,
|
|
81
|
-
b1: -(1 + cosW0) / a0,
|
|
82
|
-
b2: (1 + cosW0) / 2 / a0,
|
|
83
|
-
a1: -2 * cosW0 / a0,
|
|
84
|
-
a2: (1 - alpha) / a0
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
function lowpassCoeffs(sampleRate, freqHz) {
|
|
88
|
-
const w0 = 2 * Math.PI * freqHz / sampleRate;
|
|
89
|
-
const cosW0 = Math.cos(w0);
|
|
90
|
-
const alpha = Math.sin(w0) / (2 * Math.SQRT1_2);
|
|
91
|
-
const a0 = 1 + alpha;
|
|
92
|
-
return {
|
|
93
|
-
b0: (1 - cosW0) / 2 / a0,
|
|
94
|
-
b1: (1 - cosW0) / a0,
|
|
95
|
-
b2: (1 - cosW0) / 2 / a0,
|
|
96
|
-
a1: -2 * cosW0 / a0,
|
|
97
|
-
a2: (1 - alpha) / a0
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
79
|
function createBandpass(sampleRate, lowHz = DEFAULT_FEATURE_CONFIG.bandLowHz, highHz = DEFAULT_FEATURE_CONFIG.bandHighHz) {
|
|
101
80
|
return {
|
|
102
81
|
coeffs: { hp: highpassCoeffs(sampleRate, lowHz), lp: lowpassCoeffs(sampleRate, highHz) },
|
|
@@ -104,20 +83,6 @@ function createBandpass(sampleRate, lowHz = DEFAULT_FEATURE_CONFIG.bandLowHz, hi
|
|
|
104
83
|
lp: { x1: 0, x2: 0, y1: 0, y2: 0 }
|
|
105
84
|
};
|
|
106
85
|
}
|
|
107
|
-
function biquadRun(coeffs, state, input, output) {
|
|
108
|
-
let { x1, x2, y1, y2 } = state;
|
|
109
|
-
const { b0, b1, b2, a1, a2 } = coeffs;
|
|
110
|
-
for (let i = 0; i < input.length; i++) {
|
|
111
|
-
const x0 = input[i];
|
|
112
|
-
const y0 = b0 * x0 + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2;
|
|
113
|
-
output[i] = y0;
|
|
114
|
-
x2 = x1;
|
|
115
|
-
x1 = x0;
|
|
116
|
-
y2 = y1;
|
|
117
|
-
y1 = y0;
|
|
118
|
-
}
|
|
119
|
-
return { x1, x2, y1, y2 };
|
|
120
|
-
}
|
|
121
86
|
function bandpassRun(state, input, output) {
|
|
122
87
|
const hp = biquadRun(state.coeffs.hp, state.hp, input, output);
|
|
123
88
|
const lp = biquadRun(state.coeffs.lp, state.lp, output, output);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildNarrationScript,
|
|
3
3
|
parseNarrationTimingJson
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ZEONJCP3.js";
|
|
5
5
|
import {
|
|
6
6
|
SHAPE_NAMES,
|
|
7
7
|
buildChartData,
|
|
@@ -32,10 +32,7 @@ import {
|
|
|
32
32
|
templateRegistry,
|
|
33
33
|
writeCustomTemplatesToFrontmatter,
|
|
34
34
|
writeCustomThemesToFrontmatter
|
|
35
|
-
} from "./chunk-
|
|
36
|
-
import {
|
|
37
|
-
iconMarker
|
|
38
|
-
} from "./chunk-7ZAAICW4.js";
|
|
35
|
+
} from "./chunk-RMCUZDW5.js";
|
|
39
36
|
import {
|
|
40
37
|
ASCII_TREE_VOCAB,
|
|
41
38
|
ASCII_VOCAB,
|
|
@@ -53,10 +50,13 @@ import {
|
|
|
53
50
|
toGrid,
|
|
54
51
|
traceBoxes
|
|
55
52
|
} from "./chunk-C3NAY5YP.js";
|
|
53
|
+
import {
|
|
54
|
+
iconMarker
|
|
55
|
+
} from "./chunk-7ZAAICW4.js";
|
|
56
56
|
import {
|
|
57
57
|
defaultPageStyle,
|
|
58
58
|
resolveMediaSchedule
|
|
59
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-YNO6JV36.js";
|
|
60
60
|
import {
|
|
61
61
|
DEFAULT_THEME,
|
|
62
62
|
FRONTMATTER_CUSTOM_TEMPLATES_KEY,
|
|
@@ -74,9 +74,15 @@ import {
|
|
|
74
74
|
resolveTheme,
|
|
75
75
|
withAlpha
|
|
76
76
|
} from "./chunk-Y4D6TDZT.js";
|
|
77
|
+
import {
|
|
78
|
+
createMediaTimeMap
|
|
79
|
+
} from "./chunk-JSGIWW35.js";
|
|
80
|
+
import {
|
|
81
|
+
serializeMediaEdits
|
|
82
|
+
} from "./chunk-L7QZORLB.js";
|
|
77
83
|
import {
|
|
78
84
|
parseMarkdown
|
|
79
|
-
} from "./chunk-
|
|
85
|
+
} from "./chunk-HUXK7EOT.js";
|
|
80
86
|
import {
|
|
81
87
|
KNOWN_BLOCK_META_KEYS,
|
|
82
88
|
TABLE_FED_TEMPLATES,
|
|
@@ -596,6 +602,9 @@ function synthesizeMediaParagraph(clip) {
|
|
|
596
602
|
if (clip.clipStart != null) params.clipStart = String(clip.clipStart);
|
|
597
603
|
if (clip.clipEnd != null) params.clipEnd = String(clip.clipEnd);
|
|
598
604
|
if (clip.spillover) params.spillover = "true";
|
|
605
|
+
for (const [key, value] of Object.entries(serializeMediaEdits(clip.edits))) {
|
|
606
|
+
if (value != null) params[key] = value;
|
|
607
|
+
}
|
|
599
608
|
return {
|
|
600
609
|
type: "paragraph",
|
|
601
610
|
children: [{ type: "text", value: serializeAnnotation(clip.kind, params) }]
|
|
@@ -3976,6 +3985,26 @@ function proportionalRanges(doc, timing) {
|
|
|
3976
3985
|
});
|
|
3977
3986
|
return ranges;
|
|
3978
3987
|
}
|
|
3988
|
+
function narrationTimeMap(clip, takeDuration) {
|
|
3989
|
+
const trimmed = clip.clipStart != null || clip.clipEnd != null;
|
|
3990
|
+
if (!trimmed && !clip.edits?.cuts?.length) return null;
|
|
3991
|
+
return createMediaTimeMap({
|
|
3992
|
+
clipStart: clip.clipStart,
|
|
3993
|
+
clipEnd: clip.clipEnd,
|
|
3994
|
+
cuts: clip.edits?.cuts,
|
|
3995
|
+
sourceDuration: takeDuration
|
|
3996
|
+
});
|
|
3997
|
+
}
|
|
3998
|
+
function mapRangesToPlayed(ranges, map2) {
|
|
3999
|
+
const mapped = /* @__PURE__ */ new Map();
|
|
4000
|
+
for (const [blockId, range] of ranges) {
|
|
4001
|
+
mapped.set(blockId, {
|
|
4002
|
+
startSec: map2.snapSourceToPlayed(range.startSec),
|
|
4003
|
+
endSec: map2.snapSourceToPlayed(range.endSec)
|
|
4004
|
+
});
|
|
4005
|
+
}
|
|
4006
|
+
return mapped;
|
|
4007
|
+
}
|
|
3979
4008
|
function retimeBlocks(blocks, ctx) {
|
|
3980
4009
|
return blocks.map((block) => {
|
|
3981
4010
|
const range = ctx.ranges.get(block.id);
|
|
@@ -4018,8 +4047,11 @@ async function applyNarrationTiming(doc, container) {
|
|
|
4018
4047
|
const timing = parseNarrationTimingJson(sidecarData);
|
|
4019
4048
|
if (!timing) continue;
|
|
4020
4049
|
const flat = flattenRenderableBlocks(doc.blocks);
|
|
4021
|
-
const
|
|
4022
|
-
if (!
|
|
4050
|
+
const takeRanges = timing.blocks.length > 0 ? matchSidecarBlocks(flat, timing) : proportionalRanges(doc, timing);
|
|
4051
|
+
if (!takeRanges || takeRanges.size === 0) continue;
|
|
4052
|
+
const timeMap = narrationTimeMap(clip, timing.duration);
|
|
4053
|
+
const ranges = timeMap ? mapRangesToPlayed(takeRanges, timeMap) : takeRanges;
|
|
4054
|
+
const playedDuration = timeMap ? timeMap.playedDuration : timing.duration;
|
|
4023
4055
|
const ctx = {
|
|
4024
4056
|
clipStart: clip.startAt,
|
|
4025
4057
|
ranges,
|
|
@@ -4028,7 +4060,7 @@ async function applyNarrationTiming(doc, container) {
|
|
|
4028
4060
|
shift: 0
|
|
4029
4061
|
};
|
|
4030
4062
|
const blocks = retimeBlocks(doc.blocks, ctx);
|
|
4031
|
-
const duration = Math.max(clip.startAt +
|
|
4063
|
+
const duration = Math.max(clip.startAt + playedDuration, ctx.cursor);
|
|
4032
4064
|
const retimed = {
|
|
4033
4065
|
...doc,
|
|
4034
4066
|
blocks,
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import {
|
|
2
|
+
normalizeMediaCuts
|
|
3
|
+
} from "./chunk-L7QZORLB.js";
|
|
4
|
+
|
|
5
|
+
// src/mediaEdit/timeMap.ts
|
|
6
|
+
function createMediaTimeMap(input) {
|
|
7
|
+
const windowStart = Math.max(0, input.clipStart ?? 0);
|
|
8
|
+
let windowEnd = input.clipEnd ?? Number.POSITIVE_INFINITY;
|
|
9
|
+
if (input.sourceDuration != null && Number.isFinite(input.sourceDuration)) {
|
|
10
|
+
windowEnd = Math.min(windowEnd, input.sourceDuration);
|
|
11
|
+
}
|
|
12
|
+
windowEnd = Math.max(windowStart, windowEnd);
|
|
13
|
+
const cuts = normalizeMediaCuts(input.cuts ?? [], windowStart, windowEnd);
|
|
14
|
+
const kept = [];
|
|
15
|
+
let cursor = windowStart;
|
|
16
|
+
for (const cut of cuts) {
|
|
17
|
+
if (cut.start > cursor) kept.push({ start: cursor, end: cut.start });
|
|
18
|
+
cursor = Math.max(cursor, cut.end);
|
|
19
|
+
}
|
|
20
|
+
if (windowEnd > cursor) kept.push({ start: cursor, end: windowEnd });
|
|
21
|
+
const offsets = [];
|
|
22
|
+
let total = 0;
|
|
23
|
+
for (const range of kept) {
|
|
24
|
+
offsets.push(total);
|
|
25
|
+
total += range.end - range.start;
|
|
26
|
+
}
|
|
27
|
+
const playedDuration = total;
|
|
28
|
+
const sourceToPlayed = (t) => {
|
|
29
|
+
for (let i = 0; i < kept.length; i++) {
|
|
30
|
+
const range = kept[i];
|
|
31
|
+
if (t >= range.start && (t < range.end || i === kept.length - 1 && t === range.end)) {
|
|
32
|
+
return offsets[i] + (t - range.start);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
};
|
|
37
|
+
const snapSourceToPlayed = (t) => {
|
|
38
|
+
if (kept.length === 0 || t <= windowStart) return 0;
|
|
39
|
+
for (let i = 0; i < kept.length; i++) {
|
|
40
|
+
const range = kept[i];
|
|
41
|
+
if (t < range.start) return offsets[i];
|
|
42
|
+
if (t < range.end) return offsets[i] + (t - range.start);
|
|
43
|
+
}
|
|
44
|
+
return playedDuration;
|
|
45
|
+
};
|
|
46
|
+
const playedToSource = (p) => {
|
|
47
|
+
if (kept.length === 0) return windowStart;
|
|
48
|
+
if (p <= 0) return kept[0].start;
|
|
49
|
+
for (let i = 0; i < kept.length; i++) {
|
|
50
|
+
const length = kept[i].end - kept[i].start;
|
|
51
|
+
if (p < offsets[i] + length) return kept[i].start + (p - offsets[i]);
|
|
52
|
+
}
|
|
53
|
+
return kept[kept.length - 1].end;
|
|
54
|
+
};
|
|
55
|
+
return {
|
|
56
|
+
windowStart,
|
|
57
|
+
windowEnd,
|
|
58
|
+
cuts,
|
|
59
|
+
hasCuts: cuts.length > 0,
|
|
60
|
+
playedDuration,
|
|
61
|
+
keptRanges: () => kept.map((r) => ({ ...r })),
|
|
62
|
+
sourceToPlayed,
|
|
63
|
+
snapSourceToPlayed,
|
|
64
|
+
playedToSource
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export {
|
|
69
|
+
createMediaTimeMap
|
|
70
|
+
};
|
|
@@ -5,14 +5,14 @@ import {
|
|
|
5
5
|
} from "./chunk-SVN7T6BK.js";
|
|
6
6
|
import {
|
|
7
7
|
markdownToDoc
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-RMCUZDW5.js";
|
|
9
9
|
import {
|
|
10
10
|
cloneAndFreezeData,
|
|
11
11
|
isTemplateBlock
|
|
12
12
|
} from "./chunk-Y4D6TDZT.js";
|
|
13
13
|
import {
|
|
14
14
|
parseMarkdown
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-HUXK7EOT.js";
|
|
16
16
|
import {
|
|
17
17
|
extractPlainText,
|
|
18
18
|
getChildren
|