nodejs-audio-visualizer 2.1.0 → 2.1.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/dist/bpmEncoder.d.ts +10 -0
- package/dist/bpmEncoder.js +76 -0
- package/dist/bpmEncoder.js.map +1 -0
- package/dist/image.d.ts +4 -4
- package/dist/image.js +26 -20
- package/dist/image.js.map +1 -1
- package/dist/index.js +7 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/bpmEncoder.ts +71 -0
- package/src/image.ts +46 -28
- package/src/index.ts +6 -4
- package/src/tests/image.test.ts +14 -7
- package/src/tests/index.test.ts +2 -2
- package/src/tests/snapshots/frameSnapshotSpectrumDown.json +1 -1
- package/src/tests/snapshots/frameSnapshotSpectrumUp.json +1 -1
- package/src/tests/snapshots/frameSnapshotSpectrumUpOpacity50.json +1 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createBpmEncoder = function (imgData) {
|
|
4
|
+
var width = imgData.width;
|
|
5
|
+
var height = imgData.height;
|
|
6
|
+
var extraBytes = width % 4;
|
|
7
|
+
var rgbSize = height * (3 * width + extraBytes);
|
|
8
|
+
var headerInfoSize = 40;
|
|
9
|
+
/******************header***********************/
|
|
10
|
+
var flag = 'BM';
|
|
11
|
+
var reserved = 0;
|
|
12
|
+
var offset = 54;
|
|
13
|
+
var fileSize = rgbSize + offset;
|
|
14
|
+
var planes = 1;
|
|
15
|
+
var bitPP = 24;
|
|
16
|
+
var compress = 0;
|
|
17
|
+
var hr = 0;
|
|
18
|
+
var vr = 0;
|
|
19
|
+
var colors = 0;
|
|
20
|
+
var importantColors = 0;
|
|
21
|
+
return function (buffer) {
|
|
22
|
+
var tempBuffer = Buffer.alloc(offset + rgbSize);
|
|
23
|
+
var pos = 0;
|
|
24
|
+
tempBuffer.write(flag, pos, 2);
|
|
25
|
+
pos += 2;
|
|
26
|
+
tempBuffer.writeUInt32LE(fileSize, pos);
|
|
27
|
+
pos += 4;
|
|
28
|
+
tempBuffer.writeUInt32LE(reserved, pos);
|
|
29
|
+
pos += 4;
|
|
30
|
+
tempBuffer.writeUInt32LE(offset, pos);
|
|
31
|
+
pos += 4;
|
|
32
|
+
tempBuffer.writeUInt32LE(headerInfoSize, pos);
|
|
33
|
+
pos += 4;
|
|
34
|
+
tempBuffer.writeUInt32LE(width, pos);
|
|
35
|
+
pos += 4;
|
|
36
|
+
tempBuffer.writeInt32LE(-height, pos);
|
|
37
|
+
pos += 4;
|
|
38
|
+
tempBuffer.writeUInt16LE(planes, pos);
|
|
39
|
+
pos += 2;
|
|
40
|
+
tempBuffer.writeUInt16LE(bitPP, pos);
|
|
41
|
+
pos += 2;
|
|
42
|
+
tempBuffer.writeUInt32LE(compress, pos);
|
|
43
|
+
pos += 4;
|
|
44
|
+
tempBuffer.writeUInt32LE(rgbSize, pos);
|
|
45
|
+
pos += 4;
|
|
46
|
+
tempBuffer.writeUInt32LE(hr, pos);
|
|
47
|
+
pos += 4;
|
|
48
|
+
tempBuffer.writeUInt32LE(vr, pos);
|
|
49
|
+
pos += 4;
|
|
50
|
+
tempBuffer.writeUInt32LE(colors, pos);
|
|
51
|
+
pos += 4;
|
|
52
|
+
tempBuffer.writeUInt32LE(importantColors, pos);
|
|
53
|
+
pos += 4;
|
|
54
|
+
var i = 0;
|
|
55
|
+
var rowBytes = 3 * width + extraBytes;
|
|
56
|
+
for (var y = 0; y < height; y++) {
|
|
57
|
+
for (var x = 0; x < width; x++) {
|
|
58
|
+
var p = pos + y * rowBytes + x * 3;
|
|
59
|
+
i++; // a
|
|
60
|
+
tempBuffer[p] = buffer[i++]; // b
|
|
61
|
+
tempBuffer[p + 1] = buffer[i++]; // g
|
|
62
|
+
tempBuffer[p + 2] = buffer[i++]; // r
|
|
63
|
+
}
|
|
64
|
+
if (extraBytes > 0) {
|
|
65
|
+
var fillOffset = pos + y * rowBytes + width * 3;
|
|
66
|
+
tempBuffer.fill(0, fillOffset, fillOffset + extraBytes);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
shiftPos: pos,
|
|
71
|
+
rowBytes: rowBytes,
|
|
72
|
+
data: tempBuffer
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=bpmEncoder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bpmEncoder.js","sourceRoot":"","sources":["../src/bpmEncoder.ts"],"names":[],"mappings":"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"}
|
package/dist/image.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { RotationAliasName } from './index';
|
|
3
3
|
import { BmpDecoder } from 'bmp-js';
|
|
4
|
+
import { EncodedBmp } from './bpmEncoder';
|
|
4
5
|
export interface Color {
|
|
5
6
|
red: number;
|
|
6
7
|
green: number;
|
|
@@ -22,7 +23,7 @@ interface MixColorProps {
|
|
|
22
23
|
export declare const mixValues: (value1: number, value1Opacity: number, value2: number) => number;
|
|
23
24
|
export declare const mixColors: ({ color, colorOpacity, backgroundColor, }: MixColorProps) => Color;
|
|
24
25
|
interface DrawRectPorps {
|
|
25
|
-
imageDstBuffer:
|
|
26
|
+
imageDstBuffer: EncodedBmp;
|
|
26
27
|
position: Position;
|
|
27
28
|
size: Size;
|
|
28
29
|
color: Color;
|
|
@@ -30,7 +31,7 @@ interface DrawRectPorps {
|
|
|
30
31
|
}
|
|
31
32
|
export declare const drawRect: ({ imageDstBuffer, position, size, color, opacity, }: DrawRectPorps) => void;
|
|
32
33
|
interface CreateVisualizerFrameProps {
|
|
33
|
-
backgroundImageBuffer:
|
|
34
|
+
backgroundImageBuffer: EncodedBmp;
|
|
34
35
|
spectrum: number[];
|
|
35
36
|
size: Size;
|
|
36
37
|
position: Position;
|
|
@@ -39,10 +40,9 @@ interface CreateVisualizerFrameProps {
|
|
|
39
40
|
color: Color | string;
|
|
40
41
|
opacity: number;
|
|
41
42
|
}
|
|
42
|
-
export declare const createVisualizerFrame: ({ backgroundImageBuffer, spectrum, size, position, rotation, margin, color, opacity, }: CreateVisualizerFrameProps) =>
|
|
43
|
+
export declare const createVisualizerFrame: ({ backgroundImageBuffer, spectrum, size, position, rotation, margin, color, opacity, }: CreateVisualizerFrameProps) => EncodedBmp;
|
|
43
44
|
export declare const convertToBmp: (filePath: string) => Promise<Buffer>;
|
|
44
45
|
export declare const parseImage: (buffer: Buffer) => BmpDecoder;
|
|
45
|
-
export declare const createImageBuffer: (image: BmpDecoder) => Buffer;
|
|
46
46
|
export declare const getImageColor: (image: BmpDecoder) => Color;
|
|
47
47
|
export declare const invertColor: (color: Color) => {
|
|
48
48
|
red: number;
|
package/dist/image.js
CHANGED
|
@@ -52,30 +52,37 @@ exports.mixColors = function (_a) {
|
|
|
52
52
|
blue: exports.mixValues(color.blue, colorOpacity, backgroundColor.blue),
|
|
53
53
|
};
|
|
54
54
|
};
|
|
55
|
+
var getRectPixelColor = function (params) {
|
|
56
|
+
var imageDstBuffer = params.imageDstBuffer, pixelIndex = params.pixelIndex, color = params.color, opacity = params.opacity;
|
|
57
|
+
if (opacity === 1) {
|
|
58
|
+
return color;
|
|
59
|
+
}
|
|
60
|
+
var backgroundPixelColor = {
|
|
61
|
+
blue: imageDstBuffer.data[pixelIndex],
|
|
62
|
+
green: imageDstBuffer.data[pixelIndex + 1],
|
|
63
|
+
red: imageDstBuffer.data[pixelIndex + 2],
|
|
64
|
+
};
|
|
65
|
+
var resultColor = exports.mixColors({
|
|
66
|
+
color: color,
|
|
67
|
+
colorOpacity: opacity,
|
|
68
|
+
backgroundColor: backgroundPixelColor,
|
|
69
|
+
});
|
|
70
|
+
return resultColor;
|
|
71
|
+
};
|
|
55
72
|
exports.drawRect = function (_a) {
|
|
56
73
|
var imageDstBuffer = _a.imageDstBuffer, position = _a.position, size = _a.size, color = _a.color, opacity = _a.opacity;
|
|
57
74
|
for (var currY = position.y; currY < position.y + size.height; currY++) {
|
|
58
75
|
for (var currX = position.x; currX < position.x + size.width; currX++) {
|
|
59
|
-
var
|
|
60
|
-
|
|
61
|
-
imageDstBuffer
|
|
62
|
-
|
|
63
|
-
imageDstBuffer.data[idx + 3] = color.red;
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
var backgroundPixelColor = {
|
|
67
|
-
red: imageDstBuffer.data[idx + 3],
|
|
68
|
-
green: imageDstBuffer.data[idx + 2],
|
|
69
|
-
blue: imageDstBuffer.data[idx + 1],
|
|
70
|
-
};
|
|
71
|
-
var resultColor = exports.mixColors({
|
|
76
|
+
var pixelIndex = imageDstBuffer.shiftPos + currY * imageDstBuffer.rowBytes + currX * 3;
|
|
77
|
+
var pixelColor = getRectPixelColor({
|
|
78
|
+
imageDstBuffer: imageDstBuffer,
|
|
79
|
+
pixelIndex: pixelIndex,
|
|
72
80
|
color: color,
|
|
73
|
-
|
|
74
|
-
backgroundColor: backgroundPixelColor,
|
|
81
|
+
opacity: opacity,
|
|
75
82
|
});
|
|
76
|
-
imageDstBuffer.data[
|
|
77
|
-
imageDstBuffer.data[
|
|
78
|
-
imageDstBuffer.data[
|
|
83
|
+
imageDstBuffer.data[pixelIndex] = pixelColor.blue;
|
|
84
|
+
imageDstBuffer.data[pixelIndex + 1] = pixelColor.green;
|
|
85
|
+
imageDstBuffer.data[pixelIndex + 2] = pixelColor.red;
|
|
79
86
|
}
|
|
80
87
|
}
|
|
81
88
|
};
|
|
@@ -105,7 +112,7 @@ var drawSpectrum = function (_a) {
|
|
|
105
112
|
exports.createVisualizerFrame = function (_a) {
|
|
106
113
|
var backgroundImageBuffer = _a.backgroundImageBuffer, spectrum = _a.spectrum, size = _a.size, position = _a.position, rotation = _a.rotation, margin = _a.margin, color = _a.color, opacity = _a.opacity;
|
|
107
114
|
var imageDstBuffer = Object.assign({}, backgroundImageBuffer);
|
|
108
|
-
imageDstBuffer.data = Buffer.from(
|
|
115
|
+
imageDstBuffer.data = Buffer.from(backgroundImageBuffer.data);
|
|
109
116
|
var rgbSpectrumColor = (typeof color === 'string') ? hexToRgb(color) : color;
|
|
110
117
|
drawSpectrum({
|
|
111
118
|
imageDstBuffer: imageDstBuffer,
|
|
@@ -147,7 +154,6 @@ exports.convertToBmp = function (filePath) { return __awaiter(void 0, void 0, vo
|
|
|
147
154
|
});
|
|
148
155
|
}); };
|
|
149
156
|
exports.parseImage = function (buffer) { return bmp_js_1.decode(buffer); };
|
|
150
|
-
exports.createImageBuffer = function (image) { return bmp_js_1.encode(image).data; };
|
|
151
157
|
exports.getImageColor = function (image) {
|
|
152
158
|
var blueSum = 0;
|
|
153
159
|
var greenSum = 0;
|
package/dist/image.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.js","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,
|
|
1
|
+
{"version":3,"file":"image.js","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -51,6 +51,7 @@ var config_1 = require("./config");
|
|
|
51
51
|
var audio_1 = require("./audio");
|
|
52
52
|
var image_1 = require("./image");
|
|
53
53
|
var video_1 = require("./video");
|
|
54
|
+
var bpmEncoder_1 = require("./bpmEncoder");
|
|
54
55
|
exports.PCM_FORMAT = {
|
|
55
56
|
bit: 8,
|
|
56
57
|
sign: 'u',
|
|
@@ -62,7 +63,7 @@ var sleep = function (timeout) {
|
|
|
62
63
|
};
|
|
63
64
|
exports.renderAudioVisualizer = function (config, onProgress, shouldStop) {
|
|
64
65
|
return new Promise(function (resolve) { return __awaiter(void 0, void 0, void 0, function () {
|
|
65
|
-
var audioFilePath, backgroundImagePath, outVideoPath, backgroundImageBmpBuffer, backgroundImage, audioReader, audioBuffer, sampleRate, spectrumBusesCount, spectrumBusMargin, FPS, spectrumWidth, spectrumHeight, spectrumX, spectrumY, spectrumRotation, spectrumColor, spectrumOpacity, ffmpeg_cfr, ffmpeg_preset, frame_processing_delay, audioDuration, framesCount, audioDataStep, ffmpegVideoWriter, processSpectrum, _loop_1, i, state_1;
|
|
66
|
+
var audioFilePath, backgroundImagePath, outVideoPath, backgroundImageBmpBuffer, backgroundImage, audioReader, audioBuffer, sampleRate, spectrumBusesCount, spectrumBusMargin, FPS, spectrumWidth, spectrumHeight, spectrumX, spectrumY, spectrumRotation, spectrumColor, spectrumOpacity, ffmpeg_cfr, ffmpeg_preset, frame_processing_delay, audioDuration, framesCount, audioDataStep, ffmpegVideoWriter, bpmEncoder, backgroundImageBuffer, processSpectrum, _loop_1, i, state_1;
|
|
66
67
|
return __generator(this, function (_a) {
|
|
67
68
|
switch (_a.label) {
|
|
68
69
|
case 0:
|
|
@@ -100,9 +101,11 @@ exports.renderAudioVisualizer = function (config, onProgress, shouldStop) {
|
|
|
100
101
|
audioDataStep = Math.trunc(audioBuffer.length / framesCount);
|
|
101
102
|
ffmpegVideoWriter = video_1.spawnFfmpegVideoWriter(__assign(__assign(__assign({ audioFilename: audioFilePath, videoFileName: outVideoPath, fps: FPS }, (!!onProgress && { onStderr: video_1.getProgress(video_1.calculateProgress(framesCount + 1, onProgress)) })), (ffmpeg_cfr && { crf: ffmpeg_cfr })), (ffmpeg_preset && { preset: ffmpeg_preset })));
|
|
102
103
|
ffmpegVideoWriter.on('exit', function (code) { return resolve(code); });
|
|
104
|
+
bpmEncoder = bpmEncoder_1.createBpmEncoder({ width: backgroundImage.width, height: backgroundImage.height });
|
|
105
|
+
backgroundImageBuffer = bpmEncoder(backgroundImage.data);
|
|
103
106
|
processSpectrum = audio_1.createSpectrumsProcessor(spectrumBusesCount);
|
|
104
107
|
_loop_1 = function (i) {
|
|
105
|
-
var audioDataParser, spectrum, frameImage,
|
|
108
|
+
var audioDataParser, spectrum, frameImage, isFrameProcessed;
|
|
106
109
|
return __generator(this, function (_a) {
|
|
107
110
|
switch (_a.label) {
|
|
108
111
|
case 0:
|
|
@@ -111,7 +114,7 @@ exports.renderAudioVisualizer = function (config, onProgress, shouldStop) {
|
|
|
111
114
|
};
|
|
112
115
|
spectrum = processSpectrum(i, audioDataParser);
|
|
113
116
|
frameImage = image_1.createVisualizerFrame({
|
|
114
|
-
backgroundImageBuffer:
|
|
117
|
+
backgroundImageBuffer: backgroundImageBuffer,
|
|
115
118
|
spectrum: spectrum,
|
|
116
119
|
size: { width: spectrumWidth, height: spectrumHeight },
|
|
117
120
|
position: { x: spectrumX, y: spectrumY },
|
|
@@ -120,8 +123,7 @@ exports.renderAudioVisualizer = function (config, onProgress, shouldStop) {
|
|
|
120
123
|
color: spectrumColor,
|
|
121
124
|
opacity: spectrumOpacity,
|
|
122
125
|
});
|
|
123
|
-
|
|
124
|
-
isFrameProcessed = ffmpegVideoWriter.stdin.write(frameImageBuffer);
|
|
126
|
+
isFrameProcessed = ffmpegVideoWriter.stdin.write(frameImage.data);
|
|
125
127
|
if (!!isFrameProcessed) return [3 /*break*/, 2];
|
|
126
128
|
return [4 /*yield*/, video_1.waitDrain(ffmpegVideoWriter.stdin)];
|
|
127
129
|
case 1:
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,mCAkBkB;AAClB,iCAAqF;AACrF,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export interface EncodedBmp {
|
|
2
|
+
shiftPos: number;
|
|
3
|
+
rowBytes: number;
|
|
4
|
+
data: Buffer;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const createBpmEncoder = (imgData: { width: number; height: number; }) => {
|
|
8
|
+
const width = imgData.width;
|
|
9
|
+
const height = imgData.height;
|
|
10
|
+
const extraBytes = width % 4;
|
|
11
|
+
const rgbSize = height * (3 * width + extraBytes);
|
|
12
|
+
const headerInfoSize = 40;
|
|
13
|
+
|
|
14
|
+
/******************header***********************/
|
|
15
|
+
const flag = 'BM';
|
|
16
|
+
const reserved = 0;
|
|
17
|
+
const offset = 54;
|
|
18
|
+
const fileSize = rgbSize + offset;
|
|
19
|
+
const planes = 1;
|
|
20
|
+
const bitPP = 24;
|
|
21
|
+
const compress = 0;
|
|
22
|
+
const hr = 0;
|
|
23
|
+
const vr = 0;
|
|
24
|
+
const colors = 0;
|
|
25
|
+
const importantColors = 0;
|
|
26
|
+
|
|
27
|
+
return (buffer: Buffer): EncodedBmp => {
|
|
28
|
+
const tempBuffer = Buffer.alloc(offset + rgbSize);
|
|
29
|
+
|
|
30
|
+
let pos = 0;
|
|
31
|
+
tempBuffer.write(flag, pos, 2); pos += 2;
|
|
32
|
+
tempBuffer.writeUInt32LE(fileSize, pos); pos += 4;
|
|
33
|
+
tempBuffer.writeUInt32LE(reserved, pos); pos += 4;
|
|
34
|
+
tempBuffer.writeUInt32LE(offset, pos); pos += 4;
|
|
35
|
+
|
|
36
|
+
tempBuffer.writeUInt32LE(headerInfoSize, pos); pos += 4;
|
|
37
|
+
tempBuffer.writeUInt32LE(width, pos); pos += 4;
|
|
38
|
+
tempBuffer.writeInt32LE(-height, pos); pos += 4;
|
|
39
|
+
tempBuffer.writeUInt16LE(planes, pos); pos += 2;
|
|
40
|
+
tempBuffer.writeUInt16LE(bitPP, pos); pos += 2;
|
|
41
|
+
tempBuffer.writeUInt32LE(compress, pos); pos += 4;
|
|
42
|
+
tempBuffer.writeUInt32LE(rgbSize, pos); pos += 4;
|
|
43
|
+
tempBuffer.writeUInt32LE(hr, pos); pos += 4;
|
|
44
|
+
tempBuffer.writeUInt32LE(vr, pos); pos += 4;
|
|
45
|
+
tempBuffer.writeUInt32LE(colors, pos); pos += 4;
|
|
46
|
+
tempBuffer.writeUInt32LE(importantColors, pos); pos += 4;
|
|
47
|
+
|
|
48
|
+
let i = 0;
|
|
49
|
+
const rowBytes = 3 * width + extraBytes;
|
|
50
|
+
|
|
51
|
+
for (let y = 0; y < height; y++) {
|
|
52
|
+
for (let x = 0; x < width; x++) {
|
|
53
|
+
const p = pos + y * rowBytes + x * 3;
|
|
54
|
+
i++; // a
|
|
55
|
+
tempBuffer[p] = buffer[i++]; // b
|
|
56
|
+
tempBuffer[p + 1] = buffer[i++]; // g
|
|
57
|
+
tempBuffer[p + 2] = buffer[i++]; // r
|
|
58
|
+
}
|
|
59
|
+
if (extraBytes > 0) {
|
|
60
|
+
const fillOffset = pos + y * rowBytes + width * 3;
|
|
61
|
+
tempBuffer.fill(0, fillOffset, fillOffset + extraBytes);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
shiftPos: pos,
|
|
67
|
+
rowBytes,
|
|
68
|
+
data: tempBuffer
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
};
|
package/src/image.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { RotationAliasName } from './index';
|
|
2
|
-
import { decode,
|
|
2
|
+
import { decode, BmpDecoder } from 'bmp-js';
|
|
3
|
+
import { EncodedBmp } from './bpmEncoder';
|
|
3
4
|
import Jimp from 'jimp';
|
|
4
5
|
|
|
5
6
|
export interface Color {
|
|
@@ -39,8 +40,37 @@ export const mixColors = ({
|
|
|
39
40
|
};
|
|
40
41
|
};
|
|
41
42
|
|
|
43
|
+
const getRectPixelColor = (params: {
|
|
44
|
+
imageDstBuffer: EncodedBmp;
|
|
45
|
+
pixelIndex: number;
|
|
46
|
+
color: Color;
|
|
47
|
+
opacity: number;
|
|
48
|
+
}) => {
|
|
49
|
+
const {
|
|
50
|
+
imageDstBuffer,
|
|
51
|
+
pixelIndex,
|
|
52
|
+
color,
|
|
53
|
+
opacity,
|
|
54
|
+
} = params;
|
|
55
|
+
if (opacity === 1) {
|
|
56
|
+
return color;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const backgroundPixelColor: Color = {
|
|
60
|
+
blue: imageDstBuffer.data[pixelIndex],
|
|
61
|
+
green: imageDstBuffer.data[pixelIndex + 1],
|
|
62
|
+
red: imageDstBuffer.data[pixelIndex + 2],
|
|
63
|
+
};
|
|
64
|
+
const resultColor = mixColors({
|
|
65
|
+
color,
|
|
66
|
+
colorOpacity: opacity,
|
|
67
|
+
backgroundColor: backgroundPixelColor,
|
|
68
|
+
});
|
|
69
|
+
return resultColor;
|
|
70
|
+
};
|
|
71
|
+
|
|
42
72
|
interface DrawRectPorps {
|
|
43
|
-
imageDstBuffer:
|
|
73
|
+
imageDstBuffer: EncodedBmp;
|
|
44
74
|
position: Position;
|
|
45
75
|
size: Size;
|
|
46
76
|
color: Color;
|
|
@@ -54,35 +84,24 @@ export const drawRect = ({
|
|
|
54
84
|
color,
|
|
55
85
|
opacity,
|
|
56
86
|
}: DrawRectPorps) => {
|
|
57
|
-
for (
|
|
58
|
-
for (
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
imageDstBuffer
|
|
62
|
-
|
|
63
|
-
imageDstBuffer.data[idx + 3] = color.red;
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const backgroundPixelColor: Color = {
|
|
68
|
-
red: imageDstBuffer.data[idx + 3],
|
|
69
|
-
green: imageDstBuffer.data[idx + 2],
|
|
70
|
-
blue: imageDstBuffer.data[idx + 1],
|
|
71
|
-
};
|
|
72
|
-
const resultColor = mixColors({
|
|
87
|
+
for (let currY = position.y; currY < position.y + size.height; currY++) {
|
|
88
|
+
for (let currX = position.x; currX < position.x + size.width; currX++) {
|
|
89
|
+
const pixelIndex = imageDstBuffer.shiftPos + currY * imageDstBuffer.rowBytes + currX * 3;
|
|
90
|
+
const pixelColor = getRectPixelColor({
|
|
91
|
+
imageDstBuffer,
|
|
92
|
+
pixelIndex,
|
|
73
93
|
color,
|
|
74
|
-
|
|
75
|
-
backgroundColor: backgroundPixelColor,
|
|
94
|
+
opacity,
|
|
76
95
|
});
|
|
77
|
-
imageDstBuffer.data[
|
|
78
|
-
imageDstBuffer.data[
|
|
79
|
-
imageDstBuffer.data[
|
|
96
|
+
imageDstBuffer.data[pixelIndex] = pixelColor.blue;
|
|
97
|
+
imageDstBuffer.data[pixelIndex + 1] = pixelColor.green;
|
|
98
|
+
imageDstBuffer.data[pixelIndex + 2] = pixelColor.red;
|
|
80
99
|
}
|
|
81
100
|
}
|
|
82
101
|
};
|
|
83
102
|
|
|
84
103
|
interface DrawSpectrumProps {
|
|
85
|
-
imageDstBuffer:
|
|
104
|
+
imageDstBuffer: EncodedBmp;
|
|
86
105
|
spectrum: number[];
|
|
87
106
|
size: Size;
|
|
88
107
|
position: Position;
|
|
@@ -127,7 +146,7 @@ const drawSpectrum = ({
|
|
|
127
146
|
};
|
|
128
147
|
|
|
129
148
|
interface CreateVisualizerFrameProps {
|
|
130
|
-
backgroundImageBuffer:
|
|
149
|
+
backgroundImageBuffer: EncodedBmp;
|
|
131
150
|
spectrum: number[];
|
|
132
151
|
size: Size;
|
|
133
152
|
position: Position;
|
|
@@ -148,7 +167,8 @@ export const createVisualizerFrame = ({
|
|
|
148
167
|
opacity,
|
|
149
168
|
}: CreateVisualizerFrameProps) => {
|
|
150
169
|
const imageDstBuffer = Object.assign({}, backgroundImageBuffer);
|
|
151
|
-
imageDstBuffer.data = Buffer.from(
|
|
170
|
+
imageDstBuffer.data = Buffer.from(backgroundImageBuffer.data);
|
|
171
|
+
|
|
152
172
|
const rgbSpectrumColor = (typeof color === 'string') ? hexToRgb(color) : color;
|
|
153
173
|
drawSpectrum({
|
|
154
174
|
imageDstBuffer,
|
|
@@ -180,8 +200,6 @@ export const convertToBmp = async (filePath: string) =>
|
|
|
180
200
|
|
|
181
201
|
export const parseImage = (buffer: Buffer) => decode(buffer);
|
|
182
202
|
|
|
183
|
-
export const createImageBuffer = (image: BmpDecoder) => encode(image).data;
|
|
184
|
-
|
|
185
203
|
export const getImageColor = (image: BmpDecoder): Color => {
|
|
186
204
|
let blueSum = 0;
|
|
187
205
|
let greenSum = 0;
|
package/src/index.ts
CHANGED
|
@@ -18,8 +18,9 @@ import {
|
|
|
18
18
|
getSpectrumRotation
|
|
19
19
|
} from './config';
|
|
20
20
|
import { createAudioBuffer, bufferToUInt8, createSpectrumsProcessor } from './audio';
|
|
21
|
-
import { parseImage, createVisualizerFrame,
|
|
21
|
+
import { parseImage, createVisualizerFrame, getImageColor, invertColor, Color, convertToBmp } from './image';
|
|
22
22
|
import { spawnFfmpegVideoWriter, getProgress, calculateProgress, waitDrain } from './video';
|
|
23
|
+
import { createBpmEncoder } from './bpmEncoder';
|
|
23
24
|
|
|
24
25
|
export const PCM_FORMAT = {
|
|
25
26
|
bit: 8,
|
|
@@ -120,13 +121,15 @@ export const renderAudioVisualizer = (config: Config, onProgress?: (progress: nu
|
|
|
120
121
|
});
|
|
121
122
|
ffmpegVideoWriter.on('exit', (code: number) => resolve(code));
|
|
122
123
|
|
|
124
|
+
const bpmEncoder = createBpmEncoder({ width: backgroundImage.width, height: backgroundImage.height });
|
|
125
|
+
const backgroundImageBuffer = bpmEncoder(backgroundImage.data);
|
|
123
126
|
const processSpectrum = createSpectrumsProcessor(spectrumBusesCount);
|
|
124
127
|
for (let i = 0; i < framesCount; i++) {
|
|
125
128
|
const audioDataParser = () =>
|
|
126
129
|
PCM_FORMAT.parseFunction(audioBuffer, i * audioDataStep, i * audioDataStep + audioDataStep);
|
|
127
130
|
const spectrum = processSpectrum(i, audioDataParser);
|
|
128
131
|
const frameImage = createVisualizerFrame({
|
|
129
|
-
backgroundImageBuffer
|
|
132
|
+
backgroundImageBuffer,
|
|
130
133
|
spectrum,
|
|
131
134
|
size: { width: spectrumWidth, height: spectrumHeight },
|
|
132
135
|
position: { x: spectrumX, y: spectrumY },
|
|
@@ -135,8 +138,7 @@ export const renderAudioVisualizer = (config: Config, onProgress?: (progress: nu
|
|
|
135
138
|
color: spectrumColor,
|
|
136
139
|
opacity: spectrumOpacity,
|
|
137
140
|
});
|
|
138
|
-
const
|
|
139
|
-
const isFrameProcessed = ffmpegVideoWriter.stdin.write(frameImageBuffer);
|
|
141
|
+
const isFrameProcessed = ffmpegVideoWriter.stdin.write(frameImage.data);
|
|
140
142
|
if (!isFrameProcessed) {
|
|
141
143
|
await waitDrain(ffmpegVideoWriter.stdin);
|
|
142
144
|
}
|
package/src/tests/image.test.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
mixValues,
|
|
11
11
|
mixColors,
|
|
12
12
|
} from '../image';
|
|
13
|
+
import { createBpmEncoder } from '../bpmEncoder';
|
|
13
14
|
|
|
14
15
|
import frameSnapshotSpectrumDown from './snapshots/frameSnapshotSpectrumDown.json';
|
|
15
16
|
import frameSnapshotSpectrumUp from './snapshots/frameSnapshotSpectrumUp.json';
|
|
@@ -48,7 +49,11 @@ describe('image', function () {
|
|
|
48
49
|
it('drawRect', function () {
|
|
49
50
|
const imageWidth = 10;
|
|
50
51
|
const imageHeight = 10;
|
|
52
|
+
const extraBytes = imageWidth % 4;
|
|
53
|
+
const rowBytes = 3 * imageWidth + extraBytes;
|
|
51
54
|
const imageDstBuffer = {
|
|
55
|
+
shiftPos: 54,
|
|
56
|
+
rowBytes,
|
|
52
57
|
width: imageWidth,
|
|
53
58
|
data: Array.from({ length: imageWidth * imageHeight * 4 }).fill(0)
|
|
54
59
|
};
|
|
@@ -59,11 +64,11 @@ describe('image', function () {
|
|
|
59
64
|
const rectColor: Color = { red: 111, green: 112, blue: 123 };
|
|
60
65
|
|
|
61
66
|
const expectedImageData = Array.from({ length: imageWidth * imageWidth * 4 }).fill(0);
|
|
62
|
-
const imagePixelIndices = [
|
|
67
|
+
const imagePixelIndices = [162, 165, 168, 171, 194, 197, 200, 203, 226, 229, 232, 235];
|
|
63
68
|
imagePixelIndices.forEach((pixelIndex) => {
|
|
64
|
-
expectedImageData[pixelIndex
|
|
65
|
-
expectedImageData[pixelIndex +
|
|
66
|
-
expectedImageData[pixelIndex +
|
|
69
|
+
expectedImageData[pixelIndex] = rectColor.blue;
|
|
70
|
+
expectedImageData[pixelIndex + 1] = rectColor.green;
|
|
71
|
+
expectedImageData[pixelIndex + 2] = rectColor.red;
|
|
67
72
|
});
|
|
68
73
|
|
|
69
74
|
drawRect({
|
|
@@ -80,8 +85,10 @@ describe('image', function () {
|
|
|
80
85
|
const backgroundImagePath = path.resolve('example/media/background.png');
|
|
81
86
|
const backgroundImageBmpBuffer = await convertToBmp(backgroundImagePath);
|
|
82
87
|
const backgroundImage = parseImage(backgroundImageBmpBuffer);
|
|
88
|
+
const bpmEncoder = createBpmEncoder({ width: backgroundImage.width, height: backgroundImage.height });
|
|
89
|
+
const backgroundImageBuffer = bpmEncoder(backgroundImage.data);
|
|
83
90
|
const frameSpectrumDown = createVisualizerFrame({
|
|
84
|
-
backgroundImageBuffer
|
|
91
|
+
backgroundImageBuffer,
|
|
85
92
|
spectrum: [0.5, 0, 1],
|
|
86
93
|
size: { width: 15, height: 20 },
|
|
87
94
|
position: { x: 15, y: 0 },
|
|
@@ -94,7 +101,7 @@ describe('image', function () {
|
|
|
94
101
|
expect(resultSpectrumDown).deep.equal(frameSnapshotSpectrumDown);
|
|
95
102
|
|
|
96
103
|
const frameSpectrumUp = createVisualizerFrame({
|
|
97
|
-
backgroundImageBuffer
|
|
104
|
+
backgroundImageBuffer,
|
|
98
105
|
spectrum: [0.1, 1, 0],
|
|
99
106
|
size: { width: 25, height: 23 },
|
|
100
107
|
position: { x: 10, y: 5 },
|
|
@@ -107,7 +114,7 @@ describe('image', function () {
|
|
|
107
114
|
expect(resultSpectrumUp).deep.equal(frameSnapshotSpectrumUp);
|
|
108
115
|
|
|
109
116
|
const frameSpectrumUpOpacity50 = createVisualizerFrame({
|
|
110
|
-
backgroundImageBuffer
|
|
117
|
+
backgroundImageBuffer,
|
|
111
118
|
spectrum: [0.1, 1, 0],
|
|
112
119
|
size: { width: 25, height: 23 },
|
|
113
120
|
position: { x: 10, y: 5 },
|
package/src/tests/index.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { expect } from 'chai';
|
|
2
2
|
import { createSandbox } from 'sinon';
|
|
3
|
-
import { renderAudioVisualizer, Config
|
|
3
|
+
import { renderAudioVisualizer, Config } from '../index';
|
|
4
4
|
import fs from 'fs';
|
|
5
5
|
import { Writable, Readable } from 'stream';
|
|
6
6
|
import { ChildProcessWithoutNullStreams } from 'child_process';
|
|
@@ -24,7 +24,7 @@ describe('index', function () {
|
|
|
24
24
|
let childProcessStream: unknown = {
|
|
25
25
|
stdin: new Writable(),
|
|
26
26
|
stderr: new Readable(),
|
|
27
|
-
on: function (
|
|
27
|
+
on: function (_: string, callback: Function) {
|
|
28
28
|
exitCallback = callback;
|
|
29
29
|
}
|
|
30
30
|
};
|