textmode.export.js 1.8.0 → 1.8.1

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.
@@ -2,6 +2,13 @@
2
2
  export interface ExportFrameContext {
3
3
  frameIndex: number;
4
4
  frameCount: number;
5
+ /** Left edge of the output-frame interval. Alias of `timeSeconds`. */
6
+ startSeconds: number;
7
+ /** Center of the output-frame interval; use this to sample external media. */
8
+ centerSeconds: number;
9
+ /** Exclusive right edge of the output-frame interval. */
10
+ endSeconds: number;
11
+ /** @deprecated Use `startSeconds`. */
5
12
  timeSeconds: number;
6
13
  frameRate: number;
7
14
  signal?: AbortSignal;
@@ -1,21 +1,21 @@
1
1
  import type { PrepareExportFrame } from '../base';
2
2
  export type GIFRecordingState = 'idle' | 'recording' | 'encoding' | 'completed' | 'error';
3
3
  /**
4
- * Progress information emitted during the GIF export process.
4
+ * Progress information emitted while deterministic frames are captured and encoded as an animated GIF.
5
5
  *
6
- * @category Animation export
6
+ * @category GIF export
7
7
  *
8
8
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/GIFExportProgress | GIFExportProgress API reference}
9
9
  */
10
10
  export type GIFExportProgress = {
11
11
  /**
12
- * Current state of the recording process.
12
+ * Current GIF capture or encoding state.
13
13
  *
14
14
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/GIFExportProgress#state | GIFExportProgress.state API reference}
15
15
  */
16
16
  state: 'idle' | 'recording' | 'encoding' | 'completed' | 'error';
17
17
  /**
18
- * Number of frames that have been recorded so far.
18
+ * Number of frames captured so far.
19
19
  *
20
20
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/GIFExportProgress#frameindex | GIFExportProgress.frameIndex API reference}
21
21
  */
@@ -34,9 +34,9 @@ export type GIFExportProgress = {
34
34
  message?: string;
35
35
  };
36
36
  /**
37
- * Options for exporting the textmode content to GIF format.
37
+ * Options for capturing deterministic textmode frames as an animated GIF.
38
38
  *
39
- * @category Animation export
39
+ * @category GIF export
40
40
  *
41
41
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/GIFExportOptions | GIFExportOptions API reference}
42
42
  */
@@ -1,20 +1,3 @@
1
- import type { VideoBitrateMode, VideoCodec, VideoContentHint, VideoEncodingPlan, VideoGenerationOptions } from './types';
2
- export declare const MAX_SAFE_IN_MEMORY_VIDEO_BYTES = 100000000;
3
- export declare const ULTRA_FALLBACK_BITS_PER_PIXEL_PER_FRAME = 0.5;
4
- export type VideoQualityDescriptor = {
5
- kind: 'named';
6
- level: 'medium' | 'high' | 'very-high';
7
- } | {
8
- kind: 'bitrate';
9
- bitrate: number;
10
- bitrateMode: VideoBitrateMode;
11
- } | {
12
- kind: 'ultra';
13
- bitrate: number;
14
- };
15
- export declare function resolveUltraFallbackBitrate(width: number, height: number, frameRate: number): number;
16
- export declare function estimateVideoOutputBytes(bitrate: number, frameCount: number, frameRate: number): number;
17
- export declare function getVideoQualityDescriptor(plan: VideoEncodingPlan): VideoQualityDescriptor;
18
- export declare function normalizeVideoContentHint(value: VideoContentHint | undefined): VideoContentHint;
1
+ import type { VideoCodec, VideoEncodingPlan, VideoGenerationOptions } from './types';
2
+ /** Resolves product-level format constraints independently of encoder probing. */
19
3
  export declare function createVideoEncodingPlan(options: VideoGenerationOptions, codec?: VideoCodec): VideoEncodingPlan;
20
- export declare function assertVideoOutputFitsMemory(plan: VideoEncodingPlan, allowLargeInMemory: boolean): void;
@@ -15,12 +15,11 @@ export declare class VideoExporter {
15
15
  private _applyDefaultOptions;
16
16
  private _positiveInteger;
17
17
  private _positiveNumber;
18
- private _bitrate;
19
- private _bitrateMode;
20
- private _contentHint;
21
- private _latencyMode;
18
+ private _quality;
19
+ private _isBitrateMode;
22
20
  private _hardwareAcceleration;
23
21
  private _keyFrameInterval;
24
22
  private _currentPixelDensity;
25
23
  private _withExtension;
24
+ private _createFileSystemDestination;
26
25
  }
@@ -0,0 +1,8 @@
1
+ export interface VideoFrameTiming {
2
+ startSeconds: number;
3
+ centerSeconds: number;
4
+ endSeconds: number;
5
+ durationSeconds: number;
6
+ }
7
+ /** Produces one stable microsecond-rounded interval for an output frame. */
8
+ export declare function videoFrameTiming(frameIndex: number, frameRate: number): VideoFrameTiming;
@@ -2,10 +2,11 @@ import { type StreamTargetChunk } from 'mediabunny';
2
2
  import type { VideoExportProgress, VideoFrameDriverLike, VideoGenerationOptions } from './types';
3
3
  export type VideoOutputDestination = {
4
4
  kind: 'blob';
5
- allowLargeInMemory: boolean;
6
5
  } | {
7
6
  kind: 'stream';
8
7
  writable: WritableStream<StreamTargetChunk>;
8
+ /** Releases a destination selected before encoder probing starts. */
9
+ abort?: (reason?: unknown) => Promise<void>;
9
10
  };
10
11
  /** Records deterministic textmode frames through WebCodecs and muxes them with Mediabunny. */
11
12
  export declare class VideoRecorder {
@@ -1,2 +1,2 @@
1
1
  export { VideoExportError } from './errors';
2
- export type { VideoBitrateMode, VideoBitratePreset, VideoContentHint, VideoEncodingPlan, VideoExportErrorCode, VideoExportFormat, VideoExportOptions, VideoExportPhase, VideoFrameDriverLike, VideoHardwareAcceleration, VideoLatencyMode, VideoExportProgress, VideoGenerationOptions, VideoRecordingState, VideoRenderFrameOptions, } from './types';
2
+ export type { VideoBitrateMode, VideoEncodingPlan, VideoExportErrorCode, VideoExportFormat, VideoExportOptions, VideoExportPhase, VideoFrameDriverLike, VideoHardwareAcceleration, VideoQuality, VideoQualityLevel, VideoSaveDestination, VideoExportProgress, VideoGenerationOptions, VideoRecordingState, VideoRenderFrameOptions, } from './types';
@@ -1,45 +1,83 @@
1
1
  import type { PrepareExportFrame } from '../base';
2
2
  /**
3
- * Lifecycle state reported while a video export is being prepared, recorded, encoded, or completed.
3
+ * High-level lifecycle state reported while a video export is captured, encoded, or completed.
4
4
  *
5
- * @category Animation export
5
+ * @category Video export
6
6
  *
7
7
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoRecordingState | VideoRecordingState API reference}
8
8
  */
9
9
  export type VideoRecordingState = 'idle' | 'recording' | 'encoding' | 'completed' | 'error';
10
10
  /**
11
- * More granular phase information for progress UIs that need to distinguish setup, rendering, and finalization.
11
+ * Detailed phase information for progress UIs that distinguish capability probing, frame capture, and output.
12
12
  *
13
- * `rendering` is retained for 1.5.x compatibility. Current deterministic video capture emits `capturing`.
13
+ * Current exports emit `probing`, `capturing`, and either `writing` for streamed file-system output or `finalizing`
14
+ * for buffered output. `rendering`, `encoding`, and `draining` remain available for compatibility with older progress
15
+ * producers.
14
16
  *
15
- * @category Animation export
17
+ * @category Video export
16
18
  *
17
19
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportPhase | VideoExportPhase API reference}
18
20
  */
19
21
  export type VideoExportPhase = 'probing' | 'rendering' | 'capturing' | 'encoding' | 'draining' | 'writing' | 'finalizing';
20
22
  export type VideoCodec = 'vp8' | 'vp9' | 'avc' | (string & {});
21
23
  /**
22
- * Subjective bitrate preset used when an exact bits-per-second value is not supplied.
24
+ * Qualitative video quality level matching Mediabunny's five native levels.
23
25
  *
24
- * Higher presets request higher constant perceptual quality from Mediabunny. The `ultra` preset requests quantizer
25
- * zero with a frame-rate-aware bitrate fallback and should be described as near-lossless, never mathematically
26
- * lossless. For exact bitrate control, pass a numeric `bitrate` value in bits per second instead.
26
+ * Higher levels generally preserve more detail and produce larger, content-dependent files. Mediabunny may use
27
+ * quantizer-based encoding or a codec-adjusted bitrate, depending on codec and browser support.
27
28
  *
28
- * @category Animation export
29
+ * @category Video export
29
30
  *
30
- * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoBitratePreset | VideoBitratePreset API reference}
31
+ * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoQualityLevel | VideoQualityLevel API reference}
31
32
  */
32
- export type VideoBitratePreset = 'low' | 'medium' | 'high' | 'ultra';
33
+ export type VideoQualityLevel = 'very-low' | 'low' | 'medium' | 'high' | 'very-high';
33
34
  /**
34
- * Hint for the encoder's content-aware rate control.
35
+ * Video compression policy passed to Mediabunny.
35
36
  *
36
- * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoContentHint | VideoContentHint API reference}
37
+ * Use a named {@link VideoQualityLevel} for content-dependent qualitative encoding. Use the object form to request a
38
+ * positive target bitrate in bits per second and, optionally, constant or variable allocation. When `bitrateMode` is
39
+ * omitted, Mediabunny defaults bitrate-based encoding to `'variable'`. A target bitrate guides the encoder but does
40
+ * not guarantee an exact final file size.
41
+ *
42
+ * @example Named qualitative quality
43
+ * ```ts
44
+ * await t.saveVideo({ quality: 'very-high' });
45
+ * ```
46
+ *
47
+ * @example Target bitrate with constant allocation
48
+ * ```ts
49
+ * await t.saveVideo({ quality: { bitrate: 8_000_000, bitrateMode: 'constant' } });
50
+ * ```
51
+ *
52
+ * @category Video export
53
+ *
54
+ * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoQuality | VideoQuality API reference}
55
+ */
56
+ export type VideoQuality = VideoQualityLevel | {
57
+ bitrate: number;
58
+ bitrateMode?: VideoBitrateMode;
59
+ };
60
+ /**
61
+ * Destination policy used by `saveVideo()`.
62
+ *
63
+ * - `'download'` is the default. The complete video is buffered in memory before a browser download begins.
64
+ * - `'file-system'` opens the browser's save picker and streams encoded chunks directly to the selected file. It
65
+ * requires the File System Access API and rejects with `VIDEO_EXPORT_UNSUPPORTED` when that API is unavailable.
66
+ *
67
+ * This setting does not affect `toVideoBlob()`, which always returns an in-memory `Blob`.
68
+ *
69
+ * @category Video export
70
+ *
71
+ * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoSaveDestination | VideoSaveDestination API reference}
37
72
  */
38
- export type VideoContentHint = '' | 'motion' | 'detail' | 'text';
73
+ export type VideoSaveDestination = 'download' | 'file-system';
39
74
  /**
40
- * Video container format written by `saveVideo`.
75
+ * Video container format produced by `saveVideo()` and `toVideoBlob()`.
41
76
  *
42
- * @category Animation export
77
+ * MP4 uses AVC/H.264 and requires even coded dimensions. WebM selects VP9 when available and falls back to VP8; it
78
+ * is the only format that can be requested with transparency.
79
+ *
80
+ * @category Video export
43
81
  *
44
82
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportFormat | VideoExportFormat API reference}
45
83
  */
@@ -52,23 +90,13 @@ export type VideoExportFormat = 'webm' | 'mp4';
52
90
  * - `'constant'`: asks the encoder to keep the bitrate steadier throughout the export. This can make file size
53
91
  * more predictable, but may waste bits on simple frames or reduce detail on complex frames.
54
92
  *
55
- * @category Animation export
93
+ * If omitted for an explicit target bitrate, Mediabunny uses `'variable'`.
94
+ *
95
+ * @category Video export
56
96
  *
57
97
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoBitrateMode | VideoBitrateMode API reference}
58
98
  */
59
99
  export type VideoBitrateMode = 'variable' | 'constant';
60
- /**
61
- * Encoder scheduling mode.
62
- *
63
- * - `'quality'`: prioritizes complete, stable export output. Mediabunny notes that this mode prevents dropped frames.
64
- * - `'realtime'`: prioritizes low-latency encoding. It is intended for live streams and may drop frames when overloaded,
65
- * so it is usually not recommended for frame-perfect exports.
66
- *
67
- * @category Animation export
68
- *
69
- * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoLatencyMode | VideoLatencyMode API reference}
70
- */
71
- export type VideoLatencyMode = 'quality' | 'realtime';
72
100
  /**
73
101
  * WebCodecs hardware acceleration preference.
74
102
  *
@@ -78,34 +106,34 @@ export type VideoLatencyMode = 'quality' | 'realtime';
78
106
  * availability and output characteristics vary by device.
79
107
  * - `'prefer-software'`: prefer CPU encoding, often more consistent across machines, but usually slower.
80
108
  *
81
- * @category Animation export
109
+ * @category Video export
82
110
  *
83
111
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoHardwareAcceleration | VideoHardwareAcceleration API reference}
84
112
  */
85
113
  export type VideoHardwareAcceleration = 'no-preference' | 'prefer-hardware' | 'prefer-software';
86
- export type VideoExportErrorCode = 'VIDEO_EXPORT_UNSUPPORTED' | 'VIDEO_CODEC_UNSUPPORTED' | 'VIDEO_EXPORT_ABORTED' | 'VIDEO_EXPORT_TIMEOUT' | 'VIDEO_EXPORT_FAILED' | 'VIDEO_TRANSPARENCY_UNSUPPORTED' | 'VIDEO_DIMENSIONS_UNSUPPORTED' | 'VIDEO_OUTPUT_TOO_LARGE';
114
+ export type VideoExportErrorCode = 'VIDEO_EXPORT_UNSUPPORTED' | 'VIDEO_CODEC_UNSUPPORTED' | 'VIDEO_EXPORT_ABORTED' | 'VIDEO_EXPORT_TIMEOUT' | 'VIDEO_EXPORT_FAILED' | 'VIDEO_TRANSPARENCY_UNSUPPORTED' | 'VIDEO_DIMENSIONS_UNSUPPORTED';
87
115
  /**
88
- * Progress information emitted during the video export process.
116
+ * Progress information emitted while a deterministic video is probed, captured, and written.
89
117
  *
90
- * @category Animation export
118
+ * @category Video export
91
119
  *
92
120
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportProgress | VideoExportProgress API reference}
93
121
  */
94
122
  export type VideoExportProgress = {
95
123
  /**
96
- * Current state of the recording process.
124
+ * Current high-level export state.
97
125
  *
98
126
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportProgress#state | VideoExportProgress.state API reference}
99
127
  */
100
128
  state: VideoRecordingState;
101
129
  /**
102
- * Current export phase for newer progress UIs.
130
+ * Current detailed phase. See {@link VideoExportPhase} for current and compatibility-only values.
103
131
  *
104
132
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportProgress#phase | VideoExportProgress.phase API reference}
105
133
  */
106
134
  phase?: VideoExportPhase;
107
135
  /**
108
- * Number of frames that have been recorded so far.
136
+ * Number of frames captured so far.
109
137
  *
110
138
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportProgress#frameindex | VideoExportProgress.frameIndex API reference}
111
139
  */
@@ -123,7 +151,9 @@ export type VideoExportProgress = {
123
151
  */
124
152
  totalFrames?: number;
125
153
  /**
126
- * Export completion ratio between `0` and `1`.
154
+ * Normalized frame-capture completion ratio between `0` and `1`.
155
+ *
156
+ * Final writing or muxing may still be in progress when this value reaches `1`.
127
157
  *
128
158
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportProgress#progress | VideoExportProgress.progress API reference}
129
159
  */
@@ -135,22 +165,34 @@ export type VideoExportProgress = {
135
165
  */
136
166
  message?: string;
137
167
  /**
138
- * The rate-control path selected by the browser, when known.
168
+ * Effective codec family selected after capability probing (`avc`, `vp9`, or `vp8`).
169
+ *
170
+ * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportProgress#codec | VideoExportProgress.codec API reference}
171
+ */
172
+ codec?: VideoCodec;
173
+ /**
174
+ * Effective coded width in pixels.
175
+ *
176
+ * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportProgress#codedwidth | VideoExportProgress.codedWidth API reference}
177
+ */
178
+ codedWidth?: number;
179
+ /**
180
+ * Effective coded height in pixels.
139
181
  *
140
- * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportProgress#ratecontrol | VideoExportProgress.rateControl API reference}
182
+ * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportProgress#codedheight | VideoExportProgress.codedHeight API reference}
141
183
  */
142
- rateControl?: 'quantizer' | 'bitrate-fallback' | 'bitrate';
184
+ codedHeight?: number;
143
185
  /**
144
- * Conservative output-size estimate in bytes, when available.
186
+ * Exact output frame rate passed to the muxer.
145
187
  *
146
- * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportProgress#estimatedbytes | VideoExportProgress.estimatedBytes API reference}
188
+ * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportProgress#framerate | VideoExportProgress.frameRate API reference}
147
189
  */
148
- estimatedBytes?: number;
190
+ frameRate?: number;
149
191
  };
150
192
  /**
151
- * Options for exporting the textmode content to video format.
193
+ * Options for capturing deterministic textmode frames as MP4 or WebM video.
152
194
  *
153
- * @category Animation export
195
+ * @category Video export
154
196
  *
155
197
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportOptions | VideoExportOptions API reference}
156
198
  */
@@ -180,39 +222,23 @@ export type VideoExportOptions = {
180
222
  */
181
223
  frameRate?: number;
182
224
  /**
183
- * Target bitrate in bits per second or a quality preset. Defaults to `'medium'`.
184
- *
185
- * String values request constant-quality encoding through Mediabunny. `low`, `medium`, and `high` map to the
186
- * upstream `medium`, `high`, and `very-high` quality levels; `ultra` requests quantizer zero and may create very
187
- * large files. Numeric values remain exact bits-per-second targets and are wrapped in Mediabunny `Quality`.
188
- *
189
- * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportOptions#bitrate | VideoExportOptions.bitrate API reference}
190
- */
191
- bitrate?: number | VideoBitratePreset;
192
- /**
193
- * Bitrate allocation mode for numeric bitrates and quality fallback paths. Defaults to `'variable'`.
194
- *
195
- * Use `'variable'` for most exports so simple frames can compress efficiently and complex frames can receive more
196
- * bits. Use `'constant'` only when a steadier data rate is more important than compression efficiency.
225
+ * Video quality policy. Defaults to `'medium'`.
197
226
  *
198
- * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportOptions#bitratemode | VideoExportOptions.bitrateMode API reference}
199
- */
200
- bitrateMode?: VideoBitrateMode;
201
- /**
202
- * Content hint passed to the native video encoder. Defaults to `'text'`.
227
+ * Named levels map one-to-one to Mediabunny's qualitative levels and produce content-dependent file sizes. Use the
228
+ * object form to request a positive target bitrate in bits per second and an optional bitrate mode.
203
229
  *
204
- * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportOptions#contenthint | VideoExportOptions.contentHint API reference}
230
+ * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportOptions#quality | VideoExportOptions.quality API reference}
205
231
  */
206
- contentHint?: VideoContentHint;
232
+ quality?: VideoQuality;
207
233
  /**
208
- * Encoder latency mode. Defaults to `'quality'`.
234
+ * Save destination used by `saveVideo()`. Defaults to `'download'`.
209
235
  *
210
- * Use `'quality'` for deterministic exports; it prioritizes completed output and avoids dropped frames. Use
211
- * `'realtime'` only for low-latency use cases where dropped frames are acceptable.
236
+ * `'file-system'` opens a save picker and streams directly to the selected file when the File System Access API is
237
+ * available. `toVideoBlob()` always returns an in-memory blob and does not use this setting.
212
238
  *
213
- * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportOptions#latencymode | VideoExportOptions.latencyMode API reference}
239
+ * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportOptions#destination | VideoExportOptions.destination API reference}
214
240
  */
215
- latencyMode?: VideoLatencyMode;
241
+ destination?: VideoSaveDestination;
216
242
  /**
217
243
  * WebCodecs hardware acceleration hint. Defaults to `'no-preference'`.
218
244
  *
@@ -251,7 +277,7 @@ export type VideoExportOptions = {
251
277
  */
252
278
  prepareFrame?: PrepareExportFrame;
253
279
  /**
254
- * When true, attempts to preserve alpha data in WebM recordings. MP4 exports reject this option.
280
+ * When `true`, attempts to preserve alpha data in WebM recordings. MP4 exports reject this option.
255
281
  *
256
282
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportOptions#transparent | VideoExportOptions.transparent API reference}
257
283
  */
@@ -268,22 +294,13 @@ export type VideoExportOptions = {
268
294
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportOptions#debuglogging | VideoExportOptions.debugLogging API reference}
269
295
  */
270
296
  debugLogging?: boolean;
271
- /**
272
- * Allows `toVideoBlob()` to retain its in-memory contract above the safe 100 MB default.
273
- *
274
- * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoExportOptions#allowlargeinmemory | VideoExportOptions.allowLargeInMemory API reference}
275
- */
276
- allowLargeInMemory?: boolean;
277
297
  };
278
298
  export interface VideoGenerationOptions {
279
299
  filename?: string;
280
300
  format: VideoExportFormat;
281
301
  frameRate: number;
282
302
  frameCount: number;
283
- bitrate: number | VideoBitratePreset;
284
- bitrateMode: VideoBitrateMode;
285
- contentHint?: VideoContentHint;
286
- latencyMode: VideoLatencyMode;
303
+ quality: VideoQuality;
287
304
  hardwareAcceleration: VideoHardwareAcceleration;
288
305
  keyFrameInterval: number;
289
306
  pixelDensity: number;
@@ -291,7 +308,6 @@ export interface VideoGenerationOptions {
291
308
  height: number;
292
309
  transparent: boolean;
293
310
  debugLogging: boolean;
294
- allowLargeInMemory?: boolean;
295
311
  signal?: AbortSignal;
296
312
  prepareFrame?: PrepareExportFrame;
297
313
  }
@@ -300,14 +316,7 @@ export interface VideoEncodingPlan {
300
316
  extension: '.webm' | '.mp4';
301
317
  mimeType: string;
302
318
  codec: VideoCodec;
303
- bitrate: number;
304
- bitrateMode: VideoBitrateMode;
305
- qualityPreset: VideoBitratePreset | null;
306
- rateControlIntent: 'bitrate' | 'constant-quality' | 'ultra';
307
- qualityLevel?: 'medium' | 'high' | 'very-high';
308
- contentHint: VideoContentHint;
309
- estimatedBytes: number;
310
- latencyMode: VideoLatencyMode;
319
+ quality: VideoQuality;
311
320
  hardwareAcceleration: VideoHardwareAcceleration;
312
321
  keyFrameInterval: number;
313
322
  frameRate: number;
@@ -5,15 +5,38 @@
5
5
  *
6
6
  * ## Choose an output
7
7
  *
8
- * Use **canvas capture** for the exact image on screen: PNG, JPEG, WebP, GIF,
9
- * or video preserve compositing, filters, shaders, and post-processing. Use
10
- * **layer data export** when the artwork should stay editable or machine
11
- * readable: TXT, SVG, and JSON read from the selected layer, while JSON can
12
- * also describe the full layer stack.
8
+ * Use **canvas capture** for the rendered image on screen: PNG, JPEG, WebP,
9
+ * GIF, and video preserve compositing, filters, shaders, and post-processing.
10
+ * Use **layer data export** when the artwork should stay editable or machine
11
+ * readable: TXT and SVG read from the selected layer, while JSON can describe
12
+ * either the selected layer or the full layer stack.
13
13
  *
14
14
  * Start with {@link ExportPlugin}, then call the helpers added to your sketch
15
15
  * or use the built-in export overlay. For recipes and format trade-offs, read
16
16
  * the [Exporting guide](/docs/exporting).
17
+ *
18
+ * @categoryDescription Workflow
19
+ * Install the plugin and use the export helpers added to a textmode.js sketch.
20
+ *
21
+ * @categoryDescription Canvas capture
22
+ * Export a still image from the rendered canvas.
23
+ *
24
+ * @categoryDescription GIF export
25
+ * Capture deterministic frames and encode an animated GIF.
26
+ *
27
+ * @categoryDescription Video export
28
+ * Capture deterministic frames and encode MP4 or WebM video with Mediabunny.
29
+ *
30
+ * @categoryDescription Layer data export
31
+ * Export selected-layer text or vector data as TXT or SVG.
32
+ *
33
+ * @categoryDescription JSON document data
34
+ * Export selected-layer or full-stack document data as JSON.
35
+ *
36
+ * @categoryDescription Overlay
37
+ * Configure and control the built-in export overlay.
38
+ *
39
+ * @showCategories
17
40
  */
18
41
  import type { TextmodePlugin } from 'textmode.js';
19
42
  import './augmentations';
@@ -24,7 +47,7 @@ export type { SVGExportOptions } from './exporters/svg';
24
47
  export type { TXTExportOptions } from './exporters/txt';
25
48
  export type { JSONExportColorMode, JSONExportOptions, JSONExportTarget, TextmodeDocumentJSON } from './exporters/json';
26
49
  export type { GIFExportOptions, GIFExportProgress } from './exporters/gif';
27
- export type { VideoBitrateMode, VideoBitratePreset, VideoContentHint, VideoExportFormat, VideoExportOptions, VideoExportPhase, VideoExportProgress, VideoHardwareAcceleration, VideoLatencyMode, VideoRecordingState, } from './exporters/video';
50
+ export type { VideoBitrateMode, VideoExportFormat, VideoExportOptions, VideoExportPhase, VideoExportProgress, VideoHardwareAcceleration, VideoQuality, VideoQualityLevel, VideoSaveDestination, VideoRecordingState, } from './exporters/video';
28
51
  export type { LayerExportOptions } from './exporters/base';
29
52
  /**
30
53
  * Default export plugin instance for the standard textmode.js workflow.
@@ -3,11 +3,9 @@ import type { BladeConfig } from './Blade';
3
3
  import { Blade } from './Blade';
4
4
  export declare class VideoBlade extends Blade<VideoExportOptions> {
5
5
  private formatSelect;
6
- private bitrateSelect;
6
+ private qualitySelect;
7
7
  private frameRateInput;
8
8
  private frameCountInput;
9
- private bitrateModeSelect;
10
- private latencyModeSelect;
11
9
  private hardwareAccelerationSelect;
12
10
  private keyFrameIntervalInput;
13
11
  private transparencyInput;
@@ -27,13 +25,12 @@ export declare class VideoBlade extends Blade<VideoExportOptions> {
27
25
  private syncStatus;
28
26
  private resolvePlannedFrameCount;
29
27
  private applyDefaults;
30
- private resolveBitratePreset;
31
- private readonly handleBitrateChange;
28
+ private resolveQuality;
29
+ private readonly handleQualityChange;
32
30
  private readonly handleEstimateChange;
33
31
  private syncReadyStatus;
34
32
  private readonly handleFormatChange;
35
33
  private syncOutputEstimate;
36
- private formatBytes;
37
34
  protected _onUnmount(): void;
38
35
  private syncTransparencyAvailability;
39
36
  }
@@ -2,7 +2,7 @@ import type { ImageExportOptions } from '../exporters/image';
2
2
  import type { TXTExportOptions } from '../exporters/txt';
3
3
  import type { SVGExportOptions } from '../exporters/svg';
4
4
  import type { GIFExportOptions } from '../exporters/gif';
5
- import type { VideoBitratePreset, VideoExportOptions } from '../exporters/video';
5
+ import type { VideoExportOptions } from '../exporters/video';
6
6
  import type { JSONExportOptions } from '../exporters/json';
7
7
  export type ExportFormat = 'txt' | 'json' | 'image' | 'gif' | 'video' | 'svg';
8
8
  export type ExportOptionsMap = {
@@ -18,9 +18,7 @@ export type JSONOverlayDefaults = Pick<JSONExportOptions, 'target' | 'pretty' |
18
18
  export type ImageOverlayDefaults = Pick<ImageExportOptions, 'format' | 'scale'>;
19
19
  export type SVGOverlayDefaults = Pick<SVGExportOptions, 'includeBackgroundRectangles' | 'drawMode' | 'strokeWidth'>;
20
20
  export type GIFOverlayDefaults = Pick<GIFExportOptions, 'frameCount' | 'frameRate' | 'scale' | 'repeat'>;
21
- export type VideoOverlayDefaults = Pick<VideoExportOptions, 'format' | 'frameCount' | 'frameRate' | 'bitrateMode' | 'latencyMode' | 'hardwareAcceleration' | 'keyFrameInterval' | 'transparent'> & {
22
- bitrate?: VideoBitratePreset;
23
- };
21
+ export type VideoOverlayDefaults = Pick<VideoExportOptions, 'format' | 'frameCount' | 'frameRate' | 'quality' | 'hardwareAcceleration' | 'keyFrameInterval' | 'transparent'>;
24
22
  /**
25
23
  * Curated default options for every export format.
26
24
  *
@@ -2,7 +2,7 @@ import type { ImageExportOptions } from './exporters/image';
2
2
  import type { TXTExportOptions } from './exporters/txt';
3
3
  import type { SVGExportOptions } from './exporters/svg';
4
4
  import type { GIFExportOptions } from './exporters/gif';
5
- import type { VideoBitratePreset, VideoExportOptions } from './exporters/video';
5
+ import type { VideoExportOptions } from './exporters/video';
6
6
  import type { JSONExportOptions, TextmodeDocumentJSON } from './exporters/json';
7
7
  /**
8
8
  * Default TXT export fields controlled by the export overlay.
@@ -51,9 +51,7 @@ export type GIFOverlayDefaults = Pick<GIFExportOptions, 'frameCount' | 'frameRat
51
51
  *
52
52
  * @see {@link https://code.textmode.art/api/textmode.export.js/type-aliases/VideoOverlayDefaults | VideoOverlayDefaults API reference}
53
53
  */
54
- export type VideoOverlayDefaults = Pick<VideoExportOptions, 'format' | 'frameCount' | 'frameRate' | 'bitrateMode' | 'latencyMode' | 'hardwareAcceleration' | 'keyFrameInterval' | 'transparent'> & {
55
- bitrate?: VideoBitratePreset;
56
- };
54
+ export type VideoOverlayDefaults = Pick<VideoExportOptions, 'format' | 'frameCount' | 'frameRate' | 'quality' | 'hardwareAcceleration' | 'keyFrameInterval' | 'transparent'>;
57
55
  /**
58
56
  * Per-format default options used to seed the overlay UI inputs at mount time
59
57
  * and after a {@link ExportOverlayController.resetDefaults} call.
@@ -463,15 +461,29 @@ export interface TextmodeExportAPI {
463
461
  *
464
462
  * @example
465
463
  * ```ts
466
- * await t.saveVideo({ frameCount: 240, frameRate: 60, filename: 'capture' });
464
+ * // Mediabunny's qualitative quality levels produce content-dependent file sizes.
467
465
  * await t.saveVideo({
468
466
  * format: 'webm',
469
- * bitrate: 'high',
470
- * bitrateMode: 'variable',
471
- * latencyMode: 'quality',
472
- * keyFrameInterval: 2,
467
+ * quality: 'very-high',
468
+ * frameCount: 240,
469
+ * frameRate: 60,
470
+ * filename: 'high-quality-capture',
471
+ * });
472
+ *
473
+ * // Request a target bitrate and rate-control mode.
474
+ * await t.saveVideo({
475
+ * quality: { bitrate: 8_000_000, bitrateMode: 'variable' },
473
476
  * frameCount: 240,
474
- * filename: 'capture',
477
+ * frameRate: 60,
478
+ * filename: 'target-bitrate-capture',
479
+ * });
480
+ *
481
+ * // Stream directly to a user-selected file when the browser supports it.
482
+ * await t.saveVideo({
483
+ * destination: 'file-system',
484
+ * quality: 'high',
485
+ * frameCount: 240,
486
+ * frameRate: 60,
475
487
  * });
476
488
  * ```
477
489
  *
@@ -479,7 +491,9 @@ export interface TextmodeExportAPI {
479
491
  */
480
492
  saveVideo(options?: VideoExportOptions): Promise<void>;
481
493
  /**
482
- * Generates a video blob without downloading it.
494
+ * Generates an in-memory video blob without downloading it.
495
+ *
496
+ * `destination` is only used by {@link saveVideo}; this method always buffers and returns a `Blob`.
483
497
  *
484
498
  * @example
485
499
  * ```ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "textmode.export.js",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "Export plugin for textmode.js - Save your creations as images, GIFs, videos, SVG, JSON, and plain text.",
5
5
  "type": "module",
6
6
  "devEngines": {
@@ -64,7 +64,7 @@
64
64
  },
65
65
  "dependencies": {
66
66
  "gifenc": "^1.0.1",
67
- "mediabunny": "^1.52.3"
67
+ "mediabunny": "1.55.2"
68
68
  },
69
69
  "devDependencies": {
70
70
  "@textmode/build": "^0.1.0",