music-segment-detector 0.1.0 → 0.2.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 +34 -1
- package/dist/audioAnalyzer.d.ts +6 -1
- package/dist/audioAnalyzer.d.ts.map +1 -1
- package/dist/audioAnalyzer.js +34 -7
- package/dist/audioAnalyzer.js.map +1 -1
- package/dist/audioAnalyzer.worker.d.ts +2 -0
- package/dist/audioAnalyzer.worker.d.ts.map +1 -0
- package/dist/audioAnalyzer.worker.js +115 -0
- package/dist/audioAnalyzer.worker.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/workerPool.d.ts +44 -0
- package/dist/workerPool.d.ts.map +1 -0
- package/dist/workerPool.js +123 -0
- package/dist/workerPool.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,6 +27,20 @@ const features = await analyzeAudio("audio.wav", 2048, 512, (progress) => {
|
|
|
27
27
|
console.log(`Analysis progress: ${(progress * 100).toFixed(1)}%`);
|
|
28
28
|
});
|
|
29
29
|
|
|
30
|
+
// 1-2. Use Worker parallel processing (recommended for large files, 2.5-3x faster)
|
|
31
|
+
const features = await analyzeAudio(
|
|
32
|
+
"audio.wav",
|
|
33
|
+
2048,
|
|
34
|
+
512,
|
|
35
|
+
(progress) => {
|
|
36
|
+
console.log(`Analysis progress: ${(progress * 100).toFixed(1)}%`);
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
useWorkers: true, // Enable Worker parallel processing
|
|
40
|
+
numWorkers: 4, // Optional, defaults to CPU core count
|
|
41
|
+
},
|
|
42
|
+
);
|
|
43
|
+
|
|
30
44
|
// 2. Detect music segments
|
|
31
45
|
const segments = detectMusicSegments(features, {
|
|
32
46
|
energyPercentile: 50, // Energy percentile threshold (0-100)
|
|
@@ -45,7 +59,7 @@ segments.forEach((segment) => {
|
|
|
45
59
|
|
|
46
60
|
## API
|
|
47
61
|
|
|
48
|
-
### `analyzeAudio(audioPath, windowSize?, hopSize?, onProgress?)`
|
|
62
|
+
### `analyzeAudio(audioPath, windowSize?, hopSize?, onProgress?, options?)`
|
|
49
63
|
|
|
50
64
|
Analyze a WAV audio file and extract features.
|
|
51
65
|
|
|
@@ -53,6 +67,9 @@ Analyze a WAV audio file and extract features.
|
|
|
53
67
|
- `windowSize`: Analysis window size (default: 2048)
|
|
54
68
|
- `hopSize`: Window hop size (default: 512)
|
|
55
69
|
- `onProgress`: Optional progress callback function `(progress: number) => void`, parameter is progress value between 0-1
|
|
70
|
+
- `options`: Optional configuration
|
|
71
|
+
- `useWorkers`: Enable Worker parallel processing (default: false)
|
|
72
|
+
- `numWorkers`: Number of workers (default: CPU core count, max 8)
|
|
56
73
|
- Returns: `Promise<AudioFeatures[]>`
|
|
57
74
|
|
|
58
75
|
### `detectMusicSegments(features, config?)`
|
|
@@ -99,6 +116,11 @@ interface AudioFeatures {
|
|
|
99
116
|
spectralFlatness: number;
|
|
100
117
|
}
|
|
101
118
|
|
|
119
|
+
interface AnalyzeAudioOptions {
|
|
120
|
+
useWorkers?: boolean; // Enable Worker parallel processing
|
|
121
|
+
numWorkers?: number; // Number of workers (defaults to CPU core count)
|
|
122
|
+
}
|
|
123
|
+
|
|
102
124
|
interface MusicSegment {
|
|
103
125
|
startTime: number;
|
|
104
126
|
endTime: number;
|
|
@@ -128,11 +150,22 @@ interface DetectionConfig {
|
|
|
128
150
|
- Spectral rolloff
|
|
129
151
|
3. **Post-processing**: Smoothing, merging adjacent segments, filtering short segments
|
|
130
152
|
|
|
153
|
+
## Performance Optimization
|
|
154
|
+
|
|
155
|
+
For large audio files, it's recommended to enable Worker parallel processing for better performance:
|
|
156
|
+
|
|
157
|
+
- **Single-threaded mode** (default): Suitable for small files (< 1 minute) or low-spec environments
|
|
158
|
+
- **Worker parallel mode**: Suitable for large files, 2.5-3x performance boost (on 4-core CPU)
|
|
159
|
+
- Automatically adjusts worker count based on file size
|
|
160
|
+
- Automatically falls back to single-threaded mode if workers fail
|
|
161
|
+
- Supports progress aggregation and error handling
|
|
162
|
+
|
|
131
163
|
## Notes
|
|
132
164
|
|
|
133
165
|
- Only supports WAV format audio files
|
|
134
166
|
- For other formats, use tools like ffmpeg to convert to WAV first
|
|
135
167
|
- Detection accuracy depends on audio quality and configuration parameters
|
|
168
|
+
- Worker mode requires Node.js 16+ version
|
|
136
169
|
|
|
137
170
|
## License
|
|
138
171
|
|
package/dist/audioAnalyzer.d.ts
CHANGED
|
@@ -10,14 +10,19 @@ export interface AudioFeatures {
|
|
|
10
10
|
spectralRolloff: number;
|
|
11
11
|
spectralFlatness: number;
|
|
12
12
|
}
|
|
13
|
+
export interface AnalyzeAudioOptions {
|
|
14
|
+
useWorkers?: boolean;
|
|
15
|
+
numWorkers?: number;
|
|
16
|
+
}
|
|
13
17
|
/**
|
|
14
18
|
* 计算音频特征
|
|
15
19
|
* @param audioPath WAV 音频文件路径
|
|
16
20
|
* @param windowSize 分析窗口大小(样本数)
|
|
17
21
|
* @param hopSize 窗口跳跃大小(样本数)
|
|
18
22
|
* @param onProgress 进度回调函数,参数为 0-1 之间的进度值
|
|
23
|
+
* @param options 可选配置项,包括是否使用 Worker 并行处理
|
|
19
24
|
*/
|
|
20
|
-
export declare function analyzeAudio(audioPath: string, windowSize?: number, hopSize?: number, onProgress?: (progress: number) => void): Promise<AudioFeatures[]>;
|
|
25
|
+
export declare function analyzeAudio(audioPath: string, windowSize?: number, hopSize?: number, onProgress?: (progress: number) => void, options?: AnalyzeAudioOptions): Promise<AudioFeatures[]>;
|
|
21
26
|
/**
|
|
22
27
|
* 计算特征的统计信息(用于调试和阈值设定)
|
|
23
28
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audioAnalyzer.d.ts","sourceRoot":"","sources":["../src/audioAnalyzer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"audioAnalyzer.d.ts","sourceRoot":"","sources":["../src/audioAnalyzer.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAoLD;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,EACjB,UAAU,GAAE,MAAa,EACzB,OAAO,GAAE,MAAY,EACrB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,EACvC,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,aAAa,EAAE,CAAC,CAuB1B;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,aAAa,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAUzC,KAAK,CAAC;QAChB,GAAG,EAAE,MAAM,CAAC;QACZ,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;EA+FL"}
|
package/dist/audioAnalyzer.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from "fs/promises";
|
|
2
2
|
import * as WavDecoder from "wav-decoder";
|
|
3
3
|
import Meyda from "meyda";
|
|
4
|
+
import { WorkerPool } from "./workerPool.js";
|
|
4
5
|
/**
|
|
5
6
|
* 从 WAV 文件读取音频数据
|
|
6
7
|
*/
|
|
@@ -59,14 +60,23 @@ function calculateVariance(samples, mean) {
|
|
|
59
60
|
return sum / samples.length;
|
|
60
61
|
}
|
|
61
62
|
/**
|
|
62
|
-
*
|
|
63
|
-
* @param audioPath WAV 音频文件路径
|
|
64
|
-
* @param windowSize 分析窗口大小(样本数)
|
|
65
|
-
* @param hopSize 窗口跳跃大小(样本数)
|
|
66
|
-
* @param onProgress 进度回调函数,参数为 0-1 之间的进度值
|
|
63
|
+
* 使用 Worker 并行计算音频特征
|
|
67
64
|
*/
|
|
68
|
-
|
|
69
|
-
const
|
|
65
|
+
async function analyzeAudioParallel(channelData, sampleRate, windowSize, hopSize, onProgress, numWorkers) {
|
|
66
|
+
const pool = new WorkerPool({ numWorkers });
|
|
67
|
+
try {
|
|
68
|
+
return await pool.execute(channelData, windowSize, hopSize, sampleRate, onProgress);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
// Worker 失败时回退到单线程模式
|
|
72
|
+
console.warn("Worker parallel processing failed, falling back to single-threaded mode:", error);
|
|
73
|
+
return analyzeAudioSingleThread(channelData, sampleRate, windowSize, hopSize, onProgress);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 单线程模式计算音频特征
|
|
78
|
+
*/
|
|
79
|
+
function analyzeAudioSingleThread(channelData, sampleRate, windowSize, hopSize, onProgress) {
|
|
70
80
|
const features = [];
|
|
71
81
|
// 滑动窗口分析
|
|
72
82
|
const totalWindows = Math.floor((channelData.length - windowSize) / hopSize);
|
|
@@ -116,6 +126,23 @@ export async function analyzeAudio(audioPath, windowSize = 2048, hopSize = 512,
|
|
|
116
126
|
}
|
|
117
127
|
return features;
|
|
118
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* 计算音频特征
|
|
131
|
+
* @param audioPath WAV 音频文件路径
|
|
132
|
+
* @param windowSize 分析窗口大小(样本数)
|
|
133
|
+
* @param hopSize 窗口跳跃大小(样本数)
|
|
134
|
+
* @param onProgress 进度回调函数,参数为 0-1 之间的进度值
|
|
135
|
+
* @param options 可选配置项,包括是否使用 Worker 并行处理
|
|
136
|
+
*/
|
|
137
|
+
export async function analyzeAudio(audioPath, windowSize = 2048, hopSize = 512, onProgress, options) {
|
|
138
|
+
const { sampleRate, channelData } = await readWavFile(audioPath);
|
|
139
|
+
// 如果启用 Worker 并行处理
|
|
140
|
+
if (options?.useWorkers) {
|
|
141
|
+
return analyzeAudioParallel(channelData, sampleRate, windowSize, hopSize, onProgress, options.numWorkers);
|
|
142
|
+
}
|
|
143
|
+
// 默认使用单线程模式
|
|
144
|
+
return analyzeAudioSingleThread(channelData, sampleRate, windowSize, hopSize, onProgress);
|
|
145
|
+
}
|
|
119
146
|
/**
|
|
120
147
|
* 计算特征的统计信息(用于调试和阈值设定)
|
|
121
148
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audioAnalyzer.js","sourceRoot":"","sources":["../src/audioAnalyzer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,KAAK,UAAU,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"audioAnalyzer.js","sourceRoot":"","sources":["../src/audioAnalyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audioAnalyzer.worker.d.ts","sourceRoot":"","sources":["../src/audioAnalyzer.worker.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { parentPort } from "worker_threads";
|
|
2
|
+
import Meyda from "meyda";
|
|
3
|
+
/**
|
|
4
|
+
* 计算 RMS(均方根)
|
|
5
|
+
*/
|
|
6
|
+
function calculateRMS(samples) {
|
|
7
|
+
let sum = 0;
|
|
8
|
+
for (let i = 0; i < samples.length; i++) {
|
|
9
|
+
sum += samples[i] * samples[i];
|
|
10
|
+
}
|
|
11
|
+
return Math.sqrt(sum / samples.length);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* 计算过零率
|
|
15
|
+
*/
|
|
16
|
+
function calculateZCR(samples) {
|
|
17
|
+
let count = 0;
|
|
18
|
+
for (let i = 1; i < samples.length; i++) {
|
|
19
|
+
if ((samples[i] >= 0 && samples[i - 1] < 0) ||
|
|
20
|
+
(samples[i] < 0 && samples[i - 1] >= 0)) {
|
|
21
|
+
count++;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return count / samples.length;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 简单的 FFT 能量分布计算(高频能量)
|
|
28
|
+
*/
|
|
29
|
+
function calculateSpectralEnergy(samples) {
|
|
30
|
+
// 简化版:计算高频分量(通过差分近似)
|
|
31
|
+
let highFreqEnergy = 0;
|
|
32
|
+
for (let i = 1; i < samples.length; i++) {
|
|
33
|
+
const diff = samples[i] - samples[i - 1];
|
|
34
|
+
highFreqEnergy += diff * diff;
|
|
35
|
+
}
|
|
36
|
+
return highFreqEnergy / samples.length;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 计算方差
|
|
40
|
+
*/
|
|
41
|
+
function calculateVariance(samples, mean) {
|
|
42
|
+
let sum = 0;
|
|
43
|
+
for (let i = 0; i < samples.length; i++) {
|
|
44
|
+
const diff = samples[i] - mean;
|
|
45
|
+
sum += diff * diff;
|
|
46
|
+
}
|
|
47
|
+
return sum / samples.length;
|
|
48
|
+
}
|
|
49
|
+
if (!parentPort) {
|
|
50
|
+
throw new Error("This file must be run as a worker thread");
|
|
51
|
+
}
|
|
52
|
+
parentPort.on("message", (msg) => {
|
|
53
|
+
const { channelData, windowSize, hopSize, startIdx, endIdx, sampleRate } = msg;
|
|
54
|
+
const features = [];
|
|
55
|
+
const totalWindows = endIdx - startIdx;
|
|
56
|
+
try {
|
|
57
|
+
for (let i = startIdx; i < endIdx; i++) {
|
|
58
|
+
const start = i * hopSize;
|
|
59
|
+
const end = start + windowSize;
|
|
60
|
+
const window = channelData.slice(start, end);
|
|
61
|
+
const timestamp = start / sampleRate;
|
|
62
|
+
// 时域特征
|
|
63
|
+
const rms = calculateRMS(window);
|
|
64
|
+
const energy = rms * rms;
|
|
65
|
+
const zcr = calculateZCR(window);
|
|
66
|
+
const spectralEnergy = calculateSpectralEnergy(window);
|
|
67
|
+
// 计算方差
|
|
68
|
+
let mean = 0;
|
|
69
|
+
for (let j = 0; j < window.length; j++) {
|
|
70
|
+
mean += Math.abs(window[j]);
|
|
71
|
+
}
|
|
72
|
+
mean /= window.length;
|
|
73
|
+
const variance = calculateVariance(window, mean);
|
|
74
|
+
// 使用 Meyda 一次性提取多个特征(更高效)
|
|
75
|
+
const meydaFeatures = Meyda.extract(["mfcc", "spectralCentroid", "spectralRolloff", "spectralFlatness"], window);
|
|
76
|
+
const mfcc = meydaFeatures?.mfcc || new Array(13).fill(0);
|
|
77
|
+
const spectralCentroid = meydaFeatures?.spectralCentroid || 0;
|
|
78
|
+
const spectralRolloff = meydaFeatures?.spectralRolloff || 0;
|
|
79
|
+
const spectralFlatness = meydaFeatures?.spectralFlatness || 0;
|
|
80
|
+
features.push({
|
|
81
|
+
timestamp,
|
|
82
|
+
rms,
|
|
83
|
+
energy,
|
|
84
|
+
zcr,
|
|
85
|
+
spectralEnergy,
|
|
86
|
+
variance,
|
|
87
|
+
mfcc,
|
|
88
|
+
spectralCentroid,
|
|
89
|
+
spectralRolloff,
|
|
90
|
+
spectralFlatness,
|
|
91
|
+
});
|
|
92
|
+
// 发送进度更新(每 50 个窗口)
|
|
93
|
+
if ((i - startIdx) % 50 === 0) {
|
|
94
|
+
parentPort.postMessage({
|
|
95
|
+
type: "progress",
|
|
96
|
+
current: i - startIdx,
|
|
97
|
+
total: totalWindows,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// 发送最终结果
|
|
102
|
+
parentPort.postMessage({
|
|
103
|
+
type: "result",
|
|
104
|
+
features,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
// 发送错误信息
|
|
109
|
+
parentPort.postMessage({
|
|
110
|
+
type: "error",
|
|
111
|
+
error: error instanceof Error ? error.message : String(error),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
//# sourceMappingURL=audioAnalyzer.worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audioAnalyzer.worker.js","sourceRoot":"","sources":["../src/audioAnalyzer.worker.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { analyzeAudio, AudioFeatures, getFeatureStats, } from "./audioAnalyzer.js";
|
|
1
|
+
export { analyzeAudio, AudioFeatures, AnalyzeAudioOptions, getFeatureStats, } from "./audioAnalyzer.js";
|
|
2
2
|
export { detectMusicSegments, MusicSegment, DetectionConfig, } from "./segmentDetector.js";
|
|
3
3
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,mBAAmB,EACnB,YAAY,EACZ,eAAe,GAChB,MAAM,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,YAAY,EACZ,aAAa,EACb,mBAAmB,EACnB,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,mBAAmB,EACnB,YAAY,EACZ,eAAe,GAChB,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,OAAO,EACL,YAAY,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,OAAO,EACL,YAAY,EAGZ,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,mBAAmB,GAGpB,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { AudioFeatures } from "./audioAnalyzer.js";
|
|
2
|
+
export interface WorkerTask {
|
|
3
|
+
channelData: Float32Array;
|
|
4
|
+
windowSize: number;
|
|
5
|
+
hopSize: number;
|
|
6
|
+
startIdx: number;
|
|
7
|
+
endIdx: number;
|
|
8
|
+
sampleRate: number;
|
|
9
|
+
}
|
|
10
|
+
export interface WorkerResult {
|
|
11
|
+
features: AudioFeatures[];
|
|
12
|
+
workerId: number;
|
|
13
|
+
}
|
|
14
|
+
export interface WorkerPoolOptions {
|
|
15
|
+
numWorkers?: number;
|
|
16
|
+
onProgress?: (progress: number) => void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Worker 池管理器
|
|
20
|
+
* 用于并行处理音频特征提取
|
|
21
|
+
*/
|
|
22
|
+
export declare class WorkerPool {
|
|
23
|
+
private workers;
|
|
24
|
+
private numWorkers;
|
|
25
|
+
private workerPath;
|
|
26
|
+
constructor(options?: WorkerPoolOptions);
|
|
27
|
+
/**
|
|
28
|
+
* 执行并行音频分析
|
|
29
|
+
*/
|
|
30
|
+
execute(channelData: Float32Array, windowSize: number, hopSize: number, sampleRate: number, onProgress?: (progress: number) => void): Promise<AudioFeatures[]>;
|
|
31
|
+
/**
|
|
32
|
+
* 创建指定数量的 workers
|
|
33
|
+
*/
|
|
34
|
+
private createWorkers;
|
|
35
|
+
/**
|
|
36
|
+
* 执行所有任务
|
|
37
|
+
*/
|
|
38
|
+
private executeTasks;
|
|
39
|
+
/**
|
|
40
|
+
* 终止所有 workers
|
|
41
|
+
*/
|
|
42
|
+
private terminate;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=workerPool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workerPool.d.ts","sourceRoot":"","sources":["../src/workerPool.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAKxD,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,YAAY,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED;;;GAGG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,UAAU,CAAS;gBAEf,OAAO,GAAE,iBAAsB;IAM3C;;OAEG;IACG,OAAO,CACX,WAAW,EAAE,YAAY,EACzB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GACtC,OAAO,CAAC,aAAa,EAAE,CAAC;IA2C3B;;OAEG;IACH,OAAO,CAAC,aAAa;IAUrB;;OAEG;YACW,YAAY;IAyD1B;;OAEG;IACH,OAAO,CAAC,SAAS;CAMlB"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { Worker } from "worker_threads";
|
|
2
|
+
import { cpus } from "os";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
import path from "path";
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = path.dirname(__filename);
|
|
7
|
+
/**
|
|
8
|
+
* Worker 池管理器
|
|
9
|
+
* 用于并行处理音频特征提取
|
|
10
|
+
*/
|
|
11
|
+
export class WorkerPool {
|
|
12
|
+
workers = [];
|
|
13
|
+
numWorkers;
|
|
14
|
+
workerPath;
|
|
15
|
+
constructor(options = {}) {
|
|
16
|
+
// 默认使用 CPU 核心数,但不超过 8 个
|
|
17
|
+
this.numWorkers = options.numWorkers || Math.min(cpus().length, 8);
|
|
18
|
+
this.workerPath = path.join(__dirname, "audioAnalyzer.worker.js");
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 执行并行音频分析
|
|
22
|
+
*/
|
|
23
|
+
async execute(channelData, windowSize, hopSize, sampleRate, onProgress) {
|
|
24
|
+
const totalWindows = Math.floor((channelData.length - windowSize) / hopSize);
|
|
25
|
+
// 如果窗口数太少,不值得使用多个 worker
|
|
26
|
+
if (totalWindows < this.numWorkers * 10) {
|
|
27
|
+
this.numWorkers = Math.max(1, Math.floor(totalWindows / 10));
|
|
28
|
+
}
|
|
29
|
+
// 计算每个 worker 处理的窗口范围
|
|
30
|
+
const windowsPerWorker = Math.ceil(totalWindows / this.numWorkers);
|
|
31
|
+
const tasks = [];
|
|
32
|
+
for (let i = 0; i < this.numWorkers; i++) {
|
|
33
|
+
const startIdx = i * windowsPerWorker;
|
|
34
|
+
const endIdx = Math.min((i + 1) * windowsPerWorker, totalWindows);
|
|
35
|
+
if (startIdx >= totalWindows)
|
|
36
|
+
break;
|
|
37
|
+
tasks.push({
|
|
38
|
+
channelData,
|
|
39
|
+
windowSize,
|
|
40
|
+
hopSize,
|
|
41
|
+
startIdx,
|
|
42
|
+
endIdx,
|
|
43
|
+
sampleRate,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
// 创建 workers
|
|
47
|
+
this.createWorkers(tasks.length);
|
|
48
|
+
// 执行任务并收集结果
|
|
49
|
+
const results = await this.executeTasks(tasks, onProgress);
|
|
50
|
+
// 清理 workers
|
|
51
|
+
this.terminate();
|
|
52
|
+
// 按窗口索引排序并合并结果
|
|
53
|
+
return results.flatMap((r) => r.features);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* 创建指定数量的 workers
|
|
57
|
+
*/
|
|
58
|
+
createWorkers(count) {
|
|
59
|
+
for (let i = 0; i < count; i++) {
|
|
60
|
+
const worker = new Worker(this.workerPath, {
|
|
61
|
+
// 支持 ESM 模块
|
|
62
|
+
// Node.js 16+ 需要显式指定
|
|
63
|
+
});
|
|
64
|
+
this.workers.push(worker);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* 执行所有任务
|
|
69
|
+
*/
|
|
70
|
+
async executeTasks(tasks, onProgress) {
|
|
71
|
+
const progressMap = new Map();
|
|
72
|
+
const totalProgress = tasks.reduce((sum, t) => sum + (t.endIdx - t.startIdx), 0);
|
|
73
|
+
// 为每个 worker 分配任务并等待结果
|
|
74
|
+
const promises = tasks.map((task, idx) => {
|
|
75
|
+
return new Promise((resolve, reject) => {
|
|
76
|
+
const worker = this.workers[idx];
|
|
77
|
+
const handleMessage = (msg) => {
|
|
78
|
+
if (msg.type === "progress") {
|
|
79
|
+
// 更新进度
|
|
80
|
+
progressMap.set(idx, msg.current);
|
|
81
|
+
if (onProgress) {
|
|
82
|
+
const currentTotal = Array.from(progressMap.values()).reduce((sum, val) => sum + val, 0);
|
|
83
|
+
onProgress(currentTotal / totalProgress);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else if (msg.type === "result") {
|
|
87
|
+
worker.off("message", handleMessage);
|
|
88
|
+
worker.off("error", handleError);
|
|
89
|
+
resolve({
|
|
90
|
+
features: msg.features,
|
|
91
|
+
workerId: idx,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
else if (msg.type === "error") {
|
|
95
|
+
worker.off("message", handleMessage);
|
|
96
|
+
worker.off("error", handleError);
|
|
97
|
+
reject(new Error(`Worker ${idx} error: ${msg.error}`));
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
const handleError = (error) => {
|
|
101
|
+
worker.off("message", handleMessage);
|
|
102
|
+
worker.off("error", handleError);
|
|
103
|
+
reject(error);
|
|
104
|
+
};
|
|
105
|
+
worker.on("message", handleMessage);
|
|
106
|
+
worker.on("error", handleError);
|
|
107
|
+
// 发送任务
|
|
108
|
+
worker.postMessage(task);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
return Promise.all(promises);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* 终止所有 workers
|
|
115
|
+
*/
|
|
116
|
+
terminate() {
|
|
117
|
+
for (const worker of this.workers) {
|
|
118
|
+
worker.terminate();
|
|
119
|
+
}
|
|
120
|
+
this.workers = [];
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=workerPool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workerPool.js","sourceRoot":"","sources":["../src/workerPool.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED