asciify-engine 1.0.42 → 1.0.44

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 CHANGED
@@ -87,14 +87,33 @@ setInterval(() => {
87
87
  import { asciifyLiveVideo } from 'asciify-engine';
88
88
 
89
89
  const canvas = document.getElementById('ascii') as HTMLCanvasElement;
90
- const stop = await asciifyLiveVideo('/clip.mp4', canvas);
91
90
 
92
- // With options:
91
+ // Sizes canvas to the video's native dimensions automatically:
92
+ const stop = await asciifyLiveVideo('/clip.mp4', canvas, { autoSize: true });
93
+
94
+ // With art style:
93
95
  const stop = await asciifyLiveVideo('/clip.mp4', canvas, {
96
+ autoSize: true,
94
97
  fontSize: 6,
95
98
  artStyle: 'matrix',
96
99
  });
97
100
 
101
+ // With lifecycle hooks — useful for sizing the canvas, loading indicators, timers:
102
+ const stop = await asciifyLiveVideo('/clip.mp4', canvas, {
103
+ fontSize: 6,
104
+ onReady: (video) => {
105
+ // Called once when metadata is loaded and playback has started.
106
+ // Resize the canvas to match the video here, update your UI, etc.
107
+ canvas.width = video.videoWidth;
108
+ canvas.height = video.videoHeight;
109
+ setReady(true);
110
+ },
111
+ onFrame: () => {
112
+ // Called after every rendered frame.
113
+ setElapsed(Math.floor(performance.now() / 1000));
114
+ },
115
+ });
116
+
98
117
  // Clean up:
99
118
  stop();
100
119
  ```
package/dist/index.cjs CHANGED
@@ -1077,7 +1077,7 @@ async function asciifyVideo(source, canvas, { fontSize = 10, artStyle = "classic
1077
1077
  cancelAnimationFrame(animId);
1078
1078
  };
1079
1079
  }
1080
- async function asciifyLiveVideo(source, canvas, { fontSize = 10, artStyle = "classic", options = {} } = {}) {
1080
+ async function asciifyLiveVideo(source, canvas, { fontSize = 10, artStyle = "classic", options = {}, autoSize = false, onReady, onFrame } = {}) {
1081
1081
  let video;
1082
1082
  let ownedVideo = false;
1083
1083
  if (typeof source === "string") {
@@ -1103,13 +1103,18 @@ async function asciifyLiveVideo(source, canvas, { fontSize = 10, artStyle = "cla
1103
1103
  video.onloadedmetadata = () => resolve();
1104
1104
  video.onerror = () => reject(new Error(`asciifyLiveVideo: failed to load "${source}"`));
1105
1105
  });
1106
- video.play().catch(() => {
1106
+ await video.play().catch(() => {
1107
1107
  });
1108
1108
  } else {
1109
1109
  video = source;
1110
- if (video.paused) video.play().catch(() => {
1110
+ if (video.paused) await video.play().catch(() => {
1111
1111
  });
1112
1112
  }
1113
+ if (autoSize) {
1114
+ canvas.width = video.videoWidth;
1115
+ canvas.height = video.videoHeight;
1116
+ }
1117
+ onReady?.(video);
1113
1118
  const merged = { ...DEFAULT_OPTIONS, ...ART_STYLE_PRESETS[artStyle], ...options, fontSize };
1114
1119
  const ctx = canvas.getContext("2d");
1115
1120
  if (!ctx) throw new Error("asciifyLiveVideo: could not get 2d context from canvas.");
@@ -1120,7 +1125,10 @@ async function asciifyLiveVideo(source, canvas, { fontSize = 10, artStyle = "cla
1120
1125
  animId = requestAnimationFrame(tick);
1121
1126
  if (video.readyState < 2 || canvas.width === 0 || canvas.height === 0) return;
1122
1127
  const { frame } = imageToAsciiFrame(video, merged, canvas.width, canvas.height);
1123
- if (frame.length > 0) renderFrameToCanvas(ctx, frame, merged, canvas.width, canvas.height, 0, null);
1128
+ if (frame.length > 0) {
1129
+ renderFrameToCanvas(ctx, frame, merged, canvas.width, canvas.height, 0, null);
1130
+ onFrame?.();
1131
+ }
1124
1132
  };
1125
1133
  animId = requestAnimationFrame(tick);
1126
1134
  return () => {