Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions lib/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"rollup-plugin-web-worker-loader": "^1.6.0",
"ts-loader": "^8.0.17",
"tslib": "^2.1.0",
"typescript": "^4.1.5",
"typescript": "^4.6.2",
"worker-loader": "^3.0.8"
}
}
12 changes: 8 additions & 4 deletions lib/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,13 @@ export interface ServerMessageLoadResult {

export interface ServerMessageError {
event: "error";
recognizerId?: string;
error: string;
}

export interface ServerMessageResult {
event: "result";
recognizerId: string;
result: {
result: Array<{
conf: number;
Expand All @@ -111,6 +113,7 @@ export interface ServerMessageResult {
}
export interface ServerMessagePartialResult {
event: "partialresult";
recognizerId: string;
result: {
partial: string;
};
Expand All @@ -127,19 +130,20 @@ export namespace ModelMessage {
}
export type RecognizerMessage =
| ServerMessagePartialResult
| ServerMessageResult;
| ServerMessageResult
| ServerMessageError;

export type RecognizerEvent = RecognizerMessage["event"];

export type ServerMessage = ModelMessage | RecognizerMessage;

export namespace ServerMessage {
export function isRecognizerMessage(message: ServerMessage): boolean {
return ["result", "partialresult"].includes(message.event);
export function isRecognizerMessage(message: ServerMessage): message is RecognizerMessage {
return ["result", "partialresult"].includes(message.event) || Reflect.has(message, 'recognizerId');
}

export function isResult(message: any): message is ServerMessageResult {
return message?.result?.text != null;
return message?.result?.text != null || message?.result?.result != null;
}

export function isPartialResult(
Expand Down
33 changes: 27 additions & 6 deletions lib/src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export class Model extends EventTarget {
private _ready: boolean = false;
private messagePort: MessagePort;
private logger: Logger = new Logger();
private recognizers = new Map<string, KaldiRecognizer>();

constructor(private modelUrl: string, logLevel: number = 0) {
super();
Expand Down Expand Up @@ -51,7 +52,7 @@ export class Model extends EventTarget {

private postMessage<T = ClientMessage>(
message: T,
options?: PostMessageOptions
options?: StructuredSerializeOptions
) {
this.worker.postMessage(message, options);
}
Expand All @@ -63,7 +64,16 @@ export class Model extends EventTarget {
this._ready = message.result;
}

this.dispatchEvent(new CustomEvent(message.event, { detail: message }));
const event = new CustomEvent(message.event, { detail: message });
if (ServerMessage.isRecognizerMessage(message) && message.recognizerId) {
const recognizer = this.recognizers.get(message.recognizerId);
if (recognizer) {
recognizer.dispatchEvent(event);
return;
}
}

this.dispatchEvent(event);
}
}

Expand Down Expand Up @@ -115,6 +125,14 @@ export class Model extends EventTarget {
);
}

public registerRecognizer(recognizer: KaldiRecognizer) {
this.recognizers.set(recognizer.id, recognizer);
}

public unregisterRecognizer(recognizerId: string) {
this.recognizers.delete(recognizerId);
}

/**
* KaldiRecognizer anonymous class
*/
Expand All @@ -129,6 +147,9 @@ export class Model extends EventTarget {
"Cannot create KaldiRecognizer. Model is either not ready or has been terminated"
);
}

model.registerRecognizer(this);

model.postMessage<ClientMessageCreateRecognizer>({
action: "create",
recognizerId: this.id,
Expand All @@ -141,10 +162,8 @@ export class Model extends EventTarget {
event: RecognizerEvent,
listener: (message: RecognizerMessage) => void
) {
model.addEventListener(event, (event: any) => {
if (event.detail && ServerMessage.isRecognizerMessage(event.detail)) {
listener(event.detail);
}
this.addEventListener(event, (event: any) => {
listener(event?.detail);
});
}

Expand Down Expand Up @@ -193,6 +212,8 @@ export class Model extends EventTarget {
}

public remove(): void {
model.unregisterRecognizer(this.id);

model.postMessage<ClientMessageRemoveRecognizer>({
action: "remove",
recognizerId: this.id,
Expand Down
32 changes: 16 additions & 16 deletions lib/src/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export class RecognizerWorker {

if (!modelUrl) {
ctx.postMessage({
event: "error",
error: "Missing modelUrl parameter",
});
}
Expand All @@ -53,7 +54,7 @@ export class RecognizerWorker {
})
.catch((error) => {
this.logger.error(error);
ctx.postMessage({ error: error.message });
ctx.postMessage({ event: "error", error: error.message });
});

return;
Expand All @@ -69,7 +70,7 @@ export class RecognizerWorker {
.then((result) => {
ctx.postMessage(result);
})
.catch((error) => ctx.postMessage({ event: "error", error }));
.catch((error) => ctx.postMessage({ event: "error", recognizerId: message.recognizerId, error: error.message }));
return;
}

Expand All @@ -78,7 +79,7 @@ export class RecognizerWorker {
.then((result) => {
ctx.postMessage(result);
})
.catch((error) => ctx.postMessage({ event: "error", error }));
.catch((error) => ctx.postMessage({ event: "error", recognizerId: message.recognizerId, error: error.message }));
return;
}

Expand All @@ -87,7 +88,7 @@ export class RecognizerWorker {
.then((result) => {
ctx.postMessage(result);
})
.catch((error) => ctx.postMessage({ event: "error", error }));
.catch((error) => ctx.postMessage({ event: "error", recognizerId: message.recognizerId, error: error.message }));
return;
}

Expand All @@ -96,7 +97,7 @@ export class RecognizerWorker {
return;
}

ctx.postMessage({ error: `Unknown message ${JSON.stringify(message)}` });
ctx.postMessage({ event: "error", error: `Unknown message ${JSON.stringify(message)}` });
}

private async load(modelUrl: string): Promise<boolean> {
Expand All @@ -110,6 +111,7 @@ export class RecognizerWorker {
})
.catch((e) => {
this.logger.error(e);
reject(e);
})
)
.then(() => {
Expand Down Expand Up @@ -196,9 +198,7 @@ export class RecognizerWorker {
} catch (error) {
const errorMsg = `Recognizer (id: ${recognizerId}): Could not be created due to: ${error}\n${(error as Error)?.stack}`;
this.logger.error(errorMsg);
return {
error: errorMsg,
};
throw new Error(errorMsg);
}
}

Expand Down Expand Up @@ -242,10 +242,8 @@ export class RecognizerWorker {
);

if (!this.recognizers.has(recognizerId)) {
this.logger.warn(`Recognizer not ready, ignoring`);
return {
error: `Recognizer (id: ${recognizerId}): Not ready`,
};
this.logger.error(`Recognizer (id: ${recognizerId}) not ready, ignoring`);
throw new Error(`Recognizer (id: ${recognizerId}): Not ready`);
}

let recognizer = this.recognizers.get(recognizerId)!;
Expand Down Expand Up @@ -275,9 +273,7 @@ export class RecognizerWorker {
if (recognizer.buffAddr == null) {
const error = `Recognizer (id: ${recognizer.id}): Could not allocate buffer`;
this.logger.error(error);
return {
error
};
throw new Error(error);
}

this.Vosk.HEAPF32.set(data, recognizer.buffAddr / data.BYTES_PER_ELEMENT);
Expand Down Expand Up @@ -327,7 +323,11 @@ export class RecognizerWorker {

private async terminate() {
for (const recognizer of this.recognizers.values()) {
await this.removeRecognizer(recognizer.id);
try {
await this.removeRecognizer(recognizer.id);
} catch (error) {
this.logger.warn(`Recognizer (id: ${recognizer.id}) could not be removed. Ignoring as we are terminating.`)
}
}
this.model.delete();
close();
Expand Down