ffmpeg-progress 1.2.1 → 1.3.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 (3) hide show
  1. package/core.d.ts +4 -1
  2. package/core.js +53 -16
  3. package/package.json +3 -3
package/core.d.ts CHANGED
@@ -16,8 +16,11 @@ export type ScanVideoResult = {
16
16
  /** @description e.g. 180.03 or 0 */
17
17
  seconds: number;
18
18
  /** @description e.g. "4032x3024" */
19
- resolution: string;
19
+ resolution: string | null;
20
+ /** @description e.g. 44100 for 44.1kHz */
21
+ audioSampleRate: number | null;
20
22
  };
23
+ export declare function parseVideoMetadata(stdout: string): ScanVideoResult;
21
24
  export declare function scanVideo(file: string): Promise<ScanVideoResult>;
22
25
  export type ProgressArgs = {
23
26
  onData?: (chunk: Buffer) => void;
package/core.js CHANGED
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parseToSeconds = parseToSeconds;
4
4
  exports.secondsToString = secondsToString;
5
+ exports.parseVideoMetadata = parseVideoMetadata;
5
6
  exports.scanVideo = scanVideo;
6
7
  exports.convertFile = convertFile;
7
8
  exports.attachChildProcess = attachChildProcess;
@@ -62,26 +63,62 @@ function format_ms(ms) {
62
63
  return '0' + ms;
63
64
  return ms;
64
65
  }
66
+ // e.g. " Duration: 00:03:00.03, start: 0.000000, bitrate: 2234 kb/s"
67
+ // e.g. " Duration: N/A, start: 0.000000, bitrate: N/A"
68
+ let duration_regex = /Duration: ([0-9:.]+|N\/A),/;
69
+ // e.g. " Stream #0:0[0x1](und): Video: h264 (Baseline) (avc1 / 0x31637661), yuvj420p(pc, progressive), 4032x3024, 2045 kb/s, 29.73 fps, 600 tbr, 600 tbn (default)"
70
+ // e.g. " Stream #0:0[0x1](eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt470bg/unknown/unknown, progressive), 1920x1080 [SAR 1:1 DAR 16:9], 3958 kb/s, 29.49 fps, 29.83 tbr, 11456 tbn (default)"
71
+ // e.g. " Stream #0:1: Video: flv1 (flv), yuv420p, 1080x1920, 200 kb/s, 60 fps, 60 tbr, 1k tbn"
72
+ let resolution_regex = /Stream #0:\d[\w\[\]\(\)]*: Video: .+ (\d+x\d+)[\s|,]/;
73
+ // e.g. " Stream #0:0: Audio: mp3 (mp3float), 44100 Hz, stereo, fltp, 128 kb/s"
74
+ let audio_sample_rate_regex = /Stream #0:\d[\w\[\]\(\)]*: Audio: .+ (\d+) Hz/;
75
+ function parseVideoMetadata(stdout) {
76
+ let lines = stdout
77
+ .split('\n')
78
+ .map(line => line.trim())
79
+ .filter(line => line.length > 0);
80
+ let match = stdout.match(duration_regex);
81
+ if (!match) {
82
+ throw new Error('failed to find video duration');
83
+ }
84
+ let duration = match[1];
85
+ let seconds = parseToSeconds(duration);
86
+ let resolution = parseResolution(lines);
87
+ let audioSampleRate = parseAudioSampleRate(lines);
88
+ return { duration, seconds, resolution, audioSampleRate };
89
+ }
90
+ function parseResolution(lines) {
91
+ let has_video = lines.find(line => line.trim().startsWith('Stream #0:') && line.includes(' Video: '));
92
+ if (!has_video)
93
+ return null;
94
+ let line = lines.find(line => resolution_regex.test(line));
95
+ let match = line?.match(resolution_regex);
96
+ if (!match) {
97
+ throw new Error('failed to find video resolution');
98
+ }
99
+ let resolution = match[1];
100
+ return resolution;
101
+ }
102
+ function parseAudioSampleRate(lines) {
103
+ let has_audio = lines.find(line => line.trim().startsWith('Stream #0:') && line.includes(' Audio: '));
104
+ if (!has_audio)
105
+ return null;
106
+ let line = lines.find(line => audio_sample_rate_regex.test(line));
107
+ let match = line?.match(audio_sample_rate_regex);
108
+ if (!match) {
109
+ throw new Error('failed to find audio sample rate');
110
+ }
111
+ let audioSampleRate = +match[1];
112
+ if (!audioSampleRate) {
113
+ throw new Error(`failed to parse audio sample rate: ${JSON.stringify(match[1])}`);
114
+ }
115
+ return audioSampleRate;
116
+ }
65
117
  function scanVideo(file) {
66
118
  return new Promise((resolve, reject) => {
67
119
  (0, child_process_1.exec)(`ffmpeg -i ${JSON.stringify(file)} 2>&1`, (err, stdout, stderr) => {
68
120
  try {
69
- // e.g. " Duration: 00:03:00.03, start: 0.000000, bitrate: 2234 kb/s"
70
- // e.g. " Duration: N/A, start: 0.000000, bitrate: N/A"
71
- let match = stdout.match(/Duration: ([0-9:.]+|N\/A),/);
72
- if (!match) {
73
- throw new Error('failed to find video duration');
74
- }
75
- let duration = match[1];
76
- let seconds = parseToSeconds(duration);
77
- // e.g. " Stream #0:0[0x1](und): Video: h264 (Baseline) (avc1 / 0x31637661), yuvj420p(pc, progressive), 4032x3024, 2045 kb/s, 29.73 fps, 600 tbr, 600 tbn (default)"
78
- // e.g. " Stream #0:0[0x1](eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt470bg/unknown/unknown, progressive), 1920x1080 [SAR 1:1 DAR 16:9], 3958 kb/s, 29.49 fps, 29.83 tbr, 11456 tbn (default)"
79
- match = stdout.match(/Stream #0:\d.+: Video: .+ (\d+x\d+)[\s|,]/);
80
- if (!match) {
81
- throw new Error('failed to find video resolution');
82
- }
83
- let resolution = match[1];
84
- resolve({ duration, seconds, resolution });
121
+ resolve(parseVideoMetadata(stdout));
85
122
  }
86
123
  catch (e) {
87
124
  let error = e instanceof Error ? e : new Error(String(e));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ffmpeg-progress",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "description": "Extract progress from ffmpeg child_process",
5
5
  "keywords": [
6
6
  "ffmpeg",
@@ -37,7 +37,7 @@
37
37
  "core.js"
38
38
  ],
39
39
  "scripts": {
40
- "mocha": "rm -f *.js && ts-mocha *.test.ts",
40
+ "mocha": "rm -f *.js && ts-mocha \"*.{test,spec}.ts\"",
41
41
  "test": "npm run mocha && tsc --noEmit",
42
42
  "build": "tsc -p ."
43
43
  },
@@ -47,7 +47,7 @@
47
47
  "@types/mocha": "^10.0.10",
48
48
  "@types/node": "^22.9.0",
49
49
  "chai": "^4.5.0",
50
- "mocha": "^11.0.1",
50
+ "mocha": "^10.8.2",
51
51
  "ts-mocha": "^10.0.0",
52
52
  "ts-node": "^10.9.2",
53
53
  "ts-node-dev": "^2.0.0",