@shotstack/shotstack-canvas 1.1.7 → 1.1.8
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/dist/entry.node.cjs +76 -34
- package/dist/entry.node.cjs.map +1 -1
- package/dist/entry.node.d.cts +1 -0
- package/dist/entry.node.d.ts +1 -0
- package/dist/entry.node.js +76 -34
- package/dist/entry.node.js.map +1 -1
- package/package.json +1 -1
package/dist/entry.node.cjs
CHANGED
|
@@ -1268,6 +1268,7 @@ async function createNodePainter(opts) {
|
|
|
1268
1268
|
const hasBackground = !!(op.bg && op.bg.color);
|
|
1269
1269
|
needsAlphaExtraction = !hasBackground;
|
|
1270
1270
|
if (op.bg && op.bg.color) {
|
|
1271
|
+
ctx.clearRect(0, 0, op.width, op.height);
|
|
1271
1272
|
const { color, opacity, radius } = op.bg;
|
|
1272
1273
|
const c = parseHex6(color, opacity);
|
|
1273
1274
|
ctx.fillStyle = `rgba(${c.r},${c.g},${c.b},${c.a})`;
|
|
@@ -1281,10 +1282,15 @@ async function createNodePainter(opts) {
|
|
|
1281
1282
|
ctx.fillRect(0, 0, op.width, op.height);
|
|
1282
1283
|
}
|
|
1283
1284
|
} else {
|
|
1285
|
+
ctx.clearRect(0, 0, op.width, op.height);
|
|
1286
|
+
ctx.save();
|
|
1284
1287
|
ctx.fillStyle = "rgb(255, 255, 255)";
|
|
1285
1288
|
ctx.fillRect(0, 0, op.width, op.height);
|
|
1289
|
+
ctx.restore();
|
|
1290
|
+
offscreenCtx.save();
|
|
1286
1291
|
offscreenCtx.fillStyle = "rgb(0, 0, 0)";
|
|
1287
1292
|
offscreenCtx.fillRect(0, 0, op.width, op.height);
|
|
1293
|
+
offscreenCtx.restore();
|
|
1288
1294
|
}
|
|
1289
1295
|
continue;
|
|
1290
1296
|
}
|
|
@@ -1670,44 +1676,72 @@ var VideoGenerator = class {
|
|
|
1670
1676
|
tune = "animation",
|
|
1671
1677
|
profile = "high",
|
|
1672
1678
|
level = "4.2",
|
|
1673
|
-
pixFmt = "yuv420p"
|
|
1679
|
+
pixFmt = "yuv420p",
|
|
1680
|
+
hasAlpha = false
|
|
1674
1681
|
} = options;
|
|
1675
1682
|
const totalFrames = Math.max(2, Math.round(duration * fps) + 1);
|
|
1683
|
+
const finalOutputPath = hasAlpha ? outputPath.replace(/\.mp4$/, ".mov") : outputPath;
|
|
1676
1684
|
console.log(
|
|
1677
|
-
`\u{1F3AC} Generating video: ${width}x${height} @ ${fps}fps, ${duration}s (${totalFrames} frames)
|
|
1678
|
-
CRF=${crf}, preset=${preset}, tune=${tune}, profile=${profile}, level=${level}, pix_fmt=${pixFmt}`
|
|
1685
|
+
`\u{1F3AC} Generating video: ${width}x${height} @ ${fps}fps, ${duration}s (${totalFrames} frames)` + (hasAlpha ? " (MOV with alpha)" : "")
|
|
1679
1686
|
);
|
|
1680
1687
|
return new Promise(async (resolve, reject) => {
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1688
|
+
let args;
|
|
1689
|
+
if (hasAlpha) {
|
|
1690
|
+
args = [
|
|
1691
|
+
"-y",
|
|
1692
|
+
"-f",
|
|
1693
|
+
"image2pipe",
|
|
1694
|
+
"-vcodec",
|
|
1695
|
+
"png",
|
|
1696
|
+
"-framerate",
|
|
1697
|
+
String(fps),
|
|
1698
|
+
"-i",
|
|
1699
|
+
"-",
|
|
1700
|
+
"-c:v",
|
|
1701
|
+
"prores_ks",
|
|
1702
|
+
"-profile:v",
|
|
1703
|
+
"4444",
|
|
1704
|
+
"-pix_fmt",
|
|
1705
|
+
"yuva444p10le",
|
|
1706
|
+
"-vendor",
|
|
1707
|
+
"apl0",
|
|
1708
|
+
"-r",
|
|
1709
|
+
String(fps),
|
|
1710
|
+
finalOutputPath
|
|
1711
|
+
];
|
|
1712
|
+
console.log(` Output: ${finalOutputPath} (ProRes 4444 with alpha)`);
|
|
1713
|
+
} else {
|
|
1714
|
+
args = [
|
|
1715
|
+
"-y",
|
|
1716
|
+
"-f",
|
|
1717
|
+
"image2pipe",
|
|
1718
|
+
"-vcodec",
|
|
1719
|
+
"png",
|
|
1720
|
+
"-framerate",
|
|
1721
|
+
String(fps),
|
|
1722
|
+
"-i",
|
|
1723
|
+
"-",
|
|
1724
|
+
"-c:v",
|
|
1725
|
+
"libx264",
|
|
1726
|
+
"-preset",
|
|
1727
|
+
preset,
|
|
1728
|
+
"-crf",
|
|
1729
|
+
String(crf),
|
|
1730
|
+
"-tune",
|
|
1731
|
+
tune,
|
|
1732
|
+
"-profile:v",
|
|
1733
|
+
profile,
|
|
1734
|
+
"-level",
|
|
1735
|
+
level,
|
|
1736
|
+
"-pix_fmt",
|
|
1737
|
+
pixFmt,
|
|
1738
|
+
"-r",
|
|
1739
|
+
String(fps),
|
|
1740
|
+
"-movflags",
|
|
1741
|
+
"+faststart",
|
|
1742
|
+
outputPath
|
|
1743
|
+
];
|
|
1744
|
+
}
|
|
1711
1745
|
const ffmpeg = (0, import_child_process.spawn)(this.ffmpegPath, args, { stdio: ["pipe", "inherit", "pipe"] });
|
|
1712
1746
|
let ffmpegError = "";
|
|
1713
1747
|
ffmpeg.stderr.on("data", (data) => {
|
|
@@ -1956,13 +1990,21 @@ async function createTextEngine(opts = {}) {
|
|
|
1956
1990
|
},
|
|
1957
1991
|
async generateVideo(asset, options) {
|
|
1958
1992
|
try {
|
|
1993
|
+
const hasBackground = !!asset.background?.color;
|
|
1994
|
+
const hasAnimation = !!asset.animation?.preset;
|
|
1995
|
+
const needsAlpha = !hasBackground && hasAnimation;
|
|
1996
|
+
console.log(
|
|
1997
|
+
`\u{1F3A8} Video settings: Animation=${hasAnimation}, Background=${hasBackground}, Alpha=${needsAlpha}`
|
|
1998
|
+
);
|
|
1959
1999
|
const finalOptions = {
|
|
1960
2000
|
width: asset.width ?? width,
|
|
1961
2001
|
height: asset.height ?? height,
|
|
1962
2002
|
fps,
|
|
1963
2003
|
duration: asset.animation?.duration ?? 3,
|
|
1964
2004
|
outputPath: options.outputPath ?? "output.mp4",
|
|
1965
|
-
pixelRatio: asset.pixelRatio ?? pixelRatio
|
|
2005
|
+
pixelRatio: asset.pixelRatio ?? pixelRatio,
|
|
2006
|
+
hasAlpha: needsAlpha,
|
|
2007
|
+
...options
|
|
1966
2008
|
};
|
|
1967
2009
|
const frameGenerator = async (time) => {
|
|
1968
2010
|
return this.renderFrame(asset, time);
|