nodejs-audio-visualizer 4.3.7 → 4.3.9

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 (47) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +75 -75
  3. package/dist/audio.d.ts +12 -12
  4. package/dist/audio.js +120 -120
  5. package/dist/beats.d.ts +19 -19
  6. package/dist/beats.js +43 -43
  7. package/dist/bpmEncoder.d.ts +14 -14
  8. package/dist/bpmEncoder.js +97 -97
  9. package/dist/config.d.ts +67 -67
  10. package/dist/config.js +356 -356
  11. package/dist/dsp.d.ts +16 -16
  12. package/dist/dsp.js +76 -76
  13. package/dist/highlight.d.ts +32 -32
  14. package/dist/highlight.js +325 -325
  15. package/dist/image.d.ts +79 -79
  16. package/dist/image.js +458 -458
  17. package/dist/index.d.ts +72 -72
  18. package/dist/index.js +539 -541
  19. package/dist/index.js.map +1 -1
  20. package/dist/subtitleConvert.d.ts +3 -3
  21. package/dist/subtitleConvert.js +61 -61
  22. package/dist/video.d.ts +77 -72
  23. package/dist/video.js +407 -338
  24. package/dist/video.js.map +1 -1
  25. package/dist/waitForEventLoop.d.ts +1 -1
  26. package/dist/waitForEventLoop.js +5 -5
  27. package/package.json +61 -61
  28. package/src/audio.ts +120 -120
  29. package/src/beats.ts +68 -68
  30. package/src/bpmEncoder.ts +97 -97
  31. package/src/config.ts +462 -462
  32. package/src/dsp.ts +95 -95
  33. package/src/highlight.ts +284 -284
  34. package/src/image.ts +602 -602
  35. package/src/index.ts +693 -678
  36. package/src/subtitleConvert.ts +63 -63
  37. package/src/tests/audio.test.ts +96 -96
  38. package/src/tests/config.test.ts +475 -475
  39. package/src/tests/dsp.test.ts +24 -24
  40. package/src/tests/highlight.test.ts +178 -178
  41. package/src/tests/image.test.ts +222 -222
  42. package/src/tests/index.test.ts +156 -63
  43. package/src/tests/subtitleConvert.test.ts +23 -23
  44. package/src/tests/video.test.ts +214 -138
  45. package/src/typings.d.ts +6 -6
  46. package/src/video.ts +517 -437
  47. package/src/waitForEventLoop.ts +2 -2
@@ -1,23 +1,23 @@
1
- import { expect } from 'chai';
2
- import { lrcToSrt, isLikelyLrc, normalizeInlineSubtitlesToSrt } from '../subtitleConvert';
3
-
4
- describe('subtitleConvert', function () {
5
- it('isLikelyLrc', function () {
6
- expect(isLikelyLrc('[00:01.00]Hello')).equal(true);
7
- expect(isLikelyLrc('1\n00:00:01,000 --> 00:00:02,000\nSRT')).equal(false);
8
- });
9
-
10
- it('lrcToSrt converts basic LRC to SRT', function () {
11
- const lrc = '[00:01.00]Line one\n[00:03.50]Line two';
12
- const srt = lrcToSrt(lrc);
13
- expect(srt).to.include('00:00:01,000 --> 00:00:03,500');
14
- expect(srt).to.include('Line one');
15
- expect(srt).to.include('00:00:03,500 -->');
16
- expect(srt).to.include('Line two');
17
- });
18
-
19
- it('normalizeInlineSubtitlesToSrt leaves SRT unchanged', function () {
20
- const s = '1\n00:00:00,000 --> 00:00:01,000\nX';
21
- expect(normalizeInlineSubtitlesToSrt(s)).equal(s);
22
- });
23
- });
1
+ import { expect } from 'chai';
2
+ import { lrcToSrt, isLikelyLrc, normalizeInlineSubtitlesToSrt } from '../subtitleConvert';
3
+
4
+ describe('subtitleConvert', function () {
5
+ it('isLikelyLrc', function () {
6
+ expect(isLikelyLrc('[00:01.00]Hello')).equal(true);
7
+ expect(isLikelyLrc('1\n00:00:01,000 --> 00:00:02,000\nSRT')).equal(false);
8
+ });
9
+
10
+ it('lrcToSrt converts basic LRC to SRT', function () {
11
+ const lrc = '[00:01.00]Line one\n[00:03.50]Line two';
12
+ const srt = lrcToSrt(lrc);
13
+ expect(srt).to.include('00:00:01,000 --> 00:00:03,500');
14
+ expect(srt).to.include('Line one');
15
+ expect(srt).to.include('00:00:03,500 -->');
16
+ expect(srt).to.include('Line two');
17
+ });
18
+
19
+ it('normalizeInlineSubtitlesToSrt leaves SRT unchanged', function () {
20
+ const s = '1\n00:00:00,000 --> 00:00:01,000\nX';
21
+ expect(normalizeInlineSubtitlesToSrt(s)).equal(s);
22
+ });
23
+ });
@@ -1,138 +1,214 @@
1
- import { expect } from 'chai';
2
- import { Writable, Readable, Pipe } from 'stream';
3
- import { spawnFfmpegVideoWriter } from '../video';
4
- import { createSandbox, SinonStub } from 'sinon';
5
- import child_process, { ChildProcessWithoutNullStreams } from 'child_process';
6
-
7
- let childProcessStream = {
8
- stdin: new Writable(),
9
- stderr: new Readable(),
10
- };
11
-
12
- const videoSandbox = createSandbox();
13
-
14
- describe('video', function () {
15
-
16
- this.beforeAll(function () {
17
- videoSandbox.stub(child_process, 'spawn').returns(childProcessStream as ChildProcessWithoutNullStreams);
18
- });
19
-
20
- this.afterAll(function () {
21
- videoSandbox.restore();
22
- });
23
-
24
- it('spawnFfmpegVideoWriter returns truthy value', function () {
25
- const childProcessReadableStream = new Readable();
26
- childProcessReadableStream._read = () => { };
27
- const childProcessWritableStream = new Writable();
28
- (<Pipe>childProcessWritableStream.pipe) = () => childProcessWritableStream;
29
-
30
- childProcessStream.stdin = childProcessWritableStream;
31
- childProcessStream.stderr = childProcessReadableStream;
32
-
33
- const result = spawnFfmpegVideoWriter({ audioFilename: 'test', videoFileName: 'test', fps: 11 });
34
- expect(!!result).equal(true);
35
- });
36
-
37
- it('spawnFfmpegVideoWriter uses -ss and -t for single audioSegment', function () {
38
- const childProcessReadableStream = new Readable();
39
- childProcessReadableStream._read = () => { };
40
- const childProcessWritableStream = new Writable();
41
- (<Pipe>childProcessWritableStream.pipe) = () => childProcessWritableStream;
42
-
43
- childProcessStream.stdin = childProcessWritableStream;
44
- childProcessStream.stderr = childProcessReadableStream;
45
-
46
- let spawnArgs: string[] = [];
47
- const spawnStub = child_process.spawn as SinonStub;
48
- spawnStub.callsFake((_cmd: string, args: string[]) => {
49
- spawnArgs = args;
50
- return childProcessStream as ChildProcessWithoutNullStreams;
51
- });
52
-
53
- spawnFfmpegVideoWriter({
54
- audioFilename: 'audio.mp3',
55
- videoFileName: 'out.mp4',
56
- fps: 25,
57
- audioSegment: { seekSeconds: 12, durationSeconds: 15 },
58
- });
59
-
60
- spawnStub.resetBehavior();
61
- spawnStub.returns(childProcessStream as ChildProcessWithoutNullStreams);
62
-
63
- expect(spawnArgs).to.not.include('-filter_complex');
64
- const ssIdx = spawnArgs.indexOf('-ss');
65
- expect(ssIdx).greaterThan(-1);
66
- expect(spawnArgs[ssIdx + 1]).to.equal('12');
67
- const tIdx = spawnArgs.indexOf('-t');
68
- expect(tIdx).greaterThan(-1);
69
- expect(spawnArgs[tIdx + 1]).to.equal('15');
70
- });
71
-
72
- it('spawnFfmpegVideoWriter adds subtitles filter when subtitle file is provided', function () {
73
- const childProcessReadableStream = new Readable();
74
- childProcessReadableStream._read = () => { };
75
- const childProcessWritableStream = new Writable();
76
- (<Pipe>childProcessWritableStream.pipe) = () => childProcessWritableStream;
77
-
78
- childProcessStream.stdin = childProcessWritableStream;
79
- childProcessStream.stderr = childProcessReadableStream;
80
-
81
- let spawnArgs: string[] = [];
82
- const spawnStub = child_process.spawn as SinonStub;
83
- spawnStub.callsFake((_cmd: string, args: string[]) => {
84
- spawnArgs = args;
85
- return childProcessStream as ChildProcessWithoutNullStreams;
86
- });
87
-
88
- spawnFfmpegVideoWriter({
89
- audioFilename: 'audio.mp3',
90
- subtitleFilename: '/tmp/subtitles.srt',
91
- videoFileName: 'out.mp4',
92
- fps: 25,
93
- });
94
-
95
- spawnStub.resetBehavior();
96
- spawnStub.returns(childProcessStream as ChildProcessWithoutNullStreams);
97
-
98
- const vfIdx = spawnArgs.indexOf('-vf');
99
- expect(vfIdx).greaterThan(-1);
100
- expect(spawnArgs[vfIdx + 1]).to.equal(
101
- "subtitles='/tmp/subtitles.srt':force_style='Alignment=2'",
102
- );
103
- });
104
-
105
- it('spawnFfmpegVideoWriter passes subtitle Alignment from subtitleAlignmentAss', function () {
106
- const childProcessReadableStream = new Readable();
107
- childProcessReadableStream._read = () => { };
108
- const childProcessWritableStream = new Writable();
109
- (<Pipe>childProcessWritableStream.pipe) = () => childProcessWritableStream;
110
-
111
- childProcessStream.stdin = childProcessWritableStream;
112
- childProcessStream.stderr = childProcessReadableStream;
113
-
114
- let spawnArgs: string[] = [];
115
- const spawnStub = child_process.spawn as SinonStub;
116
- spawnStub.callsFake((_cmd: string, args: string[]) => {
117
- spawnArgs = args;
118
- return childProcessStream as ChildProcessWithoutNullStreams;
119
- });
120
-
121
- spawnFfmpegVideoWriter({
122
- audioFilename: 'audio.mp3',
123
- subtitleFilename: '/tmp/subtitles.srt',
124
- subtitleAlignmentAss: 8,
125
- videoFileName: 'out.mp4',
126
- fps: 25,
127
- });
128
-
129
- spawnStub.resetBehavior();
130
- spawnStub.returns(childProcessStream as ChildProcessWithoutNullStreams);
131
-
132
- const vfIdx = spawnArgs.indexOf('-vf');
133
- expect(vfIdx).greaterThan(-1);
134
- expect(spawnArgs[vfIdx + 1]).to.equal(
135
- "subtitles='/tmp/subtitles.srt':force_style='Alignment=8'",
136
- );
137
- });
138
- });
1
+ import { expect } from 'chai';
2
+ import { Writable, Readable, Pipe } from 'stream';
3
+ import { EventEmitter } from 'events';
4
+ import { spawnFfmpegVideoWriter, waitDrain, readVideoFrame, waitForProcessExit } from '../video';
5
+ import { createSandbox, SinonStub } from 'sinon';
6
+ import child_process, { ChildProcessWithoutNullStreams } from 'child_process';
7
+
8
+ let childProcessStream = {
9
+ stdin: new Writable(),
10
+ stderr: new Readable(),
11
+ };
12
+
13
+ const videoSandbox = createSandbox();
14
+
15
+ describe('video', function () {
16
+
17
+ this.beforeAll(function () {
18
+ videoSandbox.stub(child_process, 'spawn').returns(childProcessStream as ChildProcessWithoutNullStreams);
19
+ });
20
+
21
+ this.afterAll(function () {
22
+ videoSandbox.restore();
23
+ });
24
+
25
+ it('spawnFfmpegVideoWriter returns truthy value', function () {
26
+ const childProcessReadableStream = new Readable();
27
+ childProcessReadableStream._read = () => { };
28
+ const childProcessWritableStream = new Writable();
29
+ (<Pipe>childProcessWritableStream.pipe) = () => childProcessWritableStream;
30
+
31
+ childProcessStream.stdin = childProcessWritableStream;
32
+ childProcessStream.stderr = childProcessReadableStream;
33
+
34
+ const result = spawnFfmpegVideoWriter({ audioFilename: 'test', videoFileName: 'test', fps: 11 });
35
+ expect(!!result).equal(true);
36
+ });
37
+
38
+ it('spawnFfmpegVideoWriter uses -ss and -t for single audioSegment', function () {
39
+ const childProcessReadableStream = new Readable();
40
+ childProcessReadableStream._read = () => { };
41
+ const childProcessWritableStream = new Writable();
42
+ (<Pipe>childProcessWritableStream.pipe) = () => childProcessWritableStream;
43
+
44
+ childProcessStream.stdin = childProcessWritableStream;
45
+ childProcessStream.stderr = childProcessReadableStream;
46
+
47
+ let spawnArgs: string[] = [];
48
+ const spawnStub = child_process.spawn as SinonStub;
49
+ spawnStub.callsFake((_cmd: string, args: string[]) => {
50
+ spawnArgs = args;
51
+ return childProcessStream as ChildProcessWithoutNullStreams;
52
+ });
53
+
54
+ spawnFfmpegVideoWriter({
55
+ audioFilename: 'audio.mp3',
56
+ videoFileName: 'out.mp4',
57
+ fps: 25,
58
+ audioSegment: { seekSeconds: 12, durationSeconds: 15 },
59
+ });
60
+
61
+ spawnStub.resetBehavior();
62
+ spawnStub.returns(childProcessStream as ChildProcessWithoutNullStreams);
63
+
64
+ expect(spawnArgs).to.not.include('-filter_complex');
65
+ const ssIdx = spawnArgs.indexOf('-ss');
66
+ expect(ssIdx).greaterThan(-1);
67
+ expect(spawnArgs[ssIdx + 1]).to.equal('12');
68
+ const tIdx = spawnArgs.indexOf('-t');
69
+ expect(tIdx).greaterThan(-1);
70
+ expect(spawnArgs[tIdx + 1]).to.equal('15');
71
+ });
72
+
73
+ it('spawnFfmpegVideoWriter adds subtitles filter when subtitle file is provided', function () {
74
+ const childProcessReadableStream = new Readable();
75
+ childProcessReadableStream._read = () => { };
76
+ const childProcessWritableStream = new Writable();
77
+ (<Pipe>childProcessWritableStream.pipe) = () => childProcessWritableStream;
78
+
79
+ childProcessStream.stdin = childProcessWritableStream;
80
+ childProcessStream.stderr = childProcessReadableStream;
81
+
82
+ let spawnArgs: string[] = [];
83
+ const spawnStub = child_process.spawn as SinonStub;
84
+ spawnStub.callsFake((_cmd: string, args: string[]) => {
85
+ spawnArgs = args;
86
+ return childProcessStream as ChildProcessWithoutNullStreams;
87
+ });
88
+
89
+ spawnFfmpegVideoWriter({
90
+ audioFilename: 'audio.mp3',
91
+ subtitleFilename: '/tmp/subtitles.srt',
92
+ videoFileName: 'out.mp4',
93
+ fps: 25,
94
+ });
95
+
96
+ spawnStub.resetBehavior();
97
+ spawnStub.returns(childProcessStream as ChildProcessWithoutNullStreams);
98
+
99
+ const vfIdx = spawnArgs.indexOf('-vf');
100
+ expect(vfIdx).greaterThan(-1);
101
+ expect(spawnArgs[vfIdx + 1]).to.equal(
102
+ "subtitles='/tmp/subtitles.srt':force_style='Alignment=2'",
103
+ );
104
+ });
105
+
106
+ it('spawnFfmpegVideoWriter passes subtitle Alignment from subtitleAlignmentAss', function () {
107
+ const childProcessReadableStream = new Readable();
108
+ childProcessReadableStream._read = () => { };
109
+ const childProcessWritableStream = new Writable();
110
+ (<Pipe>childProcessWritableStream.pipe) = () => childProcessWritableStream;
111
+
112
+ childProcessStream.stdin = childProcessWritableStream;
113
+ childProcessStream.stderr = childProcessReadableStream;
114
+
115
+ let spawnArgs: string[] = [];
116
+ const spawnStub = child_process.spawn as SinonStub;
117
+ spawnStub.callsFake((_cmd: string, args: string[]) => {
118
+ spawnArgs = args;
119
+ return childProcessStream as ChildProcessWithoutNullStreams;
120
+ });
121
+
122
+ spawnFfmpegVideoWriter({
123
+ audioFilename: 'audio.mp3',
124
+ subtitleFilename: '/tmp/subtitles.srt',
125
+ subtitleAlignmentAss: 8,
126
+ videoFileName: 'out.mp4',
127
+ fps: 25,
128
+ });
129
+
130
+ spawnStub.resetBehavior();
131
+ spawnStub.returns(childProcessStream as ChildProcessWithoutNullStreams);
132
+
133
+ const vfIdx = spawnArgs.indexOf('-vf');
134
+ expect(vfIdx).greaterThan(-1);
135
+ expect(spawnArgs[vfIdx + 1]).to.equal(
136
+ "subtitles='/tmp/subtitles.srt':force_style='Alignment=8'",
137
+ );
138
+ });
139
+
140
+ it('spawnFfmpegVideoWriter configures image pipe input before output file', function () {
141
+ const childProcessReadableStream = new Readable();
142
+ childProcessReadableStream._read = () => { };
143
+ const childProcessWritableStream = new Writable();
144
+ (<Pipe>childProcessWritableStream.pipe) = () => childProcessWritableStream;
145
+
146
+ childProcessStream.stdin = childProcessWritableStream;
147
+ childProcessStream.stderr = childProcessReadableStream;
148
+
149
+ let spawnArgs: string[] = [];
150
+ const spawnStub = child_process.spawn as SinonStub;
151
+ spawnStub.callsFake((_cmd: string, args: string[]) => {
152
+ spawnArgs = args;
153
+ return childProcessStream as ChildProcessWithoutNullStreams;
154
+ });
155
+
156
+ spawnFfmpegVideoWriter({
157
+ audioFilename: 'audio.mp3',
158
+ videoFileName: 'out.mp4',
159
+ fps: 23.976,
160
+ });
161
+
162
+ spawnStub.resetBehavior();
163
+ spawnStub.returns(childProcessStream as ChildProcessWithoutNullStreams);
164
+
165
+ const audioInputIndex = spawnArgs.indexOf('-i');
166
+ expect(audioInputIndex).greaterThan(-1);
167
+ expect(spawnArgs[audioInputIndex + 1]).to.equal('audio.mp3');
168
+ const imagePipeFlagIndex = spawnArgs.indexOf('image2pipe');
169
+ expect(imagePipeFlagIndex).greaterThan(-1);
170
+ expect(spawnArgs[imagePipeFlagIndex - 1]).to.equal('-f');
171
+ const inputFpsIndex = spawnArgs.indexOf('-framerate');
172
+ expect(inputFpsIndex).greaterThan(-1);
173
+ expect(spawnArgs[inputFpsIndex + 1]).to.equal('23.976');
174
+ const pipeInputIndex = spawnArgs.lastIndexOf('-i');
175
+ expect(spawnArgs[pipeInputIndex + 1]).to.equal('-');
176
+ expect(spawnArgs.includes('-shortest')).to.equal(true);
177
+ expect(spawnArgs[spawnArgs.length - 1]).to.equal('out.mp4');
178
+ });
179
+
180
+ it('waitDrain resolves true on drain', async function () {
181
+ const writable = new Writable();
182
+ const waitPromise = waitDrain(writable, undefined, 50);
183
+ setTimeout(() => writable.emit('drain'), 5);
184
+ const isDrained = await waitPromise;
185
+ expect(isDrained).equal(true);
186
+ });
187
+
188
+ it('waitDrain resolves false on timeout', async function () {
189
+ const writable = new Writable();
190
+ const isDrained = await waitDrain(writable, undefined, 5);
191
+ expect(isDrained).equal(false);
192
+ });
193
+
194
+ it('readVideoFrame resolves null on timeout', async function () {
195
+ const readable = new Readable();
196
+ readable._read = () => {};
197
+ const frame = await readVideoFrame(readable, 4, 5);
198
+ expect(frame).equal(null);
199
+ });
200
+
201
+ it('waitForProcessExit resolves exit code', async function () {
202
+ const processEmitter = new EventEmitter();
203
+ const waitPromise = waitForProcessExit(processEmitter, 50);
204
+ setTimeout(() => processEmitter.emit('exit', 0), 5);
205
+ const exitCode = await waitPromise;
206
+ expect(exitCode).equal(0);
207
+ });
208
+
209
+ it('waitForProcessExit resolves non-zero on timeout', async function () {
210
+ const processEmitter = new EventEmitter();
211
+ const exitCode = await waitForProcessExit(processEmitter, 5);
212
+ expect(exitCode).equal(1);
213
+ });
214
+ });
package/src/typings.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- declare module 'fft-js' {
2
- export function fft(signal: number[]): [number, number][];
3
- export const util: {
4
- fftFreq(phasors: [number, number][], sampleRate: number): number[];
5
- fftMag(phasors: [number, number][]): number[];
6
- };
1
+ declare module 'fft-js' {
2
+ export function fft(signal: number[]): [number, number][];
3
+ export const util: {
4
+ fftFreq(phasors: [number, number][], sampleRate: number): number[];
5
+ fftMag(phasors: [number, number][]): number[];
6
+ };
7
7
  }