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.
- package/README.md +70 -0
- package/core.d.ts +10 -0
- package/core.js +52 -1
- 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
|
|
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 = '';
|