simple-ffmpegjs 0.3.0 → 0.3.1

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
@@ -48,8 +48,8 @@ The library handles FFmpeg's complexity internally while exposing a clean interf
48
48
  ## Example Output
49
49
 
50
50
  <p align="center">
51
- <a href="https://7llpl63xkl8jovgt.public.blob.vercel-storage.com/wonders-showcase.mp4">
52
- <img src="https://7llpl63xkl8jovgt.public.blob.vercel-storage.com/wonders-thumbnail.jpg" alt="Example video - click to watch" width="640">
51
+ <a href="https://7llpl63xkl8jovgt.public.blob.vercel-storage.com/wonders-showcase-1.mp4">
52
+ <img src="https://7llpl63xkl8jovgt.public.blob.vercel-storage.com/simple-ffmpeg/wonders-thumbnail-1.jpg" alt="Example video - click to watch" width="640">
53
53
  </a>
54
54
  </p>
55
55
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "simple-ffmpegjs",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Lightweight Node.js library for programmatic video composition using FFmpeg. Concatenate clips, add transitions, mix audio, overlay text, and more.",
5
5
  "author": "Brayden Blackwell <braydenblackwell21@gmail.com> (https://github.com/Fats403)",
6
6
  "license": "MIT",
@@ -75,6 +75,11 @@ function buildMainCommand({
75
75
  if (hasVideo && !audioOnly) {
76
76
  cmd += `-c:v ${videoCodec} `;
77
77
 
78
+ // Cross-browser compatibility flags for libx264 (Firefox, Safari, older devices)
79
+ if (videoCodec === "libx264") {
80
+ cmd += `-profile:v main -pix_fmt yuv420p `;
81
+ }
82
+
78
83
  // Preset (for software encoders)
79
84
  if (
80
85
  videoPreset &&
@@ -174,14 +179,25 @@ function buildTextBatchCommand({
174
179
  intermediateCrf,
175
180
  outputPath,
176
181
  }) {
177
- return `ffmpeg -y -i "${escapeFilePath(inputPath)}" -filter_complex "[0:v]null[invid];${filterString}" -map "[outVideoAndText]" -map 0:a? -c:v ${intermediateVideoCodec} -preset ${intermediatePreset} -crf ${intermediateCrf} -c:a copy -movflags +faststart "${escapeFilePath(outputPath)}"`;
182
+ // Add compatibility flags for libx264
183
+ const compatFlags =
184
+ intermediateVideoCodec === "libx264"
185
+ ? "-profile:v main -pix_fmt yuv420p "
186
+ : "";
187
+ return `ffmpeg -y -i "${escapeFilePath(
188
+ inputPath
189
+ )}" -filter_complex "[0:v]null[invid];${filterString}" -map "[outVideoAndText]" -map 0:a? -c:v ${intermediateVideoCodec} ${compatFlags}-preset ${intermediatePreset} -crf ${intermediateCrf} -c:a copy -movflags +faststart "${escapeFilePath(
190
+ outputPath
191
+ )}"`;
178
192
  }
179
193
 
180
194
  /**
181
195
  * Build command to generate a thumbnail
182
196
  */
183
197
  function buildThumbnailCommand({ inputPath, outputPath, time, width, height }) {
184
- let cmd = `ffmpeg -y -ss ${time} -i "${escapeFilePath(inputPath)}" -vframes 1 `;
198
+ let cmd = `ffmpeg -y -ss ${time} -i "${escapeFilePath(
199
+ inputPath
200
+ )}" -vframes 1 `;
185
201
 
186
202
  if (width || height) {
187
203
  const w = width || -1;
@@ -88,11 +88,22 @@ function buildFontsizeParam(baseClip, start, end) {
88
88
  if (type === "pop-bounce") {
89
89
  const entry =
90
90
  typeof anim.in === "number" ? anim.in : C.DEFAULT_TEXT_ANIM_IN;
91
- return `:fontsize=if(lt(t\\,${start + entry})\\,${(baseSize * 0.7).toFixed(
92
- 3
93
- )}+${(baseSize * 0.4).toFixed(
94
- 3
95
- )}*sin(PI/2*(t-${start})/${entry})\\,${baseSize})`;
91
+ // Two-phase bounce: grow with overshoot, then settle smoothly
92
+ const growEnd = start + entry * 0.6;
93
+ const minSize = (baseSize * 0.7).toFixed(3);
94
+ const overshoot = (baseSize * 1.1).toFixed(3);
95
+ const growAmount = (baseSize * 0.4).toFixed(3);
96
+ const settleAmount = (baseSize * 0.1).toFixed(3);
97
+ const phase1Duration = (entry * 0.6).toFixed(4);
98
+ const phase2Duration = (entry * 0.4).toFixed(4);
99
+ // Phase 1: 0.7 -> 1.1 (ease-out), Phase 2: 1.1 -> 1.0 (ease-in-out)
100
+ return `:fontsize=if(lt(t\\,${growEnd.toFixed(
101
+ 4
102
+ )})\\,${minSize}+${growAmount}*sin(PI/2*(t-${start})/${phase1Duration})\\,if(lt(t\\,${
103
+ start + entry
104
+ })\\,${overshoot}-${settleAmount}*sin(PI/2*(t-${growEnd.toFixed(
105
+ 4
106
+ )})/${phase2Duration})\\,${baseSize}))`;
96
107
  }
97
108
 
98
109
  if (type === "scale-in") {