asciify-engine 1.0.92 → 1.0.94

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.
@@ -0,0 +1,730 @@
1
+ ---
2
+ name: asciify-engine
3
+ description: Convert images, videos, GIFs, webcam streams, text, and animated backgrounds into high-performance ASCII art with the asciify-engine npm package. Use when creating ASCII media, integrating asciifyVideo/asciify/asciifyGif, building scroll-synced ASCII video, tuning FPS/detail/performance, using compact text-frame APIs, hover effects, chroma key, recording/export, or updating an app that depends on asciify-engine.
4
+ ---
5
+
6
+ # asciify-engine
7
+
8
+ Use this skill for the `asciify-engine` npm package.
9
+
10
+ **Package:** `asciify-engine`
11
+ **Current version:** `1.0.93`
12
+ **Playground:** https://asciify.org
13
+ **GitHub:** https://github.com/ayangabryl/asciify-engine
14
+
15
+ The engine is zero-dependency except GIF decoding. It renders ASCII art on canvas from images, videos, GIFs, webcam streams, generated backgrounds, and text.
16
+
17
+ ## When To Use
18
+
19
+ Use this skill when the user wants to:
20
+
21
+ - Convert images, videos, GIFs, webcam, or text into ASCII art.
22
+ - Add ASCII video/backgrounds to React, Next.js, Vue, Svelte, or vanilla JS.
23
+ - Build scroll-synced ASCII video with GSAP ScrollTrigger or native scroll.
24
+ - Improve ASCII media performance, FPS, detail, resolution, or hover behavior.
25
+ - Use chroma key, fullcolor, accent, matrix, grayscale, dense/braille charsets, or hover effects.
26
+ - Use low-level prepared/compact frame APIs.
27
+ - Record/export ASCII canvas output.
28
+ - Update docs, package usage, or skill instructions for `asciify-engine`.
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ npm install asciify-engine
34
+ ```
35
+
36
+ For existing apps, install the latest tested version:
37
+
38
+ ```bash
39
+ npm install asciify-engine@1.0.93
40
+ ```
41
+
42
+ ## Mental Model
43
+
44
+ Prefer the simple APIs first:
45
+
46
+ - `asciify()` for static images/canvas/video elements.
47
+ - `asciifyVideo()` for live or scroll-synced video.
48
+ - `asciifyGif()` for animated GIF files.
49
+ - `asciiBackground()` for procedural ASCII backgrounds.
50
+
51
+ For high-performance media, the engine uses compact text-frame paths when possible:
52
+
53
+ - `imageToAsciiTextFrame()`
54
+ - `videoToAsciiTextFrames()`
55
+ - `gifToAsciiTextFrames()`
56
+ - `renderTextFrameToCanvas()`
57
+
58
+ These avoid object-per-cell frames and are the preferred low-level APIs for dense media, including fullcolor in `1.0.91+`.
59
+
60
+ Use legacy object frames only when you need per-cell mutation, dots mode, heavy hover/animation transforms, or compatibility with existing `AsciiFrame` consumers:
61
+
62
+ - `imageToAsciiFrame()`
63
+ - `videoToAsciiFrames()`
64
+ - `gifToAsciiFrames()`
65
+ - `renderFrameToCanvas()`
66
+
67
+ Use `options.sourceCrop` when the source media has empty edges or needs tighter framing without changing the destination canvas size. Percent values are normalized `0–1` by default:
68
+
69
+ ```ts
70
+ options: {
71
+ sourceCrop: { y: 0.16, height: 0.62 },
72
+ }
73
+ ```
74
+
75
+ `sourceCrop` is opt-in. When omitted, the engine samples the full source exactly as older versions did.
76
+
77
+ ## Visual Target
78
+
79
+ Good ASCII media should feel intentional, not like a broken video filter.
80
+
81
+ - The subject silhouette is readable at first glance.
82
+ - Character density reveals form, light, and motion without turning into noise.
83
+ - The canvas respects the media aspect ratio and fills the intended container.
84
+ - Accent/fullcolor choices support the page design instead of shouting over it.
85
+ - Text is crisp, not browser-blurred, stretched, or visibly low resolution.
86
+ - Motion updates feel continuous; if FPS drops, reduce work before adding effects.
87
+
88
+ ## Decision Playbooks
89
+
90
+ ### User Wants More Detail
91
+
92
+ Do not only reduce `fontSize`. Use this ladder:
93
+
94
+ 1. Confirm the canvas/container is actually large enough and not CSS-stretched from a tiny backing buffer.
95
+ 2. Use `fitTo` for videos so the engine owns canvas sizing.
96
+ 3. Use `CHARSETS.dense` for normal ASCII detail.
97
+ 4. Enable `normalize: true` for muted or low-contrast sources.
98
+ 5. Raise `maxRenderDimension` one step: `960 -> 1280 -> 1600 -> 2048`.
99
+ 6. Then lower `fontSize`: `8 -> 6 -> 5 -> 4`.
100
+ 7. Try `colorMode: 'accent'` before `fullcolor` if the design can be monochrome.
101
+ 8. Use `CHARSETS.braille` only when ultra-detail matters and the style can handle the texture.
102
+
103
+ Stop when the subject reads clearly. More cells after that often make the image noisier, not better.
104
+
105
+ ### User Wants Smoother FPS
106
+
107
+ Reduce hot-path work in this order:
108
+
109
+ 1. Keep `animationStyle: 'none'` and `hoverStrength: 0`.
110
+ 2. Use compact text-frame-compatible settings: `renderMode: 'ascii'`, no `charsetFrames`.
111
+ 3. Prefer `accent`, `matrix`, or `grayscale`; keep `fullcolor` only when color matters.
112
+ 4. Lower `maxRenderDimension`: `2048 -> 1600 -> 1280 -> 960`.
113
+ 5. Raise `fontSize`: `4 -> 5 -> 6 -> 8`.
114
+ 6. Lower `fps`: `60 -> 30 -> 24`.
115
+ 7. Avoid `dots`, per-cell hover, and animated charsets on dense video.
116
+
117
+ If FPS is still poor, inspect whether the app is resizing the canvas every frame or remounting the component.
118
+
119
+ ### User Wants A Premium Hero
120
+
121
+ Recommended starting point:
122
+
123
+ ```ts
124
+ {
125
+ fitTo: hero,
126
+ fontSize: 5,
127
+ fps: 60,
128
+ maxRenderDimension: 1280,
129
+ artStyle: 'classic',
130
+ options: {
131
+ charset: CHARSETS.dense,
132
+ colorMode: 'accent',
133
+ accentColor: '#e8d7b7',
134
+ normalize: true,
135
+ animationStyle: 'none',
136
+ hoverStrength: 0,
137
+ }
138
+ }
139
+ ```
140
+
141
+ Design rules:
142
+
143
+ - Use one restrained accent color pulled from the brand/page palette.
144
+ - Put ASCII behind or below the core CTA, not directly under tiny text.
145
+ - Use masks or fades at edges when the ASCII meets page content.
146
+ - Keep the hero background quiet enough that the headline wins.
147
+ - Use scroll scrub only when it tells a story; do not scrub decorative noise.
148
+
149
+ ### User Wants Fullcolor
150
+
151
+ Use fullcolor when color carries product meaning, artwork, identity, or footage mood.
152
+
153
+ Start with:
154
+
155
+ ```ts
156
+ {
157
+ fontSize: 6,
158
+ fps: 30,
159
+ maxRenderDimension: 1280,
160
+ artStyle: 'art',
161
+ options: {
162
+ charset: CHARSETS.dense,
163
+ colorMode: 'fullcolor',
164
+ normalize: true,
165
+ animationStyle: 'none',
166
+ hoverStrength: 0,
167
+ }
168
+ }
169
+ ```
170
+
171
+ If it is slow, first lower `maxRenderDimension` or raise `fontSize`. Do not jump straight to `fontSize: 3`.
172
+
173
+ ### User Wants Hover Interaction
174
+
175
+ Hover is per-cell work. Keep it deliberate:
176
+
177
+ - Use `fontSize >= 8` for large canvases.
178
+ - Use smaller framed demos rather than full-screen 4px ASCII.
179
+ - Start with `HOVER_PRESETS.subtle` or `hoverStrength: 0.2`.
180
+ - Avoid hover on scroll-synced video unless the canvas is small.
181
+ - Prefer hover for static images, generated text backgrounds, or product demos.
182
+
183
+ ### User Says It Is Blurry
184
+
185
+ Check in this order:
186
+
187
+ 1. Is the canvas CSS size different from its backing `width`/`height`?
188
+ 2. For video, is `fitTo` provided?
189
+ 3. Is the source itself low resolution?
190
+ 4. Is `maxRenderDimension` too low for the displayed size?
191
+ 5. Is CSS applying `filter`, `transform: scale`, or opacity compositing that softens text?
192
+ 6. For tiny font ASCII, verify the design accepts raster-like pixel detail.
193
+
194
+ ### User Says It Is Blank
195
+
196
+ Check:
197
+
198
+ 1. Source loaded and video has metadata.
199
+ 2. Canvas has nonzero width/height.
200
+ 3. Video is not `display: none`.
201
+ 4. `chromaKey` is not removing the subject.
202
+ 5. `invert` and page background are not making characters invisible.
203
+ 6. For async React use, cleanup did not run before `asciifyVideo()` resolved.
204
+
205
+ ### User Says It Is Too Large Or Overflows
206
+
207
+ Use layout fixes before quality fixes:
208
+
209
+ - Wrap canvas in a positioned container.
210
+ - Set canvas CSS to `position:absolute; inset:0; width:100%; height:100%`.
211
+ - Use `fitTo: container`.
212
+ - Keep the parent aspect ratio or explicit height stable.
213
+ - Avoid manually setting `canvas.width = window.innerWidth` in React render.
214
+
215
+ ### User Wants To Remove Empty Space In The Media
216
+
217
+ Prefer source cropping over layout hacks when the video/image itself has dead space:
218
+
219
+ ```ts
220
+ await asciifyVideo(video, canvas, {
221
+ fitTo: hero,
222
+ options: {
223
+ chromaKey: true,
224
+ sourceCrop: { y: 0.16, height: 0.62 },
225
+ },
226
+ });
227
+ ```
228
+
229
+ - `sourceCrop` happens before ASCII sampling, so the subject is reframed without changing the canvas box.
230
+ - Default unit is `'percent'`; use values from `0` to `1`.
231
+ - Use `{ unit: 'pixel', x, y, width, height }` for exact media-pixel crops.
232
+ - Keep the crop aspect ratio close to the output aspect ratio when you want zero perceived stretching.
233
+ - For hero videos, crop the source first, then use small layout overlap only if the next section needs to tuck closer.
234
+
235
+ ### Scroll-Scrub Performance Model
236
+
237
+ In `1.0.93+`, the fast text-frame scrub path uses a Pretext-inspired split:
238
+
239
+ - Prepare/cache frames lazily around the current scroll target.
240
+ - Render compact row strings instead of object-per-cell frames.
241
+ - Diff transparent rows and only redraw rows whose text changed.
242
+ - Prefer `fastSeek()` when the browser supports it.
243
+ - Prefetch nearby frames around the current target so scrolling back and forth has fewer misses.
244
+
245
+ For smooth scrub, keep options compatible with this fast path:
246
+
247
+ ```ts
248
+ {
249
+ renderMode: 'ascii',
250
+ animationStyle: 'none',
251
+ hoverStrength: 0,
252
+ colorMode: 'accent', // or grayscale/matrix
253
+ }
254
+ ```
255
+
256
+ ## Design Playbooks
257
+
258
+ ### Dark Premium Landing Page
259
+
260
+ - Use `#121212` or near-black page background.
261
+ - Prefer `accent` over `fullcolor` unless the footage itself is beautiful.
262
+ - Use warm off-white or brand accent, not neon by default.
263
+ - Pair ASCII with framed layout, thin borders, or quiet masks.
264
+ - Keep copy short; ASCII should carry some of the storytelling.
265
+
266
+ ### Technical / Infrastructure Aesthetic
267
+
268
+ - Use `matrix`, `grayscale`, or a cool `accentColor`.
269
+ - Use `CHARSETS.dense`, `lines`, `box`, or `geometric`.
270
+ - Compose with visible grid lines, clipped containers, and measured spacing.
271
+ - Avoid playful emoji/katakana unless the brand asks for it.
272
+
273
+ ### Editorial / Portfolio Aesthetic
274
+
275
+ - Use `accent` with a soft paper/warm ink palette.
276
+ - Use slower video, stills, or subtle scroll reveal.
277
+ - Keep `fontSize: 5-8`; avoid over-dense unreadable texture.
278
+ - Use ASCII as proof/atmosphere around work, not as a gimmick.
279
+
280
+ ### Playground / Demo Aesthetic
281
+
282
+ - Show controls that map to real engine tradeoffs: detail, FPS, color, charset, hover.
283
+ - Surface live `cols x rows`, FPS, and current source dimensions.
284
+ - Include presets: `Smooth`, `Detailed`, `Fullcolor`, `Interactive`.
285
+ - When changing presets, explain the performance tradeoff in the UI.
286
+
287
+ ## Quality Checks
288
+
289
+ - Subject is recognizable in a screenshot.
290
+ - FPS is stable for 5-10 seconds, not just on first load.
291
+ - The canvas does not resize every frame.
292
+ - Text/CTA remains readable over or near the ASCII.
293
+ - Mobile uses a less expensive preset than desktop when needed.
294
+ - Reduced-motion users still get a static or slower frame.
295
+ - Cleanup runs on unmount and cancels video/background loops.
296
+
297
+ ## Simple APIs
298
+
299
+ ### Static Image
300
+
301
+ ```ts
302
+ import { asciify, CHARSETS } from 'asciify-engine';
303
+
304
+ await asciify('/photo.jpg', canvas, {
305
+ fontSize: 6,
306
+ artStyle: 'art',
307
+ options: {
308
+ charset: CHARSETS.dense,
309
+ colorMode: 'fullcolor',
310
+ normalize: true,
311
+ },
312
+ });
313
+ ```
314
+
315
+ ### Live Video
316
+
317
+ ```ts
318
+ import { asciifyVideo, CHARSETS } from 'asciify-engine';
319
+
320
+ const stop = await asciifyVideo('/clip.mp4', canvas, {
321
+ fitTo: container,
322
+ fontSize: 6,
323
+ fps: 60,
324
+ maxRenderDimension: 1280,
325
+ artStyle: 'classic',
326
+ options: {
327
+ charset: CHARSETS.dense,
328
+ colorMode: 'accent',
329
+ accentColor: '#e8d7b7',
330
+ normalize: true,
331
+ },
332
+ });
333
+
334
+ // cleanup
335
+ stop();
336
+ ```
337
+
338
+ ### GIF
339
+
340
+ ```ts
341
+ import { asciifyGif } from 'asciify-engine';
342
+
343
+ const stop = await asciifyGif('/loop.gif', canvas, {
344
+ fontSize: 8,
345
+ artStyle: 'letters',
346
+ options: { colorMode: 'fullcolor' },
347
+ });
348
+
349
+ stop();
350
+ ```
351
+
352
+ ## Scroll-Synced Video
353
+
354
+ `asciifyVideo()` supports scroll scrubbing. Use this for landing-page hero reveals, editorial sections, and pinned/scrollytelling moments.
355
+
356
+ ### GSAP ScrollTrigger
357
+
358
+ ```ts
359
+ import gsap from 'gsap';
360
+ import { ScrollTrigger } from 'gsap/ScrollTrigger';
361
+ import { asciifyVideo, CHARSETS } from 'asciify-engine';
362
+
363
+ const stop = await asciifyVideo('/hero.mp4', canvas, {
364
+ fitTo: wrapper,
365
+ fontSize: 4,
366
+ fps: 60,
367
+ maxRenderDimension: 1280,
368
+ trim: { start: 2.2, end: 6.65 },
369
+ scroll: {
370
+ gsap,
371
+ ScrollTrigger,
372
+ trigger: wrapper,
373
+ start: 'top 88%',
374
+ end: 'bottom 18%',
375
+ scrub: 0.45,
376
+ from: 2.2,
377
+ to: 6.65,
378
+ },
379
+ options: {
380
+ charset: CHARSETS.dense,
381
+ colorMode: 'accent',
382
+ accentColor: '#e8d7b7',
383
+ normalize: true,
384
+ chromaKey: true,
385
+ chromaKeyTolerance: 84,
386
+ },
387
+ });
388
+ ```
389
+
390
+ ### Native Scroll Scrub
391
+
392
+ ```ts
393
+ const stop = await asciifyVideo('/hero.mp4', canvas, {
394
+ fitTo: wrapper,
395
+ fontSize: 6,
396
+ scroll: {
397
+ trigger: wrapper,
398
+ from: 0,
399
+ to: 5,
400
+ },
401
+ });
402
+ ```
403
+
404
+ ### Scroll Best Practices
405
+
406
+ - Use `scroll` for time-to-scroll mapping, not custom `video.currentTime` loops.
407
+ - Pass the same `from`/`to` as `trim.start`/`trim.end` when scrubbing a clipped range.
408
+ - Use `fps: 30-60`; choose `60` for smooth short hero clips, `24-30` for heavy fullcolor.
409
+ - Use `maxRenderDimension: 960-1280` for large full-width hero videos. Use `2048` only when truly needed.
410
+ - Use `fontSize: 4-6` for detailed hero ASCII; below `4px` is expensive and should use compact text-frame paths only.
411
+ - Avoid hover effects on dense scroll video. Hover is per-cell work.
412
+ - Never set the backing video to `display: none`; the API keeps URL-created videos decode-safe automatically.
413
+
414
+ ## Performance Guide
415
+
416
+ ### Fastest Media Settings
417
+
418
+ For smooth high-density video:
419
+
420
+ ```ts
421
+ {
422
+ fontSize: 5,
423
+ fps: 60,
424
+ maxRenderDimension: 1280,
425
+ artStyle: 'classic',
426
+ options: {
427
+ charset: CHARSETS.dense,
428
+ colorMode: 'accent',
429
+ animationStyle: 'none',
430
+ hoverStrength: 0,
431
+ normalize: true,
432
+ }
433
+ }
434
+ ```
435
+
436
+ ### Fullcolor Settings
437
+
438
+ Fullcolor is supported by the compact text-frame path in `1.0.91+`.
439
+
440
+ ```ts
441
+ {
442
+ fontSize: 6,
443
+ fps: 30,
444
+ maxRenderDimension: 1280,
445
+ artStyle: 'art',
446
+ options: {
447
+ charset: CHARSETS.dense,
448
+ colorMode: 'fullcolor',
449
+ animationStyle: 'none',
450
+ hoverStrength: 0,
451
+ normalize: true,
452
+ }
453
+ }
454
+ ```
455
+
456
+ Use fullcolor when the source color is important. Use `accent` when you want the highest FPS and a more designed monochrome look.
457
+
458
+ ### Detail Tuning
459
+
460
+ - `fontSize`: main detail/performance knob. Smaller means more cells.
461
+ - `maxRenderDimension`: caps media processing resolution before ASCII conversion.
462
+ - `CHARSETS.dense`: best general image/video ramp.
463
+ - `CHARSETS.braille`: very high visual resolution but can be visually noisy and heavier.
464
+ - `normalize: true`: improves contrast/detail for muted media.
465
+ - `ditherStrength: 0-0.25`: adds texture but costs more and can shimmer in video.
466
+ - `chromaKey`: useful for green/blue-screen subjects over page backgrounds.
467
+
468
+ ### Expensive Features
469
+
470
+ These are intentionally richer and can reduce FPS on dense canvases:
471
+
472
+ - `renderMode: 'dots'`
473
+ - `hoverStrength > 0`
474
+ - `animationStyle !== 'none'`
475
+ - `charsetFrames`
476
+ - tiny `fontSize` with `fullcolor`
477
+ - very high `maxRenderDimension`
478
+
479
+ For interactive hover demos, use `fontSize >= 8` or smaller canvases.
480
+
481
+ ## Low-Level APIs
482
+
483
+ ### Compact Text Frames
484
+
485
+ Use for dense static images, GIFs, videos, and fullcolor media where you do not need per-cell mutation.
486
+
487
+ ```ts
488
+ import {
489
+ imageToAsciiTextFrame,
490
+ renderTextFrameToCanvas,
491
+ DEFAULT_OPTIONS,
492
+ } from 'asciify-engine';
493
+
494
+ const frame = imageToAsciiTextFrame(img, {
495
+ ...DEFAULT_OPTIONS,
496
+ fontSize: 6,
497
+ colorMode: 'fullcolor',
498
+ }, 1280, 720);
499
+
500
+ renderTextFrameToCanvas(ctx, frame, DEFAULT_OPTIONS, 1280, 720);
501
+ ```
502
+
503
+ Available compact APIs:
504
+
505
+ ```ts
506
+ imageToAsciiTextFrame(source, options, width?, height?) -> AsciiTextFrame
507
+ videoToAsciiTextFrames(video, options, width, height, fps?, maxSec?, onProgress?, startTime?)
508
+ gifToAsciiTextFrames(buffer, options, width, height, onProgress?)
509
+ renderTextFrameToCanvas(ctx, textFrame, options, width, height)
510
+ ```
511
+
512
+ `AsciiTextFrame` contains:
513
+
514
+ ```ts
515
+ type AsciiTextFrame = {
516
+ rows: string[];
517
+ cols: number;
518
+ rowCount: number;
519
+ colors?: Uint8ClampedArray; // present for fullcolor compact frames
520
+ }
521
+ ```
522
+
523
+ ### Legacy Object Frames
524
+
525
+ Use when you need cell objects, hover transforms, dots rendering, or compatibility:
526
+
527
+ ```ts
528
+ imageToAsciiFrame(source, options, width?, height?) -> { frame, cols, rows }
529
+ videoToAsciiFrames(video, options, width, height, fps?, maxSec?, onProgress?, startTime?)
530
+ gifToAsciiFrames(buffer, options, width, height, onProgress?)
531
+ renderFrameToCanvas(ctx, frame, options, width, height, time?, mousePos?)
532
+ ```
533
+
534
+ ### Cache Management
535
+
536
+ Long-lived editors/playgrounds that cycle many charsets or fonts can clear shared lookup caches:
537
+
538
+ ```ts
539
+ import { clearAsciifyCaches } from 'asciify-engine';
540
+
541
+ clearAsciifyCaches();
542
+ ```
543
+
544
+ ## React / Next.js Pattern
545
+
546
+ ```tsx
547
+ 'use client';
548
+
549
+ import { useEffect, useRef } from 'react';
550
+ import { asciifyVideo, CHARSETS } from 'asciify-engine';
551
+
552
+ export function AsciiHero() {
553
+ const wrapperRef = useRef<HTMLDivElement>(null);
554
+ const canvasRef = useRef<HTMLCanvasElement>(null);
555
+
556
+ useEffect(() => {
557
+ const wrapper = wrapperRef.current;
558
+ const canvas = canvasRef.current;
559
+ if (!wrapper || !canvas) return;
560
+
561
+ let cleanup: (() => void) | undefined;
562
+ let alive = true;
563
+
564
+ asciifyVideo('/hero.mp4', canvas, {
565
+ fitTo: wrapper,
566
+ fontSize: 5,
567
+ fps: 60,
568
+ maxRenderDimension: 1280,
569
+ artStyle: 'classic',
570
+ options: {
571
+ charset: CHARSETS.dense,
572
+ colorMode: 'accent',
573
+ accentColor: '#e8d7b7',
574
+ normalize: true,
575
+ },
576
+ }).then(stop => {
577
+ if (alive) cleanup = stop;
578
+ else stop();
579
+ });
580
+
581
+ return () => {
582
+ alive = false;
583
+ cleanup?.();
584
+ };
585
+ }, []);
586
+
587
+ return (
588
+ <div ref={wrapperRef} style={{ position: 'relative', width: '100%', height: '100vh' }}>
589
+ <canvas ref={canvasRef} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%' }} />
590
+ </div>
591
+ );
592
+ }
593
+ ```
594
+
595
+ ## Animated Backgrounds
596
+
597
+ ```ts
598
+ import { asciiBackground } from 'asciify-engine';
599
+
600
+ const stop = asciiBackground('#hero-bg', {
601
+ type: 'aurora',
602
+ colorScheme: 'auto',
603
+ fontSize: 14,
604
+ speed: 0.8,
605
+ density: 0.55,
606
+ accentColor: '#d4ff00',
607
+ });
608
+
609
+ stop();
610
+ ```
611
+
612
+ Available background types:
613
+
614
+ `wave`, `rain`, `stars`, `pulse`, `noise`, `grid`, `aurora`, `silk`, `void`, `morph`, `fire`, `dna`, `terrain`, `circuit`
615
+
616
+ Individual `render*Background` functions are also exported for custom canvas loops.
617
+
618
+ ## Options Reference
619
+
620
+ Common `AsciiOptions`:
621
+
622
+ | Property | Type | Notes |
623
+ |---|---|---|
624
+ | `fontSize` | `number` | Main detail/performance knob. |
625
+ | `charSpacing` | `number` | Cell spacing multiplier. |
626
+ | `brightness` | `number` | `-1` to `1`. |
627
+ | `contrast` | `number` | Positive increases contrast. |
628
+ | `charset` | `string` | Use `CHARSETS`. |
629
+ | `colorMode` | `'grayscale' | 'fullcolor' | 'matrix' | 'accent'` | Fullcolor is fast-path capable in `1.0.91+`. |
630
+ | `accentColor` | `string` | Used for accent/matrix-style rendering. |
631
+ | `invert` | `boolean | 'auto'` | Use `'auto'` for light/dark themes. |
632
+ | `renderMode` | `'ascii' | 'dots'` | Dots is richer/heavier. |
633
+ | `animationStyle` | `AnimationStyle` | Keep `'none'` for max FPS. |
634
+ | `animationSpeed` | `number` | Animation speed multiplier. |
635
+ | `dotSizeRatio` | `number` | Dot size for dots mode. |
636
+ | `ditherStrength` | `number` | Use lightly for video. |
637
+ | `hoverStrength` | `number` | Set `0` for fast media. |
638
+ | `hoverRadius` | `number` | Hover influence radius. |
639
+ | `hoverEffect` | `HoverEffect` | Spotlight/magnify/etc. |
640
+ | `hoverColor` | `string` | Hover tint. |
641
+ | `artStyle` | `ArtStyle` | Preset name. |
642
+ | `customText` | `string` | Repeating custom text. |
643
+ | `chromaKey` | `boolean | string | {r,g,b} | null` | Green/blue/custom keying. |
644
+ | `chromaKeyTolerance` | `number` | Default around `60`; raise for noisy footage. |
645
+ | `normalize` | `boolean` | Stretch source luminance. |
646
+ | `charsetFrames` | `string[]` | Animated charset sequence; heavier. |
647
+ | `charsetFps` | `number` | Charset sequence rate. |
648
+
649
+ ## Charsets And Styles
650
+
651
+ Use:
652
+
653
+ ```ts
654
+ import { CHARSETS, ART_STYLE_PRESETS } from 'asciify-engine';
655
+ ```
656
+
657
+ Common charsets:
658
+
659
+ - `CHARSETS.standard`
660
+ - `CHARSETS.dense`
661
+ - `CHARSETS.blocks`
662
+ - `CHARSETS.braille`
663
+ - `CHARSETS.lines`
664
+ - `CHARSETS.dots`
665
+ - `CHARSETS.letters`
666
+ - `CHARSETS.katakana`
667
+ - `CHARSETS.circles`
668
+ - `CHARSETS.geometric`
669
+ - `CHARSETS.shadows`
670
+ - `CHARSETS.starfield`
671
+
672
+ Common art styles:
673
+
674
+ - `classic`: standard ASCII.
675
+ - `art`: dense fullcolor detail.
676
+ - `particles`: dots/fullcolor.
677
+ - `letters`: alphabet characters.
678
+ - `terminal`: matrix green.
679
+ - `braille`: high detail.
680
+ - `box`, `lines`, `katakana`, `emoji`, `circles`, `shadows`, `geometric`, `waves`, `shards`, `smoke`.
681
+
682
+ ## Hover And Animation
683
+
684
+ Hover effects:
685
+
686
+ `spotlight`, `magnify`, `repel`, `glow`, `colorShift`, `attract`, `shatter`, `trail`, `glitchText`
687
+
688
+ Hover presets:
689
+
690
+ `none`, `subtle`, `flashlight`, `magnifier`, `forceField`, `neon`, `fire`, `ice`, `gravity`, `shatter`, `ghost`, `glitchReveal`
691
+
692
+ Animation styles:
693
+
694
+ `none`, `wave`, `pulse`, `rain`, `breathe`, `sparkle`, `glitch`, `spiral`, `typewriter`, `scatter`, `waveField`, `ripple`, `melt`, `orbit`, `cellular`
695
+
696
+ Best practice:
697
+
698
+ - For video backgrounds and scroll heroes, use `animationStyle: 'none'` and `hoverStrength: 0`.
699
+ - For interactive hover demos, keep the canvas smaller or use `fontSize >= 8`.
700
+ - Avoid combining tiny fonts, fullcolor, hover, and animation unless the visual really needs it.
701
+
702
+ ## Recording And Export
703
+
704
+ ```ts
705
+ import { createRecorder, recordAndDownload } from 'asciify-engine';
706
+
707
+ await recordAndDownload(canvas, { duration: 3000, filename: 'ascii-art' });
708
+
709
+ const recorder = createRecorder(canvas, { fps: 30 });
710
+ recorder.start();
711
+ const blob = await recorder.stop();
712
+ ```
713
+
714
+ ## Type Imports
715
+
716
+ ```ts
717
+ import type {
718
+ AsciiOptions,
719
+ AsciiCell,
720
+ AsciiFrame,
721
+ AsciiTextFrame,
722
+ AsciifySimpleOptions,
723
+ AsciifyVideoOptions,
724
+ VideoScrollScrubOptions,
725
+ ColorMode,
726
+ AnimationStyle,
727
+ ArtStyle,
728
+ HoverEffect,
729
+ } from 'asciify-engine';
730
+ ```