@clipkit/runtime 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +54 -0
- package/README.md +98 -0
- package/dist/animation/easings.d.ts +9 -0
- package/dist/animation/easings.d.ts.map +1 -0
- package/dist/animation/easings.js +230 -0
- package/dist/animation/easings.js.map +1 -0
- package/dist/animation/expr.d.ts +44 -0
- package/dist/animation/expr.d.ts.map +1 -0
- package/dist/animation/expr.js +236 -0
- package/dist/animation/expr.js.map +1 -0
- package/dist/animation/keyframes.d.ts +23 -0
- package/dist/animation/keyframes.d.ts.map +1 -0
- package/dist/animation/keyframes.js +117 -0
- package/dist/animation/keyframes.js.map +1 -0
- package/dist/animation/motion-path.d.ts +18 -0
- package/dist/animation/motion-path.d.ts.map +1 -0
- package/dist/animation/motion-path.js +269 -0
- package/dist/animation/motion-path.js.map +1 -0
- package/dist/animation/noise1d.d.ts +5 -0
- package/dist/animation/noise1d.d.ts.map +1 -0
- package/dist/animation/noise1d.js +27 -0
- package/dist/animation/noise1d.js.map +1 -0
- package/dist/animation/presets.d.ts +60 -0
- package/dist/animation/presets.d.ts.map +1 -0
- package/dist/animation/presets.js +221 -0
- package/dist/animation/presets.js.map +1 -0
- package/dist/assets/cache.d.ts +18 -0
- package/dist/assets/cache.d.ts.map +1 -0
- package/dist/assets/cache.js +56 -0
- package/dist/assets/cache.js.map +1 -0
- package/dist/assets/fonts.d.ts +20 -0
- package/dist/assets/fonts.d.ts.map +1 -0
- package/dist/assets/fonts.js +127 -0
- package/dist/assets/fonts.js.map +1 -0
- package/dist/assets/loader.d.ts +18 -0
- package/dist/assets/loader.d.ts.map +1 -0
- package/dist/assets/loader.js +87 -0
- package/dist/assets/loader.js.map +1 -0
- package/dist/assets/lut.d.ts +5 -0
- package/dist/assets/lut.d.ts.map +1 -0
- package/dist/assets/lut.js +77 -0
- package/dist/assets/lut.js.map +1 -0
- package/dist/assets/media-time.d.ts +31 -0
- package/dist/assets/media-time.d.ts.map +1 -0
- package/dist/assets/media-time.js +65 -0
- package/dist/assets/media-time.js.map +1 -0
- package/dist/assets/mp4-frame-source.d.ts +44 -0
- package/dist/assets/mp4-frame-source.d.ts.map +1 -0
- package/dist/assets/mp4-frame-source.js +387 -0
- package/dist/assets/mp4-frame-source.js.map +1 -0
- package/dist/audio/encoder.d.ts +31 -0
- package/dist/audio/encoder.d.ts.map +1 -0
- package/dist/audio/encoder.js +96 -0
- package/dist/audio/encoder.js.map +1 -0
- package/dist/audio/fades.d.ts +16 -0
- package/dist/audio/fades.d.ts.map +1 -0
- package/dist/audio/fades.js +43 -0
- package/dist/audio/fades.js.map +1 -0
- package/dist/audio/limiter.d.ts +8 -0
- package/dist/audio/limiter.d.ts.map +1 -0
- package/dist/audio/limiter.js +39 -0
- package/dist/audio/limiter.js.map +1 -0
- package/dist/audio/loader.d.ts +6 -0
- package/dist/audio/loader.d.ts.map +1 -0
- package/dist/audio/loader.js +42 -0
- package/dist/audio/loader.js.map +1 -0
- package/dist/audio/mixer.d.ts +17 -0
- package/dist/audio/mixer.d.ts.map +1 -0
- package/dist/audio/mixer.js +204 -0
- package/dist/audio/mixer.js.map +1 -0
- package/dist/audio/varispeed.d.ts +24 -0
- package/dist/audio/varispeed.d.ts.map +1 -0
- package/dist/audio/varispeed.js +114 -0
- package/dist/audio/varispeed.js.map +1 -0
- package/dist/audio/wav.d.ts +6 -0
- package/dist/audio/wav.d.ts.map +1 -0
- package/dist/audio/wav.js +62 -0
- package/dist/audio/wav.js.map +1 -0
- package/dist/backend/backend.d.ts +579 -0
- package/dist/backend/backend.d.ts.map +1 -0
- package/dist/backend/backend.js +17 -0
- package/dist/backend/backend.js.map +1 -0
- package/dist/backend/webgl-backend.d.ts +97 -0
- package/dist/backend/webgl-backend.d.ts.map +1 -0
- package/dist/backend/webgl-backend.js +2142 -0
- package/dist/backend/webgl-backend.js.map +1 -0
- package/dist/backend/webgpu-backend.d.ts +121 -0
- package/dist/backend/webgpu-backend.d.ts.map +1 -0
- package/dist/backend/webgpu-backend.js +2481 -0
- package/dist/backend/webgpu-backend.js.map +1 -0
- package/dist/compositor/bitfont.d.ts +8 -0
- package/dist/compositor/bitfont.d.ts.map +1 -0
- package/dist/compositor/bitfont.js +52 -0
- package/dist/compositor/bitfont.js.map +1 -0
- package/dist/compositor/camera.d.ts +5 -0
- package/dist/compositor/camera.d.ts.map +1 -0
- package/dist/compositor/camera.js +114 -0
- package/dist/compositor/camera.js.map +1 -0
- package/dist/compositor/color.d.ts +26 -0
- package/dist/compositor/color.d.ts.map +1 -0
- package/dist/compositor/color.js +189 -0
- package/dist/compositor/color.js.map +1 -0
- package/dist/compositor/element-renderers/caption.d.ts +4 -0
- package/dist/compositor/element-renderers/caption.d.ts.map +1 -0
- package/dist/compositor/element-renderers/caption.js +376 -0
- package/dist/compositor/element-renderers/caption.js.map +1 -0
- package/dist/compositor/element-renderers/group.d.ts +12 -0
- package/dist/compositor/element-renderers/group.d.ts.map +1 -0
- package/dist/compositor/element-renderers/group.js +259 -0
- package/dist/compositor/element-renderers/group.js.map +1 -0
- package/dist/compositor/element-renderers/image.d.ts +4 -0
- package/dist/compositor/element-renderers/image.d.ts.map +1 -0
- package/dist/compositor/element-renderers/image.js +97 -0
- package/dist/compositor/element-renderers/image.js.map +1 -0
- package/dist/compositor/element-renderers/lit.d.ts +6 -0
- package/dist/compositor/element-renderers/lit.d.ts.map +1 -0
- package/dist/compositor/element-renderers/lit.js +82 -0
- package/dist/compositor/element-renderers/lit.js.map +1 -0
- package/dist/compositor/element-renderers/particles.d.ts +4 -0
- package/dist/compositor/element-renderers/particles.d.ts.map +1 -0
- package/dist/compositor/element-renderers/particles.js +212 -0
- package/dist/compositor/element-renderers/particles.js.map +1 -0
- package/dist/compositor/element-renderers/shape.d.ts +4 -0
- package/dist/compositor/element-renderers/shape.d.ts.map +1 -0
- package/dist/compositor/element-renderers/shape.js +171 -0
- package/dist/compositor/element-renderers/shape.js.map +1 -0
- package/dist/compositor/element-renderers/svg.d.ts +4 -0
- package/dist/compositor/element-renderers/svg.d.ts.map +1 -0
- package/dist/compositor/element-renderers/svg.js +210 -0
- package/dist/compositor/element-renderers/svg.js.map +1 -0
- package/dist/compositor/element-renderers/text.d.ts +25 -0
- package/dist/compositor/element-renderers/text.d.ts.map +1 -0
- package/dist/compositor/element-renderers/text.js +1358 -0
- package/dist/compositor/element-renderers/text.js.map +1 -0
- package/dist/compositor/element-renderers/video.d.ts +12 -0
- package/dist/compositor/element-renderers/video.d.ts.map +1 -0
- package/dist/compositor/element-renderers/video.js +109 -0
- package/dist/compositor/element-renderers/video.js.map +1 -0
- package/dist/compositor/fit.d.ts +18 -0
- package/dist/compositor/fit.d.ts.map +1 -0
- package/dist/compositor/fit.js +106 -0
- package/dist/compositor/fit.js.map +1 -0
- package/dist/compositor/lighting.d.ts +63 -0
- package/dist/compositor/lighting.d.ts.map +1 -0
- package/dist/compositor/lighting.js +141 -0
- package/dist/compositor/lighting.js.map +1 -0
- package/dist/compositor/mat4.d.ts +88 -0
- package/dist/compositor/mat4.d.ts.map +1 -0
- package/dist/compositor/mat4.js +245 -0
- package/dist/compositor/mat4.js.map +1 -0
- package/dist/compositor/project.d.ts +24 -0
- package/dist/compositor/project.d.ts.map +1 -0
- package/dist/compositor/project.js +105 -0
- package/dist/compositor/project.js.map +1 -0
- package/dist/compositor/render-context.d.ts +194 -0
- package/dist/compositor/render-context.d.ts.map +1 -0
- package/dist/compositor/render-context.js +10 -0
- package/dist/compositor/render-context.js.map +1 -0
- package/dist/compositor/resolve.d.ts +80 -0
- package/dist/compositor/resolve.d.ts.map +1 -0
- package/dist/compositor/resolve.js +276 -0
- package/dist/compositor/resolve.js.map +1 -0
- package/dist/compositor/scene.d.ts +10 -0
- package/dist/compositor/scene.d.ts.map +1 -0
- package/dist/compositor/scene.js +658 -0
- package/dist/compositor/scene.js.map +1 -0
- package/dist/compositor/transform.d.ts +73 -0
- package/dist/compositor/transform.d.ts.map +1 -0
- package/dist/compositor/transform.js +229 -0
- package/dist/compositor/transform.js.map +1 -0
- package/dist/compositor/unit.d.ts +27 -0
- package/dist/compositor/unit.d.ts.map +1 -0
- package/dist/compositor/unit.js +74 -0
- package/dist/compositor/unit.js.map +1 -0
- package/dist/encoder/exporter.d.ts +95 -0
- package/dist/encoder/exporter.d.ts.map +1 -0
- package/dist/encoder/exporter.js +341 -0
- package/dist/encoder/exporter.js.map +1 -0
- package/dist/encoder/index.d.ts +3 -0
- package/dist/encoder/index.d.ts.map +1 -0
- package/dist/encoder/index.js +2 -0
- package/dist/encoder/index.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +13 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +32 -0
- package/dist/logger.js.map +1 -0
- package/dist/runtime.d.ts +216 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +1012 -0
- package/dist/runtime.js.map +1 -0
- package/dist/svg/morph.d.ts +6 -0
- package/dist/svg/morph.d.ts.map +1 -0
- package/dist/svg/morph.js +62 -0
- package/dist/svg/morph.js.map +1 -0
- package/dist/svg/svg-renderer.d.ts +18 -0
- package/dist/svg/svg-renderer.d.ts.map +1 -0
- package/dist/svg/svg-renderer.js +142 -0
- package/dist/svg/svg-renderer.js.map +1 -0
- package/dist/text/caption-chunk.d.ts +17 -0
- package/dist/text/caption-chunk.d.ts.map +1 -0
- package/dist/text/caption-chunk.js +76 -0
- package/dist/text/caption-chunk.js.map +1 -0
- package/dist/text/font-atlas.d.ts +63 -0
- package/dist/text/font-atlas.d.ts.map +1 -0
- package/dist/text/font-atlas.js +225 -0
- package/dist/text/font-atlas.js.map +1 -0
- package/dist/text/measure.d.ts +38 -0
- package/dist/text/measure.d.ts.map +1 -0
- package/dist/text/measure.js +164 -0
- package/dist/text/measure.js.map +1 -0
- package/dist/text/text-animation.d.ts +52 -0
- package/dist/text/text-animation.d.ts.map +1 -0
- package/dist/text/text-animation.js +133 -0
- package/dist/text/text-animation.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import { Muxer, ArrayBufferTarget } from "mp4-muxer";
|
|
2
|
+
import { encodeAudioBuffer, pickAudioCodec } from "../audio/encoder.js";
|
|
3
|
+
/**
|
|
4
|
+
* Heights for each named resolution tier. Source aspect ratio drives
|
|
5
|
+
* the width.
|
|
6
|
+
*/
|
|
7
|
+
const RESOLUTION_HEIGHTS = {
|
|
8
|
+
'480p': 480,
|
|
9
|
+
'720p': 720,
|
|
10
|
+
'1080p': 1080,
|
|
11
|
+
'1440p': 1440,
|
|
12
|
+
'4k': 2160,
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Default video bitrates per resolution tier. Tuned for landing-page /
|
|
16
|
+
* UI motion graphics with lots of text — slightly conservative on the
|
|
17
|
+
* low end, generous at 4K where chroma sampling shows blockiness fast.
|
|
18
|
+
*/
|
|
19
|
+
const RESOLUTION_BITRATES = {
|
|
20
|
+
'480p': 1_500_000,
|
|
21
|
+
'720p': 4_000_000,
|
|
22
|
+
'1080p': 8_000_000,
|
|
23
|
+
'1440p': 16_000_000,
|
|
24
|
+
'4k': 35_000_000,
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* H.264 codec strings per resolution tier. The level field caps the
|
|
28
|
+
* pixel area the encoder will accept — Level 4.2 (default elsewhere)
|
|
29
|
+
* tops out at 1080p, so 1440p / 4K must move up to Level 5.1, which
|
|
30
|
+
* covers up to 4K30. High Profile (640) gives noticeably better
|
|
31
|
+
* compression than Baseline (420) at the same bitrate.
|
|
32
|
+
*/
|
|
33
|
+
const RESOLUTION_CODECS = {
|
|
34
|
+
'480p': 'avc1.42E01F', // Baseline @ Level 3.1 (covers 854×480)
|
|
35
|
+
'720p': 'avc1.42E01F', // Baseline @ Level 3.1
|
|
36
|
+
'1080p': 'avc1.42002A', // Baseline @ Level 4.2
|
|
37
|
+
'1440p': 'avc1.640033', // High @ Level 5.1
|
|
38
|
+
'4k': 'avc1.640033', // High @ Level 5.1
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Encoder pacing + stall guards for the export path.
|
|
42
|
+
*
|
|
43
|
+
* BACKPRESSURE_LIMIT — max frames allowed in the VideoEncoder queue before the
|
|
44
|
+
* render loop pauses for it to drain. Bounds memory and stops frame submission
|
|
45
|
+
* from racing ahead of a slow (software) encoder.
|
|
46
|
+
*
|
|
47
|
+
* FLUSH_TIMEOUT_MS — ceiling on encoder.flush(). With backpressure the queue is
|
|
48
|
+
* tiny by the time we flush, so a flush that exceeds this is a genuine stall;
|
|
49
|
+
* we reject it so the failure is visible instead of an infinite "100%" hang.
|
|
50
|
+
*/
|
|
51
|
+
const BACKPRESSURE_LIMIT = 8;
|
|
52
|
+
const FLUSH_TIMEOUT_MS = 120_000;
|
|
53
|
+
/**
|
|
54
|
+
* Resolve a RenderResolution + Source dimensions into the concrete
|
|
55
|
+
* physical canvas size, pixel ratio, and a sensible default bitrate.
|
|
56
|
+
*/
|
|
57
|
+
export function resolveRenderResolution(resolution, sourceWidth, sourceHeight) {
|
|
58
|
+
if (resolution === 'source') {
|
|
59
|
+
// Pick a codec based on the source's actual height, not a fixed
|
|
60
|
+
// tier — a 4K source authored natively still needs Level 5.1.
|
|
61
|
+
const codec = sourceHeight > 1080 ? 'avc1.640033' : 'avc1.42002A';
|
|
62
|
+
return {
|
|
63
|
+
physicalWidth: sourceWidth,
|
|
64
|
+
physicalHeight: sourceHeight,
|
|
65
|
+
pixelRatio: 1,
|
|
66
|
+
defaultBitrate: 5_000_000,
|
|
67
|
+
defaultCodec: codec,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const targetHeight = RESOLUTION_HEIGHTS[resolution];
|
|
71
|
+
const pixelRatio = targetHeight / sourceHeight;
|
|
72
|
+
return {
|
|
73
|
+
physicalWidth: Math.round(sourceWidth * pixelRatio),
|
|
74
|
+
physicalHeight: targetHeight,
|
|
75
|
+
pixelRatio,
|
|
76
|
+
defaultBitrate: RESOLUTION_BITRATES[resolution],
|
|
77
|
+
defaultCodec: RESOLUTION_CODECS[resolution],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* H.264 (and ffmpeg's yuv420p) require EVEN frame dimensions. A named
|
|
82
|
+
* resolution tier derives width from the source aspect ratio, which can land
|
|
83
|
+
* odd — e.g. a 16:9 source at 480p gives 1920×(480/1080) = 853. Floor each
|
|
84
|
+
* encode dimension to the nearest even pixel so every tier / aspect ratio
|
|
85
|
+
* encodes cleanly. Export-only: the live preview backend is never resized
|
|
86
|
+
* through this.
|
|
87
|
+
*/
|
|
88
|
+
function toEvenDimension(n) {
|
|
89
|
+
const floored = Math.max(2, Math.floor(n));
|
|
90
|
+
return floored % 2 === 0 ? floored : floored - 1;
|
|
91
|
+
}
|
|
92
|
+
export class ClipkitExporter {
|
|
93
|
+
canvas;
|
|
94
|
+
renderer;
|
|
95
|
+
encoder = null;
|
|
96
|
+
muxer = null;
|
|
97
|
+
tempCanvas;
|
|
98
|
+
tempCtx;
|
|
99
|
+
constructor(canvas, renderer) {
|
|
100
|
+
this.canvas = canvas;
|
|
101
|
+
this.renderer = renderer;
|
|
102
|
+
this.tempCanvas = document.createElement("canvas");
|
|
103
|
+
this.tempCtx = this.tempCanvas.getContext("2d");
|
|
104
|
+
}
|
|
105
|
+
async export(source, options = {}) {
|
|
106
|
+
const { codec = "avc1.42002A", // H.264 Baseline Profile Level 4.2 (supports 1080p)
|
|
107
|
+
bitrate = 5_000_000, framerate = source.frame_rate || 30, onProgress, } = options;
|
|
108
|
+
// Apply schema-aware defaults — Source dimensions are optional in the
|
|
109
|
+
// schema but mandatory for encoding.
|
|
110
|
+
const sourceWidth = source.width ?? 1920;
|
|
111
|
+
const sourceHeight = source.height ?? 1080;
|
|
112
|
+
const duration = typeof source.duration === "number" ? source.duration : 10;
|
|
113
|
+
// Output dimensions come from the runtime canvas — the runtime is
|
|
114
|
+
// expected to have resize()'d the backend to the right pixel ratio
|
|
115
|
+
// before calling export(). Falls back to source dims if not. Clamped to
|
|
116
|
+
// even (H.264 requires it) — the backend canvas may be odd at some tiers.
|
|
117
|
+
const width = toEvenDimension(this.canvas.width || sourceWidth);
|
|
118
|
+
const height = toEvenDimension(this.canvas.height || sourceHeight);
|
|
119
|
+
console.log("[clipkit] Starting export:", { codec, bitrate, framerate, sourceWidth, sourceHeight, width, height, duration, hasAudio: !!options.audio });
|
|
120
|
+
this.tempCanvas.width = width;
|
|
121
|
+
this.tempCanvas.height = height;
|
|
122
|
+
const totalFrames = Math.ceil(duration * framerate);
|
|
123
|
+
// Motion blur — exact sub-frame supersampling (PROTOCOL.md §3.x).
|
|
124
|
+
// N renders per output frame across a shutter window centered on the
|
|
125
|
+
// frame time, averaged per 8-bit channel in float (single rounding).
|
|
126
|
+
// samples=1 or no motion_blur block → the plain single-render path.
|
|
127
|
+
const mb = source.motion_blur;
|
|
128
|
+
const mbSamples = mb
|
|
129
|
+
? Math.max(1, Math.min(32, Math.round(typeof mb.samples === "number" ? mb.samples : 8)))
|
|
130
|
+
: 1;
|
|
131
|
+
const mbShutter = mb && typeof mb.shutter === "number"
|
|
132
|
+
? Math.min(1, Math.max(0, mb.shutter))
|
|
133
|
+
: 0.5;
|
|
134
|
+
const blurOn = mbSamples > 1 && mbShutter > 0;
|
|
135
|
+
const mbAccum = blurOn ? new Float32Array(width * height * 4) : null;
|
|
136
|
+
console.log("[clipkit] Encoding", totalFrames, "frames at", framerate, "fps", blurOn ? `(motion blur: ${mbSamples} samples, shutter ${mbShutter})` : "");
|
|
137
|
+
const target = new ArrayBufferTarget();
|
|
138
|
+
// Negotiate an audio codec this environment can actually encode. Chromium
|
|
139
|
+
// on Linux (the render container) has NO AAC encoder, so AAC throws
|
|
140
|
+
// "Unsupported codec type" mid-export; pickAudioCodec falls back to Opus
|
|
141
|
+
// there (MP4 muxes both). null → no audio encoder at all: render silently
|
|
142
|
+
// instead of crashing.
|
|
143
|
+
let audioPick = null;
|
|
144
|
+
if (options.audio) {
|
|
145
|
+
audioPick = await pickAudioCodec(options.audio.buffer.sampleRate, options.audio.buffer.numberOfChannels, options.audio.bitrate);
|
|
146
|
+
if (!audioPick) {
|
|
147
|
+
console.warn("[clipkit] No supported audio encoder — rendering without audio.");
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
const muxerConfig = {
|
|
151
|
+
target,
|
|
152
|
+
video: {
|
|
153
|
+
codec: "avc",
|
|
154
|
+
width,
|
|
155
|
+
height,
|
|
156
|
+
},
|
|
157
|
+
fastStart: "in-memory",
|
|
158
|
+
};
|
|
159
|
+
// Add the audio track only when we have a working encoder for it.
|
|
160
|
+
if (options.audio && audioPick) {
|
|
161
|
+
muxerConfig.audio = {
|
|
162
|
+
codec: audioPick.muxer,
|
|
163
|
+
sampleRate: options.audio.buffer.sampleRate,
|
|
164
|
+
numberOfChannels: options.audio.buffer.numberOfChannels,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
this.muxer = new Muxer(muxerConfig);
|
|
168
|
+
// Encode audio first (it's fast — single pass over the pre-mixed buffer).
|
|
169
|
+
// Audio chunks reach the muxer before video chunks; mp4-muxer handles
|
|
170
|
+
// interleaving on finalize. Non-fatal: an audio failure must never sink the
|
|
171
|
+
// whole render — drop audio and keep the video.
|
|
172
|
+
if (options.audio && audioPick) {
|
|
173
|
+
console.log("[clipkit] Encoding audio:", {
|
|
174
|
+
codec: audioPick.muxer,
|
|
175
|
+
sampleRate: options.audio.buffer.sampleRate,
|
|
176
|
+
channels: options.audio.buffer.numberOfChannels,
|
|
177
|
+
duration: options.audio.buffer.duration.toFixed(2) + "s",
|
|
178
|
+
});
|
|
179
|
+
try {
|
|
180
|
+
await encodeAudioBuffer(options.audio.buffer, this.muxer, {
|
|
181
|
+
bitrate: options.audio.bitrate,
|
|
182
|
+
codec: audioPick.encoder,
|
|
183
|
+
});
|
|
184
|
+
console.log("[clipkit] Audio encoded");
|
|
185
|
+
}
|
|
186
|
+
catch (e) {
|
|
187
|
+
console.warn("[clipkit] Audio encode failed — continuing without audio:", e instanceof Error ? e.message : String(e));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// Progress is driven from the encoder OUTPUT (frames actually encoded), not
|
|
191
|
+
// from submission. Submission races ahead of a slow software encoder — which
|
|
192
|
+
// is exactly why the bar used to hit 100% while flush() was still draining.
|
|
193
|
+
// Now 100% means every frame is truly encoded + muxed.
|
|
194
|
+
let encodedChunks = 0;
|
|
195
|
+
// Latch encoder faults. The WebCodecs error callback fires asynchronously and
|
|
196
|
+
// does not reliably reject the pending flush() across browsers, so we capture
|
|
197
|
+
// it and throw at the next checkpoint — turning a silent hang into a visible,
|
|
198
|
+
// catchable failure.
|
|
199
|
+
let encoderError = null;
|
|
200
|
+
this.encoder = new VideoEncoder({
|
|
201
|
+
output: (chunk, metadata) => {
|
|
202
|
+
this.muxer?.addVideoChunk(chunk, metadata);
|
|
203
|
+
encodedChunks++;
|
|
204
|
+
if (onProgress)
|
|
205
|
+
onProgress(Math.min(1, encodedChunks / totalFrames));
|
|
206
|
+
if (encodedChunks % 30 === 0 || encodedChunks === totalFrames) {
|
|
207
|
+
console.log(`[clipkit] Encoded ${encodedChunks}/${totalFrames}`);
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
error: (error) => {
|
|
211
|
+
encoderError = error instanceof Error ? error : new Error(String(error));
|
|
212
|
+
console.error("[clipkit] VideoEncoder error:", encoderError.message);
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
this.encoder.configure({
|
|
216
|
+
codec,
|
|
217
|
+
width,
|
|
218
|
+
height,
|
|
219
|
+
bitrate,
|
|
220
|
+
});
|
|
221
|
+
// Render and encode each frame
|
|
222
|
+
for (let frameIndex = 0; frameIndex < totalFrames; frameIndex++) {
|
|
223
|
+
const currentTime = frameIndex * (1 / framerate);
|
|
224
|
+
if (blurOn && mbAccum) {
|
|
225
|
+
mbAccum.fill(0);
|
|
226
|
+
for (let k = 0; k < mbSamples; k++) {
|
|
227
|
+
const tk = Math.min(Math.max(currentTime + ((k + 0.5) / mbSamples - 0.5) * (mbShutter / framerate), 0), duration);
|
|
228
|
+
await this.renderer.renderAsync(source, tk);
|
|
229
|
+
await this.renderer.gpuFinish(); // drain GPU before read-back (hardware-GL capture race)
|
|
230
|
+
this.tempCtx.drawImage(this.canvas, 0, 0, width, height);
|
|
231
|
+
const sample = this.tempCtx.getImageData(0, 0, width, height).data;
|
|
232
|
+
for (let i = 0; i < sample.length; i++)
|
|
233
|
+
mbAccum[i] += sample[i];
|
|
234
|
+
}
|
|
235
|
+
const out = this.tempCtx.createImageData(width, height);
|
|
236
|
+
const od = out.data;
|
|
237
|
+
const inv = 1 / mbSamples;
|
|
238
|
+
for (let i = 0; i < od.length; i++)
|
|
239
|
+
od[i] = Math.round(mbAccum[i] * inv);
|
|
240
|
+
this.tempCtx.putImageData(out, 0, 0);
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
await this.renderer.renderAsync(source, currentTime);
|
|
244
|
+
await this.renderer.gpuFinish(); // drain GPU before read-back (hardware-GL capture race)
|
|
245
|
+
this.tempCtx.drawImage(this.canvas, 0, 0, width, height);
|
|
246
|
+
}
|
|
247
|
+
const videoFrame = new VideoFrame(this.tempCanvas, {
|
|
248
|
+
timestamp: (frameIndex * 1_000_000) / framerate, // microseconds
|
|
249
|
+
duration: 1_000_000 / framerate,
|
|
250
|
+
});
|
|
251
|
+
// Backpressure — never let submission race more than a few frames ahead of
|
|
252
|
+
// the (often software) encoder. Without this a heavy comp queues hundreds
|
|
253
|
+
// of VideoFrames faster than they drain: memory climbs and flush() can take
|
|
254
|
+
// (or appear to take) forever. 'dequeue' is the modern drain signal; race a
|
|
255
|
+
// short macrotask timer so we never wedge if it isn't delivered.
|
|
256
|
+
while (this.encoder.encodeQueueSize > BACKPRESSURE_LIMIT) {
|
|
257
|
+
if (encoderError)
|
|
258
|
+
throw encoderError;
|
|
259
|
+
await new Promise((resolve) => {
|
|
260
|
+
const enc = this.encoder;
|
|
261
|
+
let settled = false;
|
|
262
|
+
const finish = () => {
|
|
263
|
+
if (settled)
|
|
264
|
+
return;
|
|
265
|
+
settled = true;
|
|
266
|
+
enc.removeEventListener("dequeue", finish);
|
|
267
|
+
resolve();
|
|
268
|
+
};
|
|
269
|
+
enc.addEventListener("dequeue", finish, { once: true });
|
|
270
|
+
setTimeout(finish, 50);
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
if (encoderError)
|
|
274
|
+
throw encoderError;
|
|
275
|
+
// Encode frame
|
|
276
|
+
const keyFrame = frameIndex % 30 === 0; // Keyframe every 30 frames
|
|
277
|
+
this.encoder.encode(videoFrame, { keyFrame });
|
|
278
|
+
// Close frame to free memory. Progress comes from the encoder OUTPUT
|
|
279
|
+
// callback (chunks actually encoded), not from submission here.
|
|
280
|
+
videoFrame.close();
|
|
281
|
+
}
|
|
282
|
+
// Watchdog around flush — a wedged software encoder can leave flush() pending
|
|
283
|
+
// forever, which is what hung the export at "100%" with no error and no
|
|
284
|
+
// download. With backpressure the queue is small here, so a flush that blows
|
|
285
|
+
// past this ceiling is a real stall: reject so the UI surfaces an error
|
|
286
|
+
// instead of an infinite spinner. Ceiling is generous — legit heavy comps are
|
|
287
|
+
// fine; an actual hang is not.
|
|
288
|
+
if (encoderError)
|
|
289
|
+
throw encoderError;
|
|
290
|
+
await Promise.race([
|
|
291
|
+
this.encoder.flush(),
|
|
292
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(`Export stalled: encoder.flush did not resolve within ${FLUSH_TIMEOUT_MS / 1000}s`)), FLUSH_TIMEOUT_MS)),
|
|
293
|
+
]);
|
|
294
|
+
if (encoderError)
|
|
295
|
+
throw encoderError;
|
|
296
|
+
console.log("[clipkit] Encoding complete");
|
|
297
|
+
this.muxer.finalize();
|
|
298
|
+
const { buffer } = target;
|
|
299
|
+
if (!buffer || buffer.byteLength === 0) {
|
|
300
|
+
throw new Error("Muxer produced no output");
|
|
301
|
+
}
|
|
302
|
+
console.log("[clipkit] Muxer finalized, size:", (buffer.byteLength / 1024 / 1024).toFixed(2), "MB");
|
|
303
|
+
const mp4Blob = new Blob([buffer], { type: "video/mp4" });
|
|
304
|
+
// Cleanup
|
|
305
|
+
this.encoder.close();
|
|
306
|
+
this.encoder = null;
|
|
307
|
+
this.muxer = null;
|
|
308
|
+
console.log("[clipkit] Export complete, size:", (mp4Blob.size / 1024 / 1024).toFixed(2), "MB");
|
|
309
|
+
return mp4Blob;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Render each frame and hand its PNG bytes (base64, with alpha) to `onFrame`.
|
|
313
|
+
* No encoder/muxer — this feeds the transparent export path (ProRes 4444 /
|
|
314
|
+
* VP9-alpha), which assembles the PNGs with a server-side ffmpeg. `alpha`
|
|
315
|
+
* relies on the renderer having been told to clear transparent (the runtime
|
|
316
|
+
* arranges that). Returns the frame count.
|
|
317
|
+
*/
|
|
318
|
+
async exportFrames(source, options) {
|
|
319
|
+
const framerate = options.framerate ?? source.frame_rate ?? 30;
|
|
320
|
+
const duration = typeof source.duration === "number" ? source.duration : 10;
|
|
321
|
+
// Even dims for the downstream ffmpeg encode (yuv420p), same as export().
|
|
322
|
+
const width = toEvenDimension(this.canvas.width || (source.width ?? 1920));
|
|
323
|
+
const height = toEvenDimension(this.canvas.height || (source.height ?? 1080));
|
|
324
|
+
this.tempCanvas.width = width;
|
|
325
|
+
this.tempCanvas.height = height;
|
|
326
|
+
const totalFrames = Math.ceil(duration * framerate);
|
|
327
|
+
for (let i = 0; i < totalFrames; i++) {
|
|
328
|
+
await this.renderer.renderAsync(source, i / framerate);
|
|
329
|
+
await this.renderer.gpuFinish(); // drain GPU before read-back (hardware-GL capture race)
|
|
330
|
+
// Transparent output must not composite onto the previous frame.
|
|
331
|
+
if (options.alpha)
|
|
332
|
+
this.tempCtx.clearRect(0, 0, width, height);
|
|
333
|
+
this.tempCtx.drawImage(this.canvas, 0, 0, width, height);
|
|
334
|
+
const dataUrl = this.tempCanvas.toDataURL("image/png");
|
|
335
|
+
await options.onFrame(i, dataUrl.slice(dataUrl.indexOf(",") + 1));
|
|
336
|
+
options.onProgress?.((i + 1) / totalFrames);
|
|
337
|
+
}
|
|
338
|
+
return totalFrames;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
//# sourceMappingURL=exporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exporter.js","sourceRoot":"","sources":["../../src/encoder/exporter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AACpD,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAyB,MAAM,qBAAqB,CAAA;AA6C9F;;;GAGG;AACH,MAAM,kBAAkB,GAAwD;IAC9E,MAAM,EAAE,GAAG;IACX,MAAM,EAAE,GAAG;IACX,OAAO,EAAE,IAAI;IACb,OAAO,EAAE,IAAI;IACb,IAAI,EAAE,IAAI;CACX,CAAC;AAEF;;;;GAIG;AACH,MAAM,mBAAmB,GAAwD;IAC/E,MAAM,EAAG,SAAS;IAClB,MAAM,EAAG,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,UAAU;IACnB,IAAI,EAAK,UAAU;CACpB,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,iBAAiB,GAAwD;IAC7E,MAAM,EAAG,aAAa,EAAE,wCAAwC;IAChE,MAAM,EAAG,aAAa,EAAE,uBAAuB;IAC/C,OAAO,EAAE,aAAa,EAAE,uBAAuB;IAC/C,OAAO,EAAE,aAAa,EAAE,mBAAmB;IAC3C,IAAI,EAAK,aAAa,EAAE,mBAAmB;CAC5C,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAC7B,MAAM,gBAAgB,GAAG,OAAO,CAAC;AAEjC;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CACrC,UAA4B,EAC5B,WAAmB,EACnB,YAAoB;IAQpB,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;QAC5B,gEAAgE;QAChE,8DAA8D;QAC9D,MAAM,KAAK,GAAG,YAAY,GAAG,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC;QAClE,OAAO;YACL,aAAa,EAAE,WAAW;YAC1B,cAAc,EAAE,YAAY;YAC5B,UAAU,EAAE,CAAC;YACb,cAAc,EAAE,SAAS;YACzB,YAAY,EAAE,KAAK;SACpB,CAAC;IACJ,CAAC;IACD,MAAM,YAAY,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;IACpD,MAAM,UAAU,GAAG,YAAY,GAAG,YAAY,CAAC;IAC/C,OAAO;QACL,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,UAAU,CAAC;QACnD,cAAc,EAAE,YAAY;QAC5B,UAAU;QACV,cAAc,EAAE,mBAAmB,CAAC,UAAU,CAAC;QAC/C,YAAY,EAAE,iBAAiB,CAAC,UAAU,CAAC;KAC5C,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,eAAe,CAAC,CAAS;IAChC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;IAC1C,OAAO,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAA;AAClD,CAAC;AAsBD,MAAM,OAAO,eAAe;IAClB,MAAM,CAAqC;IAC3C,QAAQ,CAAe;IACvB,OAAO,GAAwB,IAAI,CAAA;IACnC,KAAK,GAAoC,IAAI,CAAA;IAC7C,UAAU,CAAmB;IAC7B,OAAO,CAA0B;IAEzC,YAAY,MAA2C,EAAE,QAAuB;QAC9E,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QAExB,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAA;QAClD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAE,CAAA;IAClD,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,MAAc,EAAE,UAAyB,EAAE;QACtD,MAAM,EACJ,KAAK,GAAG,aAAa,EAAE,oDAAoD;QAC3E,OAAO,GAAG,SAAS,EACnB,SAAS,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,EACnC,UAAU,GACX,GAAG,OAAO,CAAA;QAEX,sEAAsE;QACtE,qCAAqC;QACrC,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,IAAI,IAAI,CAAA;QACxC,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,IAAI,IAAI,CAAA;QAC1C,MAAM,QAAQ,GAAG,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAA;QAE3E,kEAAkE;QAClE,mEAAmE;QACnE,wEAAwE;QACxE,0EAA0E;QAC1E,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,WAAW,CAAC,CAAA;QAC/D,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,YAAY,CAAC,CAAA;QAElE,OAAO,CAAC,GAAG,CAAC,4BAA4B,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAAA;QAEvJ,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,KAAK,CAAA;QAC7B,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,MAAM,CAAA;QAE/B,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAA;QAEnD,kEAAkE;QAClE,qEAAqE;QACrE,qEAAqE;QACrE,oEAAoE;QACpE,MAAM,EAAE,GAAG,MAAM,CAAC,WAAW,CAAA;QAC7B,MAAM,SAAS,GAAG,EAAE;YAClB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACxF,CAAC,CAAC,CAAC,CAAA;QACL,MAAM,SAAS,GAAG,EAAE,IAAI,OAAO,EAAE,CAAC,OAAO,KAAK,QAAQ;YACpD,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC;YACtC,CAAC,CAAC,GAAG,CAAA;QACP,MAAM,MAAM,GAAG,SAAS,GAAG,CAAC,IAAI,SAAS,GAAG,CAAC,CAAA;QAC7C,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QAEpE,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,KAAK,EAC1E,MAAM,CAAC,CAAC,CAAC,iBAAiB,SAAS,qBAAqB,SAAS,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QAE5E,MAAM,MAAM,GAAG,IAAI,iBAAiB,EAAE,CAAA;QAEtC,0EAA0E;QAC1E,oEAAoE;QACpE,yEAAyE;QACzE,0EAA0E;QAC1E,uBAAuB;QACvB,IAAI,SAAS,GAA4B,IAAI,CAAA;QAC7C,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,SAAS,GAAG,MAAM,cAAc,CAC9B,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,EAC/B,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,gBAAgB,EACrC,OAAO,CAAC,KAAK,CAAC,OAAO,CACtB,CAAA;YACD,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAA;YACjF,CAAC;QACH,CAAC;QAED,MAAM,WAAW,GAA8D;YAC7E,MAAM;YACN,KAAK,EAAE;gBACL,KAAK,EAAE,KAAK;gBACZ,KAAK;gBACL,MAAM;aACP;YACD,SAAS,EAAE,WAAW;SACvB,CAAA;QAED,kEAAkE;QAClE,IAAI,OAAO,CAAC,KAAK,IAAI,SAAS,EAAE,CAAC;YAC/B,WAAW,CAAC,KAAK,GAAG;gBAClB,KAAK,EAAE,SAAS,CAAC,KAAK;gBACtB,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU;gBAC3C,gBAAgB,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,gBAAgB;aACxD,CAAA;QACH,CAAC;QAED,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,CAAA;QAEnC,0EAA0E;QAC1E,sEAAsE;QACtE,4EAA4E;QAC5E,gDAAgD;QAChD,IAAI,OAAO,CAAC,KAAK,IAAI,SAAS,EAAE,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE;gBACvC,KAAK,EAAE,SAAS,CAAC,KAAK;gBACtB,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU;gBAC3C,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,gBAAgB;gBAC/C,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG;aACzD,CAAC,CAAA;YACF,IAAI,CAAC;gBACH,MAAM,iBAAiB,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,EAAE;oBACxD,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO;oBAC9B,KAAK,EAAE,SAAS,CAAC,OAAO;iBACzB,CAAC,CAAA;gBACF,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAA;YACxC,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,CAAC,IAAI,CACV,2DAA2D,EAC3D,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAC3C,CAAA;YACH,CAAC;QACH,CAAC;QAED,4EAA4E;QAC5E,6EAA6E;QAC7E,4EAA4E;QAC5E,uDAAuD;QACvD,IAAI,aAAa,GAAG,CAAC,CAAA;QACrB,8EAA8E;QAC9E,8EAA8E;QAC9E,8EAA8E;QAC9E,qBAAqB;QACrB,IAAI,YAAY,GAAiB,IAAI,CAAA;QAErC,IAAI,CAAC,OAAO,GAAG,IAAI,YAAY,CAAC;YAC9B,MAAM,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;gBAC1B,IAAI,CAAC,KAAK,EAAE,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;gBAC1C,aAAa,EAAE,CAAA;gBACf,IAAI,UAAU;oBAAE,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,GAAG,WAAW,CAAC,CAAC,CAAA;gBACpE,IAAI,aAAa,GAAG,EAAE,KAAK,CAAC,IAAI,aAAa,KAAK,WAAW,EAAE,CAAC;oBAC9D,OAAO,CAAC,GAAG,CAAC,qBAAqB,aAAa,IAAI,WAAW,EAAE,CAAC,CAAA;gBAClE,CAAC;YACH,CAAC;YACD,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE;gBACf,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;gBACxE,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,YAAY,CAAC,OAAO,CAAC,CAAA;YACtE,CAAC;SACF,CAAC,CAAA;QAEF,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;YACrB,KAAK;YACL,KAAK;YACL,MAAM;YACN,OAAO;SACR,CAAC,CAAA;QAEF,+BAA+B;QAC/B,KAAK,IAAI,UAAU,GAAG,CAAC,EAAE,UAAU,GAAG,WAAW,EAAE,UAAU,EAAE,EAAE,CAAC;YAChE,MAAM,WAAW,GAAG,UAAU,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,CAAA;YAEhD,IAAI,MAAM,IAAI,OAAO,EAAE,CAAC;gBACtB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;gBACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,EAAE,CAAC;oBACnC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CACjB,IAAI,CAAC,GAAG,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,SAAS,GAAG,GAAG,CAAC,GAAG,CAAC,SAAS,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC,EAClF,QAAQ,CACT,CAAA;oBACD,MAAM,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;oBAC3C,MAAM,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAA,CAAC,wDAAwD;oBACxF,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,MAA2B,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;oBAC7E,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,IAAI,CAAA;oBAClE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE;wBAAE,OAAO,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAA;gBACjE,CAAC;gBACD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;gBACvD,MAAM,EAAE,GAAG,GAAG,CAAC,IAAI,CAAA;gBACnB,MAAM,GAAG,GAAG,CAAC,GAAG,SAAS,CAAA;gBACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE;oBAAE,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAA;gBACxE,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;YACtC,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;gBACpD,MAAM,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAA,CAAC,wDAAwD;gBACxF,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,MAA2B,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;YAC/E,CAAC;YAED,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,UAAU,EAAE;gBACjD,SAAS,EAAE,CAAC,UAAU,GAAG,SAAS,CAAC,GAAG,SAAS,EAAE,eAAe;gBAChE,QAAQ,EAAE,SAAS,GAAG,SAAS;aAChC,CAAC,CAAA;YAEF,2EAA2E;YAC3E,0EAA0E;YAC1E,4EAA4E;YAC5E,4EAA4E;YAC5E,iEAAiE;YACjE,OAAO,IAAI,CAAC,OAAO,CAAC,eAAe,GAAG,kBAAkB,EAAE,CAAC;gBACzD,IAAI,YAAY;oBAAE,MAAM,YAAY,CAAA;gBACpC,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;oBAClC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAQ,CAAA;oBACzB,IAAI,OAAO,GAAG,KAAK,CAAA;oBACnB,MAAM,MAAM,GAAG,GAAG,EAAE;wBAClB,IAAI,OAAO;4BAAE,OAAM;wBACnB,OAAO,GAAG,IAAI,CAAA;wBACd,GAAG,CAAC,mBAAmB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;wBAC1C,OAAO,EAAE,CAAA;oBACX,CAAC,CAAA;oBACD,GAAG,CAAC,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;oBACvD,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;gBACxB,CAAC,CAAC,CAAA;YACJ,CAAC;YACD,IAAI,YAAY;gBAAE,MAAM,YAAY,CAAA;YAEpC,eAAe;YACf,MAAM,QAAQ,GAAG,UAAU,GAAG,EAAE,KAAK,CAAC,CAAA,CAAC,2BAA2B;YAClE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAA;YAE7C,qEAAqE;YACrE,gEAAgE;YAChE,UAAU,CAAC,KAAK,EAAE,CAAA;QACpB,CAAC;QAED,8EAA8E;QAC9E,wEAAwE;QACxE,6EAA6E;QAC7E,wEAAwE;QACxE,8EAA8E;QAC9E,+BAA+B;QAC/B,IAAI,YAAY;YAAE,MAAM,YAAY,CAAA;QACpC,MAAM,OAAO,CAAC,IAAI,CAAC;YACjB,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;YACpB,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAC/B,UAAU,CACR,GAAG,EAAE,CACH,MAAM,CACJ,IAAI,KAAK,CACP,wDAAwD,gBAAgB,GAAG,IAAI,GAAG,CACnF,CACF,EACH,gBAAgB,CACjB,CACF;SACF,CAAC,CAAA;QACF,IAAI,YAAY;YAAE,MAAM,YAAY,CAAA;QACpC,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAA;QAE1C,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAA;QACrB,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAA;QAEzB,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;QAC7C,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,kCAAkC,EAAE,CAAC,MAAM,CAAC,UAAU,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;QAEnG,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAA;QAEzD,UAAU;QACV,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;QACpB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;QACnB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;QAEjB,OAAO,CAAC,GAAG,CAAC,kCAAkC,EAAE,CAAC,OAAO,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;QAC9F,OAAO,OAAO,CAAA;IAChB,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,YAAY,CAChB,MAAc,EACd,OAKC;QAED,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,MAAM,CAAC,UAAU,IAAI,EAAE,CAAA;QAC9D,MAAM,QAAQ,GAAG,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAA;QAC3E,0EAA0E;QAC1E,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAA;QAC1E,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAA;QAC7E,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,KAAK,CAAA;QAC7B,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,MAAM,CAAA;QAC/B,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAA;QAEnD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,MAAM,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,GAAG,SAAS,CAAC,CAAA;YACtD,MAAM,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAA,CAAC,wDAAwD;YACxF,iEAAiE;YACjE,IAAI,OAAO,CAAC,KAAK;gBAAE,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;YAC9D,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,MAA2B,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;YAC7E,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;YACtD,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;YACjE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC,CAAA;QAC7C,CAAC;QACD,OAAO,WAAW,CAAA;IACpB,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/encoder/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/encoder/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { ClipkitRuntime } from './runtime.js';
|
|
2
|
+
export { setLogger, getLogger, type Logger } from './logger.js';
|
|
3
|
+
export { projectElementQuad, unprojectToPlane, elementDepthZ, type Pt, } from './compositor/project.js';
|
|
4
|
+
export { mapToMediaTime, trimWindow, rateOf, timeRemapOf, trimDurationOf, type MediaTiming, } from './assets/media-time.js';
|
|
5
|
+
export { fadeBreakpoints, fadeGainAt, type FadePoint } from './audio/fades.js';
|
|
6
|
+
export { createMasterLimiter } from './audio/limiter.js';
|
|
7
|
+
export { applyEasing } from './animation/easings.js';
|
|
8
|
+
export { compileExpr, evalExpr, isExpr, type ExprScope } from './animation/expr.js';
|
|
9
|
+
export { ClipkitExporter, resolveRenderResolution, type ExportOptions, type FrameProducer, type RenderResolution, } from './encoder/exporter.js';
|
|
10
|
+
export type { Source, Element } from '@clipkit/protocol';
|
|
11
|
+
export { chunkCaptionWords, activeCaptionChunk, type CaptionChunk } from './text/caption-chunk.js';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAIhE,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,EACb,KAAK,EAAE,GACR,MAAM,yBAAyB,CAAC;AAIjC,OAAO,EACL,cAAc,EACd,UAAU,EACV,MAAM,EACN,WAAW,EACX,cAAc,EACd,KAAK,WAAW,GACjB,MAAM,wBAAwB,CAAC;AAIhC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAI/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAIzD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAGpF,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,gBAAgB,GACtB,MAAM,uBAAuB,CAAC;AAK/B,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAKzD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,yBAAyB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// @clipkit/runtime — public surface.
|
|
2
|
+
export { ClipkitRuntime } from './runtime.js';
|
|
3
|
+
export { setLogger, getLogger } from './logger.js';
|
|
4
|
+
// Pure projection helpers for editor camera-view gizmos (§item 6) —
|
|
5
|
+
// render-consistent (reuse the compositor's camera + resolve + matrix).
|
|
6
|
+
export { projectElementQuad, unprojectToPlane, elementDepthZ, } from './compositor/project.js';
|
|
7
|
+
// Composition-time → media-time mapping, shared with the playback
|
|
8
|
+
// engine (video pump sync + audio scheduling for video tracks).
|
|
9
|
+
export { mapToMediaTime, trimWindow, rateOf, timeRemapOf, trimDurationOf, } from './assets/media-time.js';
|
|
10
|
+
// Audio fade envelope, shared with the playback engine's scheduler so
|
|
11
|
+
// preview and export gains are identical.
|
|
12
|
+
export { fadeBreakpoints, fadeGainAt } from './audio/fades.js';
|
|
13
|
+
// Master output limiter, shared with the playback engine's scheduler so the
|
|
14
|
+
// preview master bus and the export master bus apply identical clip protection.
|
|
15
|
+
export { createMasterLimiter } from './audio/limiter.js';
|
|
16
|
+
// The normative easing evaluator — shared with the editors' curve
|
|
17
|
+
// display so the drawn curve IS the curve that renders.
|
|
18
|
+
export { applyEasing } from './animation/easings.js';
|
|
19
|
+
// Tier-A expression evaluator (editors/tools use compileExpr for live validity).
|
|
20
|
+
export { compileExpr, evalExpr, isExpr } from './animation/expr.js';
|
|
21
|
+
// Encoder (still callable directly for advanced use).
|
|
22
|
+
export { ClipkitExporter, resolveRenderResolution, } from './encoder/exporter.js';
|
|
23
|
+
// Caption windowing — split a caption's words into chunks (max_length) and pick
|
|
24
|
+
// the chunk active at time t. Shared with the editor timeline so its chunk
|
|
25
|
+
// blocks match what the renderer shows.
|
|
26
|
+
export { chunkCaptionWords, activeCaptionChunk } from './text/caption-chunk.js';
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AAErC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,SAAS,EAAe,MAAM,aAAa,CAAC;AAEhE,oEAAoE;AACpE,wEAAwE;AACxE,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,GAEd,MAAM,yBAAyB,CAAC;AAEjC,kEAAkE;AAClE,gEAAgE;AAChE,OAAO,EACL,cAAc,EACd,UAAU,EACV,MAAM,EACN,WAAW,EACX,cAAc,GAEf,MAAM,wBAAwB,CAAC;AAEhC,sEAAsE;AACtE,0CAA0C;AAC1C,OAAO,EAAE,eAAe,EAAE,UAAU,EAAkB,MAAM,kBAAkB,CAAC;AAE/E,4EAA4E;AAC5E,gFAAgF;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,kEAAkE;AAClE,wDAAwD;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,iFAAiF;AACjF,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAkB,MAAM,qBAAqB,CAAC;AAEpF,sDAAsD;AACtD,OAAO,EACL,eAAe,EACf,uBAAuB,GAIxB,MAAM,uBAAuB,CAAC;AAO/B,gFAAgF;AAChF,2EAA2E;AAC3E,wCAAwC;AACxC,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAqB,MAAM,yBAAyB,CAAC"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface Logger {
|
|
2
|
+
debug(message: string, ...args: unknown[]): void;
|
|
3
|
+
info(message: string, ...args: unknown[]): void;
|
|
4
|
+
warn(message: string, ...args: unknown[]): void;
|
|
5
|
+
error(message: string, ...args: unknown[]): void;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Replace the runtime's logger. Pass `'console'` to log to the browser console
|
|
9
|
+
* (default), `'silent'` to suppress everything, or a custom Logger object.
|
|
10
|
+
*/
|
|
11
|
+
export declare function setLogger(logger: Logger | 'console' | 'silent'): void;
|
|
12
|
+
export declare function getLogger(): Logger;
|
|
13
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IACjD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAClD;AAkBD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,IAAI,CAIrE;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Pluggable logger. The runtime prefixes its console output with `[clipkit]`
|
|
2
|
+
// (formerly `[v0]` in the upstream prototype). Consumers can swap in their
|
|
3
|
+
// own logger, silence everything, or route through their existing observability.
|
|
4
|
+
const silentLogger = {
|
|
5
|
+
debug: () => { },
|
|
6
|
+
info: () => { },
|
|
7
|
+
warn: () => { },
|
|
8
|
+
error: () => { },
|
|
9
|
+
};
|
|
10
|
+
const consoleLogger = {
|
|
11
|
+
debug: (m, ...a) => console.debug(`[clipkit] ${m}`, ...a),
|
|
12
|
+
info: (m, ...a) => console.info(`[clipkit] ${m}`, ...a),
|
|
13
|
+
warn: (m, ...a) => console.warn(`[clipkit] ${m}`, ...a),
|
|
14
|
+
error: (m, ...a) => console.error(`[clipkit] ${m}`, ...a),
|
|
15
|
+
};
|
|
16
|
+
let activeLogger = consoleLogger;
|
|
17
|
+
/**
|
|
18
|
+
* Replace the runtime's logger. Pass `'console'` to log to the browser console
|
|
19
|
+
* (default), `'silent'` to suppress everything, or a custom Logger object.
|
|
20
|
+
*/
|
|
21
|
+
export function setLogger(logger) {
|
|
22
|
+
if (logger === 'console')
|
|
23
|
+
activeLogger = consoleLogger;
|
|
24
|
+
else if (logger === 'silent')
|
|
25
|
+
activeLogger = silentLogger;
|
|
26
|
+
else
|
|
27
|
+
activeLogger = logger;
|
|
28
|
+
}
|
|
29
|
+
export function getLogger() {
|
|
30
|
+
return activeLogger;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,2EAA2E;AAC3E,iFAAiF;AASjF,MAAM,YAAY,GAAW;IAC3B,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;IACf,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;IACd,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC;IACd,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;CAChB,CAAC;AAEF,MAAM,aAAa,GAAW;IAC5B,KAAK,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IACzD,IAAI,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IACvD,IAAI,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IACvD,KAAK,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;CAC1D,CAAC;AAEF,IAAI,YAAY,GAAW,aAAa,CAAC;AAEzC;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,MAAqC;IAC7D,IAAI,MAAM,KAAK,SAAS;QAAE,YAAY,GAAG,aAAa,CAAC;SAClD,IAAI,MAAM,KAAK,QAAQ;QAAE,YAAY,GAAG,YAAY,CAAC;;QACrD,YAAY,GAAG,MAAM,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,YAAY,CAAC;AACtB,CAAC"}
|