SpeakerIdentificationWorker.ets
4.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import worker, { ErrorEvent, MessageEvents, ThreadWorkerGlobalScope } from '@ohos.worker';
import {
OnlineStream,
readWaveFromBinary,
Samples,
SpeakerEmbeddingExtractor,
SpeakerEmbeddingExtractorConfig,
SpeakerEmbeddingManager
} from 'sherpa_onnx';
const workerPort: ThreadWorkerGlobalScope = worker.workerPort;
let extractor: SpeakerEmbeddingExtractor;
let manager: SpeakerEmbeddingManager;
function readWaveFromRawfile(filename: string, context: Context): Samples {
const data: Uint8Array = context.resourceManager.getRawFileContentSync(filename);
return readWaveFromBinary(data) as Samples;
}
function initExtractor(context: Context): SpeakerEmbeddingExtractor {
const config: SpeakerEmbeddingExtractorConfig = new SpeakerEmbeddingExtractorConfig();
// Please put the model file inside the directory
// harmony-os/SherpaOnnxSpeakerIdentification/entry/src/main/resources/rawfile
/*
(py38) fangjuns-MacBook-Pro:rawfile fangjun$ pwd
/Users/fangjun/open-source/sherpa-onnx/harmony-os/SherpaOnnxSpeakerIdentification/entry/src/main/resources/rawfile
(py38) fangjuns-MacBook-Pro:rawfile fangjun$ ls -lh
total 77336
-rw-r--r-- 1 fangjun staff 38M Dec 9 19:34 3dspeaker_speech_eres2net_base_sv_zh-cn_3dspeaker_16k.onnx
*/
// You can find more models at
// https://github.com/k2-fsa/sherpa-onnx/releases/tag/speaker-recongition-models
config.model = '3dspeaker_speech_eres2net_base_sv_zh-cn_3dspeaker_16k.onnx';
config.numThreads = 2;
config.debug = true;
return new SpeakerEmbeddingExtractor(config, context.resourceManager);
}
function extractEmbedding(samples: Samples): Float32Array {
const stream: OnlineStream = extractor.createStream();
stream.acceptWaveform(samples);
return extractor.compute(stream);
}
/**
* Defines the event handler to be called when the worker thread receives a message sent by the host thread.
* The event handler is executed in the worker thread.
*
* @param e message data
*/
workerPort.onmessage = (e: MessageEvents) => {
const msgType = e.data['msgType'] as string;
console.log(`from the main thread, msg-type: ${msgType}`);
if (msgType == 'init-extractor' && !extractor) {
const context: Context = e.data['context'] as Context;
extractor = initExtractor(context);
manager = new SpeakerEmbeddingManager(extractor.dim);
workerPort.postMessage({
msgType: 'manager-all-speaker-names', allSpeakers: manager.getAllSpeakerNames(),
});
}
if (msgType == 'manager-delete-speaker') {
const name = e.data['name'] as string;
const ok: boolean = manager.remove(name);
if (ok) {
console.log(`Removed ${name}.`);
console.log(`Number of speakers: ${manager.getNumSpeakers()}`);
console.log(`Number of speakers2: ${manager.getAllSpeakerNames().length}`);
console.log(JSON.stringify(manager.getAllSpeakerNames()));
workerPort.postMessage({
msgType: 'manager-all-speaker-names', allSpeakers: manager.getAllSpeakerNames(),
});
}
}
if (msgType == 'manager-add-speaker') {
const name = e.data['name'] as string;
const samples = e.data['samples'] as Float32Array;
const sampleRate = e.data['sampleRate'] as number;
const v = extractEmbedding({ samples, sampleRate });
const ok: boolean = manager.add({ name, v });
if (ok) {
workerPort.postMessage({
msgType: 'manager-add-speaker-done',
status: `Added ${name}`,
ok,
});
workerPort.postMessage({
msgType: 'manager-all-speaker-names', allSpeakers: manager.getAllSpeakerNames(),
}
);
} else {
workerPort.postMessage({
msgType: 'manager-add-speaker-done',
status: `Failed to add ${name}. Possibly due to exsiting speaker name. Please recheck`,
ok,
});
}
}
if (msgType == 'manager-search-speaker') {
const threshold = e.data['threshold'] as number;
const samples = e.data['samples'] as Float32Array;
const sampleRate = e.data['sampleRate'] as number;
const v = extractEmbedding({ samples, sampleRate });
let name: string = manager.search({ threshold, v });
if (name == '' || name == undefined) {
name = "===<Unknown>===";
}
workerPort.postMessage({
msgType: 'manager-search-speaker-done',
name
});
}
}
/**
* Defines the event handler to be called when the worker receives a message that cannot be deserialized.
* The event handler is executed in the worker thread.
*
* @param e message data
*/
workerPort.onmessageerror = (e: MessageEvents) => {
}
/**
* Defines the event handler to be called when an exception occurs during worker execution.
* The event handler is executed in the worker thread.
*
* @param e error message
*/
workerPort.onerror = (e: ErrorEvent) => {
}