asciify-engine 1.0.41 → 1.0.43
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/README.md +31 -17
- package/dist/index.cjs +62 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -1
- package/dist/index.d.ts +32 -1
- package/dist/index.js +62 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -232,6 +232,16 @@ interface AsciifySimpleOptions {
|
|
|
232
232
|
/** Extra options to merge on top of the preset */
|
|
233
233
|
options?: Partial<AsciiOptions>;
|
|
234
234
|
}
|
|
235
|
+
interface AsciifyLiveVideoOptions extends AsciifySimpleOptions {
|
|
236
|
+
/**
|
|
237
|
+
* Called once when the video metadata is ready and playback has started.
|
|
238
|
+
* Receive the backing video element — useful for sizing the canvas or
|
|
239
|
+
* triggering a ready state in your UI.
|
|
240
|
+
*/
|
|
241
|
+
onReady?: (video: HTMLVideoElement) => void;
|
|
242
|
+
/** Called after every rendered frame. Useful for frame counters or timers. */
|
|
243
|
+
onFrame?: () => void;
|
|
244
|
+
}
|
|
235
245
|
/**
|
|
236
246
|
* Convert an image/video/canvas element to ASCII art and render it onto a canvas.
|
|
237
247
|
*
|
|
@@ -258,6 +268,27 @@ declare function asciifyGif(source: string | ArrayBuffer, canvas: HTMLCanvasElem
|
|
|
258
268
|
* // later: stop();
|
|
259
269
|
*/
|
|
260
270
|
declare function asciifyVideo(source: HTMLVideoElement | string, canvas: HTMLCanvasElement, { fontSize, artStyle, options }?: AsciifySimpleOptions): Promise<() => void>;
|
|
271
|
+
/**
|
|
272
|
+
* Stream a video element (or URL) as live ASCII art onto a canvas — frame by
|
|
273
|
+
* frame in real time, with no pre-extraction delay.
|
|
274
|
+
*
|
|
275
|
+
* Unlike `asciifyVideo` (which pre-processes the full clip), this renders each
|
|
276
|
+
* video frame live as the video plays, making it suitable for long videos,
|
|
277
|
+
* looping clips, and any case where you want instant playback.
|
|
278
|
+
*
|
|
279
|
+
* ⚠️ Important: never set the backing `<video>` element to `display: none` —
|
|
280
|
+
* browsers skip GPU frame decoding for hidden elements, resulting in a blank
|
|
281
|
+
* canvas. `asciifyLiveVideo` handles this automatically when given a URL.
|
|
282
|
+
* If you supply your own video element, make sure it is visible or uses
|
|
283
|
+
* `opacity: 0; position: fixed` instead.
|
|
284
|
+
*
|
|
285
|
+
* @returns A `stop()` function that cancels the animation loop and cleans up.
|
|
286
|
+
*
|
|
287
|
+
* @example
|
|
288
|
+
* const stop = await asciifyLiveVideo('/clip.mp4', canvas);
|
|
289
|
+
* // later: stop();
|
|
290
|
+
*/
|
|
291
|
+
declare function asciifyLiveVideo(source: HTMLVideoElement | string, canvas: HTMLCanvasElement, { fontSize, artStyle, options, onReady, onFrame }?: AsciifyLiveVideoOptions): Promise<() => void>;
|
|
261
292
|
|
|
262
293
|
interface WaveBackgroundOptions {
|
|
263
294
|
/** Font size in CSS pixels (default: 13) */
|
|
@@ -918,4 +949,4 @@ interface WebcamOptions {
|
|
|
918
949
|
*/
|
|
919
950
|
declare function asciifyWebcam(canvas: HTMLCanvasElement, { fontSize, style, options, liveOptions, mirror, constraints, dpr: dprOverride, }?: WebcamOptions): Promise<() => void>;
|
|
920
951
|
|
|
921
|
-
export { ART_STYLE_PRESETS, type AnimationStyle, type ArtStyle, type AsciiBackgroundOptions, type AsciiCell, type AsciiFrame, type AsciiOptions, type AsciiResult, type AsciifySimpleOptions, type AuroraBackgroundOptions, BACKGROUND_TYPES, type BackgroundType, CHARSETS, type CharsetKey, type CircuitBackgroundOptions, type ColorMode, DEFAULT_OPTIONS, type DnaBackgroundOptions, type FireBackgroundOptions, type GridBackgroundOptions, HOVER_PRESETS, type HoverEffect, type HoverPreset, type MorphBackgroundOptions, type MountWaveOptions, type NoiseBackgroundOptions, PALETTE_THEMES, type PaletteTheme, type PulseBackgroundOptions, type RainBackgroundOptions, type RenderMode, type SilkBackgroundOptions, type SnapshotOptions, type SourceType, type StarsBackgroundOptions, type TerrainBackgroundOptions, type TextBackgroundOptions, type VoidBackgroundOptions, type WaveBackgroundOptions, type WebcamOptions, asciiBackground, asciiText, asciiTextAnsi, asciify, asciifyGif, asciifyVideo, asciifyWebcam, buildTextFrame, captureSnapshot, gifToAsciiFrames, imageToAsciiFrame, mountWaveBackground, renderAuroraBackground, renderCircuitBackground, renderDnaBackground, renderFireBackground, renderFrameToCanvas, renderGridBackground, renderMorphBackground, renderNoiseBackground, renderPulseBackground, renderRainBackground, renderSilkBackground, renderStarsBackground, renderTerrainBackground, renderTextBackground, renderVoidBackground, renderWaveBackground, snapshotAndDownload, videoToAsciiFrames };
|
|
952
|
+
export { ART_STYLE_PRESETS, type AnimationStyle, type ArtStyle, type AsciiBackgroundOptions, type AsciiCell, type AsciiFrame, type AsciiOptions, type AsciiResult, type AsciifyLiveVideoOptions, type AsciifySimpleOptions, type AuroraBackgroundOptions, BACKGROUND_TYPES, type BackgroundType, CHARSETS, type CharsetKey, type CircuitBackgroundOptions, type ColorMode, DEFAULT_OPTIONS, type DnaBackgroundOptions, type FireBackgroundOptions, type GridBackgroundOptions, HOVER_PRESETS, type HoverEffect, type HoverPreset, type MorphBackgroundOptions, type MountWaveOptions, type NoiseBackgroundOptions, PALETTE_THEMES, type PaletteTheme, type PulseBackgroundOptions, type RainBackgroundOptions, type RenderMode, type SilkBackgroundOptions, type SnapshotOptions, type SourceType, type StarsBackgroundOptions, type TerrainBackgroundOptions, type TextBackgroundOptions, type VoidBackgroundOptions, type WaveBackgroundOptions, type WebcamOptions, asciiBackground, asciiText, asciiTextAnsi, asciify, asciifyGif, asciifyLiveVideo, asciifyVideo, asciifyWebcam, buildTextFrame, captureSnapshot, gifToAsciiFrames, imageToAsciiFrame, mountWaveBackground, renderAuroraBackground, renderCircuitBackground, renderDnaBackground, renderFireBackground, renderFrameToCanvas, renderGridBackground, renderMorphBackground, renderNoiseBackground, renderPulseBackground, renderRainBackground, renderSilkBackground, renderStarsBackground, renderTerrainBackground, renderTextBackground, renderVoidBackground, renderWaveBackground, snapshotAndDownload, videoToAsciiFrames };
|
package/dist/index.d.ts
CHANGED
|
@@ -232,6 +232,16 @@ interface AsciifySimpleOptions {
|
|
|
232
232
|
/** Extra options to merge on top of the preset */
|
|
233
233
|
options?: Partial<AsciiOptions>;
|
|
234
234
|
}
|
|
235
|
+
interface AsciifyLiveVideoOptions extends AsciifySimpleOptions {
|
|
236
|
+
/**
|
|
237
|
+
* Called once when the video metadata is ready and playback has started.
|
|
238
|
+
* Receive the backing video element — useful for sizing the canvas or
|
|
239
|
+
* triggering a ready state in your UI.
|
|
240
|
+
*/
|
|
241
|
+
onReady?: (video: HTMLVideoElement) => void;
|
|
242
|
+
/** Called after every rendered frame. Useful for frame counters or timers. */
|
|
243
|
+
onFrame?: () => void;
|
|
244
|
+
}
|
|
235
245
|
/**
|
|
236
246
|
* Convert an image/video/canvas element to ASCII art and render it onto a canvas.
|
|
237
247
|
*
|
|
@@ -258,6 +268,27 @@ declare function asciifyGif(source: string | ArrayBuffer, canvas: HTMLCanvasElem
|
|
|
258
268
|
* // later: stop();
|
|
259
269
|
*/
|
|
260
270
|
declare function asciifyVideo(source: HTMLVideoElement | string, canvas: HTMLCanvasElement, { fontSize, artStyle, options }?: AsciifySimpleOptions): Promise<() => void>;
|
|
271
|
+
/**
|
|
272
|
+
* Stream a video element (or URL) as live ASCII art onto a canvas — frame by
|
|
273
|
+
* frame in real time, with no pre-extraction delay.
|
|
274
|
+
*
|
|
275
|
+
* Unlike `asciifyVideo` (which pre-processes the full clip), this renders each
|
|
276
|
+
* video frame live as the video plays, making it suitable for long videos,
|
|
277
|
+
* looping clips, and any case where you want instant playback.
|
|
278
|
+
*
|
|
279
|
+
* ⚠️ Important: never set the backing `<video>` element to `display: none` —
|
|
280
|
+
* browsers skip GPU frame decoding for hidden elements, resulting in a blank
|
|
281
|
+
* canvas. `asciifyLiveVideo` handles this automatically when given a URL.
|
|
282
|
+
* If you supply your own video element, make sure it is visible or uses
|
|
283
|
+
* `opacity: 0; position: fixed` instead.
|
|
284
|
+
*
|
|
285
|
+
* @returns A `stop()` function that cancels the animation loop and cleans up.
|
|
286
|
+
*
|
|
287
|
+
* @example
|
|
288
|
+
* const stop = await asciifyLiveVideo('/clip.mp4', canvas);
|
|
289
|
+
* // later: stop();
|
|
290
|
+
*/
|
|
291
|
+
declare function asciifyLiveVideo(source: HTMLVideoElement | string, canvas: HTMLCanvasElement, { fontSize, artStyle, options, onReady, onFrame }?: AsciifyLiveVideoOptions): Promise<() => void>;
|
|
261
292
|
|
|
262
293
|
interface WaveBackgroundOptions {
|
|
263
294
|
/** Font size in CSS pixels (default: 13) */
|
|
@@ -918,4 +949,4 @@ interface WebcamOptions {
|
|
|
918
949
|
*/
|
|
919
950
|
declare function asciifyWebcam(canvas: HTMLCanvasElement, { fontSize, style, options, liveOptions, mirror, constraints, dpr: dprOverride, }?: WebcamOptions): Promise<() => void>;
|
|
920
951
|
|
|
921
|
-
export { ART_STYLE_PRESETS, type AnimationStyle, type ArtStyle, type AsciiBackgroundOptions, type AsciiCell, type AsciiFrame, type AsciiOptions, type AsciiResult, type AsciifySimpleOptions, type AuroraBackgroundOptions, BACKGROUND_TYPES, type BackgroundType, CHARSETS, type CharsetKey, type CircuitBackgroundOptions, type ColorMode, DEFAULT_OPTIONS, type DnaBackgroundOptions, type FireBackgroundOptions, type GridBackgroundOptions, HOVER_PRESETS, type HoverEffect, type HoverPreset, type MorphBackgroundOptions, type MountWaveOptions, type NoiseBackgroundOptions, PALETTE_THEMES, type PaletteTheme, type PulseBackgroundOptions, type RainBackgroundOptions, type RenderMode, type SilkBackgroundOptions, type SnapshotOptions, type SourceType, type StarsBackgroundOptions, type TerrainBackgroundOptions, type TextBackgroundOptions, type VoidBackgroundOptions, type WaveBackgroundOptions, type WebcamOptions, asciiBackground, asciiText, asciiTextAnsi, asciify, asciifyGif, asciifyVideo, asciifyWebcam, buildTextFrame, captureSnapshot, gifToAsciiFrames, imageToAsciiFrame, mountWaveBackground, renderAuroraBackground, renderCircuitBackground, renderDnaBackground, renderFireBackground, renderFrameToCanvas, renderGridBackground, renderMorphBackground, renderNoiseBackground, renderPulseBackground, renderRainBackground, renderSilkBackground, renderStarsBackground, renderTerrainBackground, renderTextBackground, renderVoidBackground, renderWaveBackground, snapshotAndDownload, videoToAsciiFrames };
|
|
952
|
+
export { ART_STYLE_PRESETS, type AnimationStyle, type ArtStyle, type AsciiBackgroundOptions, type AsciiCell, type AsciiFrame, type AsciiOptions, type AsciiResult, type AsciifyLiveVideoOptions, type AsciifySimpleOptions, type AuroraBackgroundOptions, BACKGROUND_TYPES, type BackgroundType, CHARSETS, type CharsetKey, type CircuitBackgroundOptions, type ColorMode, DEFAULT_OPTIONS, type DnaBackgroundOptions, type FireBackgroundOptions, type GridBackgroundOptions, HOVER_PRESETS, type HoverEffect, type HoverPreset, type MorphBackgroundOptions, type MountWaveOptions, type NoiseBackgroundOptions, PALETTE_THEMES, type PaletteTheme, type PulseBackgroundOptions, type RainBackgroundOptions, type RenderMode, type SilkBackgroundOptions, type SnapshotOptions, type SourceType, type StarsBackgroundOptions, type TerrainBackgroundOptions, type TextBackgroundOptions, type VoidBackgroundOptions, type WaveBackgroundOptions, type WebcamOptions, asciiBackground, asciiText, asciiTextAnsi, asciify, asciifyGif, asciifyLiveVideo, asciifyVideo, asciifyWebcam, buildTextFrame, captureSnapshot, gifToAsciiFrames, imageToAsciiFrame, mountWaveBackground, renderAuroraBackground, renderCircuitBackground, renderDnaBackground, renderFireBackground, renderFrameToCanvas, renderGridBackground, renderMorphBackground, renderNoiseBackground, renderPulseBackground, renderRainBackground, renderSilkBackground, renderStarsBackground, renderTerrainBackground, renderTextBackground, renderVoidBackground, renderWaveBackground, snapshotAndDownload, videoToAsciiFrames };
|
package/dist/index.js
CHANGED
|
@@ -1075,6 +1075,67 @@ async function asciifyVideo(source, canvas, { fontSize = 10, artStyle = "classic
|
|
|
1075
1075
|
cancelAnimationFrame(animId);
|
|
1076
1076
|
};
|
|
1077
1077
|
}
|
|
1078
|
+
async function asciifyLiveVideo(source, canvas, { fontSize = 10, artStyle = "classic", options = {}, onReady, onFrame } = {}) {
|
|
1079
|
+
let video;
|
|
1080
|
+
let ownedVideo = false;
|
|
1081
|
+
if (typeof source === "string") {
|
|
1082
|
+
video = document.createElement("video");
|
|
1083
|
+
video.src = source;
|
|
1084
|
+
video.muted = true;
|
|
1085
|
+
video.loop = true;
|
|
1086
|
+
video.playsInline = true;
|
|
1087
|
+
video.setAttribute("playsinline", "");
|
|
1088
|
+
Object.assign(video.style, {
|
|
1089
|
+
position: "fixed",
|
|
1090
|
+
top: "0",
|
|
1091
|
+
left: "0",
|
|
1092
|
+
width: "1px",
|
|
1093
|
+
height: "1px",
|
|
1094
|
+
opacity: "0",
|
|
1095
|
+
pointerEvents: "none",
|
|
1096
|
+
zIndex: "-1"
|
|
1097
|
+
});
|
|
1098
|
+
document.body.appendChild(video);
|
|
1099
|
+
ownedVideo = true;
|
|
1100
|
+
await new Promise((resolve, reject) => {
|
|
1101
|
+
video.onloadedmetadata = () => resolve();
|
|
1102
|
+
video.onerror = () => reject(new Error(`asciifyLiveVideo: failed to load "${source}"`));
|
|
1103
|
+
});
|
|
1104
|
+
await video.play().catch(() => {
|
|
1105
|
+
});
|
|
1106
|
+
onReady?.(video);
|
|
1107
|
+
} else {
|
|
1108
|
+
video = source;
|
|
1109
|
+
if (video.paused) await video.play().catch(() => {
|
|
1110
|
+
});
|
|
1111
|
+
onReady?.(video);
|
|
1112
|
+
}
|
|
1113
|
+
const merged = { ...DEFAULT_OPTIONS, ...ART_STYLE_PRESETS[artStyle], ...options, fontSize };
|
|
1114
|
+
const ctx = canvas.getContext("2d");
|
|
1115
|
+
if (!ctx) throw new Error("asciifyLiveVideo: could not get 2d context from canvas.");
|
|
1116
|
+
let cancelled = false;
|
|
1117
|
+
let animId;
|
|
1118
|
+
const tick = () => {
|
|
1119
|
+
if (cancelled) return;
|
|
1120
|
+
animId = requestAnimationFrame(tick);
|
|
1121
|
+
if (video.readyState < 2 || canvas.width === 0 || canvas.height === 0) return;
|
|
1122
|
+
const { frame } = imageToAsciiFrame(video, merged, canvas.width, canvas.height);
|
|
1123
|
+
if (frame.length > 0) {
|
|
1124
|
+
renderFrameToCanvas(ctx, frame, merged, canvas.width, canvas.height, 0, null);
|
|
1125
|
+
onFrame?.();
|
|
1126
|
+
}
|
|
1127
|
+
};
|
|
1128
|
+
animId = requestAnimationFrame(tick);
|
|
1129
|
+
return () => {
|
|
1130
|
+
cancelled = true;
|
|
1131
|
+
cancelAnimationFrame(animId);
|
|
1132
|
+
if (ownedVideo) {
|
|
1133
|
+
video.pause();
|
|
1134
|
+
video.src = "";
|
|
1135
|
+
document.body.removeChild(video);
|
|
1136
|
+
}
|
|
1137
|
+
};
|
|
1138
|
+
}
|
|
1078
1139
|
|
|
1079
1140
|
// src/backgrounds/rain.ts
|
|
1080
1141
|
function renderRainBackground(ctx, width, height, time, options = {}) {
|
|
@@ -2455,6 +2516,6 @@ async function asciifyWebcam(canvas, {
|
|
|
2455
2516
|
};
|
|
2456
2517
|
}
|
|
2457
2518
|
|
|
2458
|
-
export { ART_STYLE_PRESETS, BACKGROUND_TYPES, CHARSETS, DEFAULT_OPTIONS, HOVER_PRESETS, PALETTE_THEMES, asciiBackground, asciiText, asciiTextAnsi, asciify, asciifyGif, asciifyVideo, asciifyWebcam, buildTextFrame, captureSnapshot, gifToAsciiFrames, imageToAsciiFrame, mountWaveBackground, renderAuroraBackground, renderCircuitBackground, renderDnaBackground, renderFireBackground, renderFrameToCanvas, renderGridBackground, renderMorphBackground, renderNoiseBackground, renderPulseBackground, renderRainBackground, renderSilkBackground, renderStarsBackground, renderTerrainBackground, renderTextBackground, renderVoidBackground, renderWaveBackground, snapshotAndDownload, videoToAsciiFrames };
|
|
2519
|
+
export { ART_STYLE_PRESETS, BACKGROUND_TYPES, CHARSETS, DEFAULT_OPTIONS, HOVER_PRESETS, PALETTE_THEMES, asciiBackground, asciiText, asciiTextAnsi, asciify, asciifyGif, asciifyLiveVideo, asciifyVideo, asciifyWebcam, buildTextFrame, captureSnapshot, gifToAsciiFrames, imageToAsciiFrame, mountWaveBackground, renderAuroraBackground, renderCircuitBackground, renderDnaBackground, renderFireBackground, renderFrameToCanvas, renderGridBackground, renderMorphBackground, renderNoiseBackground, renderPulseBackground, renderRainBackground, renderSilkBackground, renderStarsBackground, renderTerrainBackground, renderTextBackground, renderVoidBackground, renderWaveBackground, snapshotAndDownload, videoToAsciiFrames };
|
|
2459
2520
|
//# sourceMappingURL=index.js.map
|
|
2460
2521
|
//# sourceMappingURL=index.js.map
|