@shotstack/shotstack-canvas 1.0.3 → 1.0.5

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.
@@ -185,13 +185,13 @@ interface VideoGenerationOptions {
185
185
  duration: number;
186
186
  outputPath: string;
187
187
  pixelRatio?: number;
188
- /** Optional quality controls (sane defaults provided) */
189
188
  crf?: number;
190
189
  preset?: "ultrafast" | "superfast" | "veryfast" | "faster" | "fast" | "medium" | "slow" | "slower" | "veryslow";
191
190
  tune?: "film" | "animation" | "grain" | "stillimage" | "psnr" | "ssim" | "fastdecode" | "zerolatency";
192
191
  profile?: "baseline" | "main" | "high";
193
192
  level?: string;
194
193
  pixFmt?: string;
194
+ ffmpegPath?: string;
195
195
  }
196
196
 
197
197
  declare function createTextEngine(opts?: {
@@ -185,13 +185,13 @@ interface VideoGenerationOptions {
185
185
  duration: number;
186
186
  outputPath: string;
187
187
  pixelRatio?: number;
188
- /** Optional quality controls (sane defaults provided) */
189
188
  crf?: number;
190
189
  preset?: "ultrafast" | "superfast" | "veryfast" | "faster" | "fast" | "medium" | "slow" | "slower" | "veryslow";
191
190
  tune?: "film" | "animation" | "grain" | "stillimage" | "psnr" | "ssim" | "fastdecode" | "zerolatency";
192
191
  profile?: "baseline" | "main" | "high";
193
192
  level?: string;
194
193
  pixFmt?: string;
194
+ ffmpegPath?: string;
195
195
  }
196
196
 
197
197
  declare function createTextEngine(opts?: {
@@ -1249,22 +1249,34 @@ async function loadFileOrHttpToArrayBuffer(pathOrUrl) {
1249
1249
 
1250
1250
  // src/core/video-generator.ts
1251
1251
  import { spawn } from "child_process";
1252
+ import fs from "fs";
1252
1253
  var VideoGenerator = class {
1253
1254
  ffmpegPath = null;
1254
- async init() {
1255
+ trySetPath(p) {
1256
+ if (p && fs.existsSync(p)) {
1257
+ this.ffmpegPath = p;
1258
+ return true;
1259
+ }
1260
+ return false;
1261
+ }
1262
+ async init(opts) {
1255
1263
  if (typeof window !== "undefined") {
1256
1264
  throw new Error("VideoGenerator is only available in Node.js environment");
1257
1265
  }
1266
+ if (this.trySetPath(opts?.ffmpegPath)) return;
1267
+ if (this.trySetPath(process.env.FFMPEG_PATH)) return;
1268
+ if (this.trySetPath(process.env.FFMPEG_BIN)) return;
1269
+ if (this.trySetPath("/opt/bin/ffmpeg")) return;
1258
1270
  try {
1259
1271
  const ffmpegStatic = await import("ffmpeg-static");
1260
- this.ffmpegPath = ffmpegStatic.default;
1261
- } catch (error) {
1262
- console.error("Failed to load ffmpeg-static:", error);
1263
- throw new Error("FFmpeg not available. Please install ffmpeg-static");
1272
+ const p = ffmpegStatic.default;
1273
+ if (this.trySetPath(p)) return;
1274
+ } catch {
1264
1275
  }
1276
+ throw new Error("FFmpeg not available. Please install ffmpeg-static or provide FFMPEG_PATH.");
1265
1277
  }
1266
1278
  async generateVideo(frameGenerator, options) {
1267
- if (!this.ffmpegPath) await this.init();
1279
+ if (!this.ffmpegPath) await this.init({ ffmpegPath: options.ffmpegPath });
1268
1280
  const {
1269
1281
  width,
1270
1282
  height,
@@ -1287,17 +1299,14 @@ var VideoGenerator = class {
1287
1299
  return new Promise(async (resolve, reject) => {
1288
1300
  const args = [
1289
1301
  "-y",
1290
- // Input as image pipe
1291
1302
  "-f",
1292
1303
  "image2pipe",
1293
1304
  "-vcodec",
1294
1305
  "png",
1295
1306
  "-framerate",
1296
1307
  String(fps),
1297
- // input frame rate
1298
1308
  "-i",
1299
1309
  "-",
1300
- // Encoding params
1301
1310
  "-c:v",
1302
1311
  "libx264",
1303
1312
  "-preset",
@@ -1312,7 +1321,6 @@ var VideoGenerator = class {
1312
1321
  level,
1313
1322
  "-pix_fmt",
1314
1323
  pixFmt,
1315
- // Set output framerate explicitly
1316
1324
  "-r",
1317
1325
  String(fps),
1318
1326
  "-movflags",
@@ -1356,9 +1364,7 @@ var VideoGenerator = class {
1356
1364
  await painter.render(ops);
1357
1365
  const png = await painter.toPNG();
1358
1366
  const ok = ffmpeg.stdin.write(png);
1359
- if (!ok) {
1360
- await new Promise((r) => ffmpeg.stdin.once("drain", r));
1361
- }
1367
+ if (!ok) await new Promise((r) => ffmpeg.stdin.once("drain", r));
1362
1368
  if (frame % Math.max(1, Math.floor(fps / 2)) === 0) {
1363
1369
  const pct = Math.round((frame + 1) / totalFrames * 100);
1364
1370
  console.log(`\u{1F39E}\uFE0F Rendering frames: ${pct}%`);