ffmpeg-progress 1.4.0 → 1.6.0

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.
Files changed (4) hide show
  1. package/README.md +70 -0
  2. package/core.d.ts +10 -0
  3. package/core.js +52 -1
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -42,6 +42,54 @@ await convertFile({
42
42
  timer.end()
43
43
  ```
44
44
 
45
+ **Convert video with custom FFmpeg arguments**:
46
+
47
+ ```typescript
48
+ import { convertFile } from 'ffmpeg-progress'
49
+
50
+ // H.264 codec with YUV420p pixel format and 2000k bitrate
51
+ await convertFile({
52
+ inFile: 'input.mp4',
53
+ outFile: 'output.mp4',
54
+ ffmpegArgs: ['-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-b:v', '2000k'],
55
+ })
56
+
57
+ // Resize video - Scale to 720p
58
+ await convertFile({
59
+ inFile: 'input.mp4',
60
+ outFile: 'output.mp4',
61
+ ffmpegArgs: ['-vf', 'scale=1280:720'],
62
+ })
63
+
64
+ // Extract audio - Convert video to MP3
65
+ await convertFile({
66
+ inFile: 'input.mp4',
67
+ outFile: 'output.mp3',
68
+ ffmpegArgs: ['-vn', '-acodec', 'libmp3lame', '-ab', '192k'],
69
+ })
70
+
71
+ // Quality preset - Use H.264 with slow preset and CRF quality
72
+ await convertFile({
73
+ inFile: 'input.mp4',
74
+ outFile: 'output.mp4',
75
+ ffmpegArgs: ['-c:v', 'libx264', '-preset', 'slow', '-crf', '23'],
76
+ })
77
+ ```
78
+
79
+ **Rotate video**:
80
+
81
+ ```typescript
82
+ import { rotateVideo } from 'ffmpeg-progress'
83
+
84
+ await rotateVideo({
85
+ inFile: 'test/in.mp4',
86
+ outFile: 'test/rotated.mp4',
87
+ angle: 90, // Rotate 90° clockwise (or 180, 270)
88
+ })
89
+ ```
90
+
91
+ Progress monitoring is also available similar to `convertFile` using `onDuration`, `onProgress`, etc.
92
+
45
93
  **Get video resolution**:
46
94
 
47
95
  ```typescript
@@ -51,6 +99,15 @@ console.log(await getVideoResolution('test/rotate.mp4'))
51
99
  // { width: 3024, height: 4032 }
52
100
  ```
53
101
 
102
+ **Get video duration in seconds**:
103
+
104
+ ```typescript
105
+ import { getVideoDuration } from 'ffmpeg-progress'
106
+
107
+ console.log(await getVideoDuration('test/in.mp4'))
108
+ // 15.04 (duration in seconds)
109
+ ```
110
+
54
111
  ## Typescript Types
55
112
 
56
113
  ```typescript
@@ -89,6 +146,16 @@ export function convertFile(
89
146
  args: {
90
147
  inFile: string
91
148
  outFile: string
149
+ ffmpegArgs?: string[]
150
+ } & ProgressArgs,
151
+ ): Promise<void>
152
+
153
+ export function rotateVideo(
154
+ args: {
155
+ inFile: string
156
+ outFile: string
157
+ /** degrees to rotate in clockwise direction */
158
+ angle: 90 | 180 | 270
92
159
  } & ProgressArgs,
93
160
  ): Promise<void>
94
161
 
@@ -107,6 +174,9 @@ export function getVideoResolution(video_file: string): Promise<{
107
174
  width: number
108
175
  height: number
109
176
  }>
177
+
178
+ /** @description get video duration in seconds, e.g. `15.04` */
179
+ export async function getVideoDuration(video_file: string): Promise<number>
110
180
  ```
111
181
 
112
182
  ## License
package/core.d.ts CHANGED
@@ -43,6 +43,14 @@ export type OnProgressArgs = {
43
43
  export declare function convertFile(args: {
44
44
  inFile: string;
45
45
  outFile: string;
46
+ /** e.g. ['-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-b:v', '2000k'] */
47
+ ffmpegArgs?: string[];
48
+ } & ProgressArgs): Promise<void>;
49
+ export declare function rotateVideo(args: {
50
+ inFile: string;
51
+ outFile: string;
52
+ /** degrees to rotate in clockwise direction */
53
+ angle: 90 | 180 | 270;
46
54
  } & ProgressArgs): Promise<void>;
47
55
  export declare function attachChildProcess(args: {
48
56
  childProcess: ChildProcessWithoutNullStreams;
@@ -62,3 +70,5 @@ export declare function getVideoResolution(video_file: string): Promise<{
62
70
  width: number;
63
71
  height: number;
64
72
  }>;
73
+ /** @description get video duration in seconds, e.g. `15.04` */
74
+ export declare function getVideoDuration(video_file: string): Promise<number>;
package/core.js CHANGED
@@ -5,9 +5,11 @@ exports.secondsToString = secondsToString;
5
5
  exports.parseVideoMetadata = parseVideoMetadata;
6
6
  exports.scanVideo = scanVideo;
7
7
  exports.convertFile = convertFile;
8
+ exports.rotateVideo = rotateVideo;
8
9
  exports.attachChildProcess = attachChildProcess;
9
10
  exports.estimateOutSize = estimateOutSize;
10
11
  exports.getVideoResolution = getVideoResolution;
12
+ exports.getVideoDuration = getVideoDuration;
11
13
  const child_process_1 = require("child_process");
12
14
  const promises_1 = require("fs/promises");
13
15
  const path_1 = require("path");
@@ -135,9 +137,37 @@ function scanVideo(file) {
135
137
  });
136
138
  }
137
139
  async function convertFile(args) {
138
- let childProcess = (0, child_process_1.spawn)('ffmpeg', ['-y', '-i', args.inFile, args.outFile]);
140
+ let ffmpegCommand = ['-y', '-i', args.inFile];
141
+ if (args.ffmpegArgs) {
142
+ ffmpegCommand.push(...args.ffmpegArgs);
143
+ }
144
+ ffmpegCommand.push(args.outFile);
145
+ let childProcess = (0, child_process_1.spawn)('ffmpeg', ffmpegCommand);
139
146
  return attachChildProcess({ childProcess, ...args });
140
147
  }
148
+ async function rotateVideo(args) {
149
+ let filter;
150
+ switch (args.angle) {
151
+ case 90:
152
+ // 90° clockwise
153
+ filter = 'transpose=1';
154
+ break;
155
+ case 180:
156
+ // 180° rotation
157
+ filter = 'transpose=1,transpose=1';
158
+ break;
159
+ case 270:
160
+ // 270° clockwise (or 90° counterclockwise)
161
+ filter = 'transpose=2';
162
+ break;
163
+ default:
164
+ throw new Error(`Unsupported rotation angle: ${args.angle}. Supported angles are 90, 180, or 270 degrees.`);
165
+ }
166
+ return convertFile({
167
+ ...args,
168
+ ffmpegArgs: ['-vf', filter, '-c:a', 'copy'],
169
+ });
170
+ }
141
171
  async function attachChildProcess(args) {
142
172
  let { code, signal } = await new Promise((resolve, reject) => {
143
173
  let { childProcess } = args;
@@ -232,6 +262,27 @@ async function getVideoResolution(video_file) {
232
262
  await (0, promises_1.unlink)(image_file);
233
263
  return resolution;
234
264
  }
265
+ /** @description get video duration in seconds, e.g. `15.04` */
266
+ async function getVideoDuration(video_file) {
267
+ let childProcess = (0, child_process_1.spawn)('ffprobe', [
268
+ '-v',
269
+ 'error',
270
+ '-show_entries',
271
+ 'format=duration',
272
+ '-of',
273
+ 'default=noprint_wrappers=1:nokey=1',
274
+ video_file,
275
+ ]);
276
+ var { stdout, stderr, code, signal } = await waitChildProcess(childProcess);
277
+ if (code != 0) {
278
+ throw new Error(`ffprobe exit abnormally, exit code: ${code}, signal: ${signal}, stdout: ${stdout}, stderr: ${stderr}`);
279
+ }
280
+ let duration = +stdout;
281
+ if (!duration) {
282
+ throw new Error('failed to parse video duration: ' + JSON.stringify(stdout));
283
+ }
284
+ return duration;
285
+ }
235
286
  function waitChildProcess(childProcess) {
236
287
  return new Promise((resolve, reject) => {
237
288
  let stdout = '';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ffmpeg-progress",
3
- "version": "1.4.0",
3
+ "version": "1.6.0",
4
4
  "description": "Extract progress from ffmpeg child_process",
5
5
  "keywords": [
6
6
  "ffmpeg",