echogarden 0.11.12 → 0.11.13

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 (122) hide show
  1. package/data/schemas/options.json +16 -0
  2. package/dist/api/Alignment.js +2 -2
  3. package/dist/api/Alignment.js.map +1 -1
  4. package/dist/api/Recognition.js +2 -2
  5. package/dist/api/Recognition.js.map +1 -1
  6. package/dist/api/Synthesis.js +5 -4
  7. package/dist/api/Synthesis.js.map +1 -1
  8. package/dist/api/Translation.js +2 -2
  9. package/dist/api/Translation.js.map +1 -1
  10. package/dist/audio/AudioUtilities.d.ts +1 -0
  11. package/dist/audio/AudioUtilities.js +25 -7
  12. package/dist/audio/AudioUtilities.js.map +1 -1
  13. package/dist/cli/CLI.js +2 -2
  14. package/dist/cli/CLI.js.map +1 -1
  15. package/dist/recognition/WhisperSTT.js +2 -2
  16. package/dist/recognition/WhisperSTT.js.map +1 -1
  17. package/dist/subtitles/Subtitles.d.ts +10 -7
  18. package/dist/subtitles/Subtitles.js +268 -207
  19. package/dist/subtitles/Subtitles.js.map +1 -1
  20. package/docs/Options.md +4 -2
  21. package/package.json +7 -6
  22. package/src/alignment/DTWMfccSequenceAlignment.ts +43 -0
  23. package/src/alignment/DTWSequenceAlignment.ts +121 -0
  24. package/src/alignment/DTWSequenceAlignmentWindowed.ts +210 -0
  25. package/src/alignment/LevenshteinSequenceAlignment.ts +126 -0
  26. package/src/alignment/SpeechAlignment.ts +488 -0
  27. package/src/api/API.ts +12 -0
  28. package/src/api/APIOptions.ts +15 -0
  29. package/src/api/Alignment.ts +329 -0
  30. package/src/api/Common.ts +16 -0
  31. package/src/api/Denoising.ts +120 -0
  32. package/src/api/LanguageDetection.ts +286 -0
  33. package/src/api/Recognition.ts +344 -0
  34. package/src/api/Synthesis.ts +1735 -0
  35. package/src/api/Translation.ts +143 -0
  36. package/src/api/Vad.ts +172 -0
  37. package/src/audio/AudioBufferConversion.ts +248 -0
  38. package/src/audio/AudioPlayer.ts +358 -0
  39. package/src/audio/AudioRecorder.ts +91 -0
  40. package/src/audio/AudioUtilities.ts +392 -0
  41. package/src/audio/SoxPath.ts +24 -0
  42. package/src/cli/CLI.ts +1360 -0
  43. package/src/cli/CLIConfigFile.ts +91 -0
  44. package/src/cli/CLILauncher.ts +26 -0
  45. package/src/cli/CLIOptionsSchema.ts +54 -0
  46. package/src/cli/CLIParser.ts +41 -0
  47. package/src/cli/CLIStarter.ts +40 -0
  48. package/src/codecs/FFMpegTranscoder.ts +214 -0
  49. package/src/codecs/TIMITCodec.ts +17 -0
  50. package/src/codecs/WaveCodec.ts +260 -0
  51. package/src/denoising/RNNoise.ts +95 -0
  52. package/src/dsp/BiquadFilter.ts +488 -0
  53. package/src/dsp/FFT.ts +187 -0
  54. package/src/dsp/MFCC.ts +227 -0
  55. package/src/dsp/MelSpectogram.ts +145 -0
  56. package/src/dsp/Rubberband.ts +249 -0
  57. package/src/dsp/Sonic.ts +59 -0
  58. package/src/dsp/SpeexResampler.ts +79 -0
  59. package/src/math/VectorMath.ts +812 -0
  60. package/src/nlp/ChineseSegmentation.ts +68 -0
  61. package/src/nlp/CompromiseNLP.ts +113 -0
  62. package/src/nlp/EspeakPhonemizer.ts +168 -0
  63. package/src/nlp/IPA.ts +139 -0
  64. package/src/nlp/JapaneseSegmentation.ts +53 -0
  65. package/src/nlp/Lexicon.ts +119 -0
  66. package/src/nlp/PhoneConversion.ts +508 -0
  67. package/src/nlp/Segmentation.ts +237 -0
  68. package/src/nlp/TextNormalizer.ts +160 -0
  69. package/src/recognition/AmazonTranscribeSTT.ts +112 -0
  70. package/src/recognition/AzureCognitiveServicesSTT.ts +76 -0
  71. package/src/recognition/GoogleCloudSTT.ts +92 -0
  72. package/src/recognition/SileroSTT.ts +173 -0
  73. package/src/recognition/VoskSTT.ts +112 -0
  74. package/src/recognition/WhisperSTT.ts +1518 -0
  75. package/src/server/Client.ts +297 -0
  76. package/src/server/Server.ts +178 -0
  77. package/src/server/ServerStarter.ts +12 -0
  78. package/src/server/Worker.ts +400 -0
  79. package/src/server/WorkerStarter.ts +38 -0
  80. package/src/speech-language-detection/SileroLanguageDetection.ts +105 -0
  81. package/src/subtitles/Subtitles.ts +478 -0
  82. package/src/synthesis/AwsPollyTTS.ts +78 -0
  83. package/src/synthesis/AzureCognitiveServicesTTS.ts +146 -0
  84. package/src/synthesis/CoquiServerTTS.ts +29 -0
  85. package/src/synthesis/ElevenLabsTTS.ts +104 -0
  86. package/src/synthesis/EspeakTTS.ts +552 -0
  87. package/src/synthesis/FliteTTS.ts +387 -0
  88. package/src/synthesis/GoogleCloudTTS.ts +112 -0
  89. package/src/synthesis/GoogleTranslateTTS.ts +210 -0
  90. package/src/synthesis/MicrosoftEdgeTTS.ts +298 -0
  91. package/src/synthesis/SamTTS.ts +30 -0
  92. package/src/synthesis/SapiTTS.ts +222 -0
  93. package/src/synthesis/StreamlabsPollyTTS.ts +114 -0
  94. package/src/synthesis/SvoxPicoTTS.ts +318 -0
  95. package/src/synthesis/VitsTTS.ts +734 -0
  96. package/src/tests/Test.ts +24 -0
  97. package/src/text-language-detection/FastTextLanguageDetection.ts +53 -0
  98. package/src/text-language-detection/TinyLDLanguageDetection.ts +16 -0
  99. package/src/typings/Fillers.d.ts +41 -0
  100. package/src/utilities/BinaryArrayConversion.ts +159 -0
  101. package/src/utilities/Compression.ts +91 -0
  102. package/src/utilities/FileDownloader.ts +201 -0
  103. package/src/utilities/FileSystem.ts +265 -0
  104. package/src/utilities/Hashing.ts +230 -0
  105. package/src/utilities/Locale.ts +119 -0
  106. package/src/utilities/Logger.ts +72 -0
  107. package/src/utilities/NdArrayUtilities.ts +31 -0
  108. package/src/utilities/ObjectUtilities.ts +169 -0
  109. package/src/utilities/OpenPromise.ts +13 -0
  110. package/src/utilities/PackageManager.ts +97 -0
  111. package/src/utilities/Queue.ts +17 -0
  112. package/src/utilities/RandomGenerator.ts +237 -0
  113. package/src/utilities/SignalChannel.ts +22 -0
  114. package/src/utilities/TarballMaker.ts +68 -0
  115. package/src/utilities/Timeline.ts +231 -0
  116. package/src/utilities/Timer.ts +93 -0
  117. package/src/utilities/Utilities.ts +574 -0
  118. package/src/utilities/WasmMemoryManager.ts +516 -0
  119. package/src/utilities/WebReader.ts +55 -0
  120. package/src/utilities/WikipediaReader.ts +41 -0
  121. package/src/voice-activity-detection/SileroVAD.ts +86 -0
  122. package/src/voice-activity-detection/WebRtcVAD.ts +76 -0
@@ -0,0 +1,297 @@
1
+ import { WebSocket } from 'ws'
2
+ import { encode as encodeMsgPack, decode as decodeMsgPack } from 'msgpack-lite'
3
+ import { RequestVoiceListResult, SynthesisOptions, SynthesisSegmentEvent, SynthesisResult, VoiceListRequestOptions } from "../api/Synthesis.js"
4
+ import { SynthesisResponseMessage, SynthesisSegmentEventMessage, SynthesisSentenceEventMessage, VoiceListRequestMessage, WorkerRequestMessage, VoiceListResponseMessage, AlignmentRequestMessage, AlignmentResponseMessage, RecognitionRequestMessage, RecognitionResponseMessage, SpeechTranslationRequestMessage, SpeechTranslationResponseMessage, SpeechLanguageDetectionRequestMessage, SpeechLanguageDetectionResponseMessage, TextLanguageDetectionResponseMessage, TextLanguageDetectionRequestMessage, SynthesisRequestMessage } from './Worker.js'
5
+ import { getRandomHexString, logToStderr } from '../utilities/Utilities.js'
6
+ import { OpenPromise } from '../utilities/OpenPromise.js'
7
+ import { AudioSourceParam, RawAudio } from '../audio/AudioUtilities.js'
8
+ import { AlignmentOptions, AlignmentResult } from '../api/Alignment.js'
9
+ import { RecognitionOptions, RecognitionResult } from '../api/Recognition.js'
10
+ import { SpeechTranslationOptions, SpeechTranslationResult } from '../api/Translation.js'
11
+ import { Worker as WorkerThread } from 'node:worker_threads'
12
+ import { SpeechLanguageDetectionOptions, SpeechLanguageDetectionResult, TextLanguageDetectionOptions, TextLanguageDetectionResult } from '../api/LanguageDetection.js'
13
+
14
+ const log = logToStderr
15
+
16
+ export class Client {
17
+ sendMessage: (message: any) => void
18
+
19
+ responseListeners = new Map<string, (message: string) => void>()
20
+
21
+ constructor(sourceChannel: WebSocket | WorkerThread) {
22
+ if (sourceChannel instanceof WebSocket) {
23
+ sourceChannel.on("message", (messageData, isBinary) => {
24
+ if (!isBinary) {
25
+ log(`Received an unexpected string WebSocket message: '${(messageData as Buffer).toString("utf-8")}'`)
26
+ return
27
+ }
28
+
29
+ let incomingMessage: any
30
+
31
+ try {
32
+ incomingMessage = decodeMsgPack(messageData as Buffer)
33
+ } catch (e) {
34
+ log(`Failed to decode incoming message. Reason: ${e}`)
35
+ return
36
+ }
37
+
38
+ this.onMessage(incomingMessage)
39
+ })
40
+
41
+ this.sendMessage = (outgoingMessage) => {
42
+ const encodedMessage = encodeMsgPack(outgoingMessage)
43
+
44
+ sourceChannel.send(encodedMessage)
45
+ }
46
+ } else if (sourceChannel instanceof WorkerThread) {
47
+ sourceChannel.on("message", (message) => {
48
+ this.onMessage(message)
49
+ })
50
+
51
+ sourceChannel.on("error", (e) => {
52
+ throw e
53
+ })
54
+
55
+ this.sendMessage = (outgoingMessage) => {
56
+ sourceChannel.postMessage(outgoingMessage)
57
+ }
58
+ } else {
59
+ throw new Error(`Invalid source: not a WebSocket or WorkerThread object`)
60
+ }
61
+ }
62
+
63
+ async synthesize(input: string | string[], options: SynthesisOptions, onSegment?: SynthesisSegmentEvent, onSentence?: SynthesisSegmentEvent): Promise<SynthesisResult> {
64
+ const requestOpenPromise = new OpenPromise<SynthesisResult>()
65
+
66
+ const requestMessage: SynthesisRequestMessage = {
67
+ messageType: "SynthesisRequest",
68
+ input,
69
+ options
70
+ }
71
+
72
+ function onResponse(responseMessage: SynthesisResponseMessage | SynthesisSegmentEventMessage | SynthesisSentenceEventMessage) {
73
+ if (responseMessage.messageType == "SynthesisResponse") {
74
+ requestOpenPromise.resolve(responseMessage)
75
+ } else if (responseMessage.messageType == "SynthesisSegmentEvent" && onSegment) {
76
+ onSegment(responseMessage)
77
+ } else if (responseMessage.messageType == "SynthesisSentenceEvent" && onSentence) {
78
+ onSentence(responseMessage)
79
+ }
80
+ }
81
+
82
+ function onError(e: any) {
83
+ requestOpenPromise.reject(e)
84
+ }
85
+
86
+ try {
87
+ this.sendRequest(requestMessage, onResponse, onError)
88
+ } catch (e) {
89
+ onError(e)
90
+ }
91
+
92
+ return requestOpenPromise.promise
93
+ }
94
+
95
+ async requestVoiceList(options: VoiceListRequestOptions): Promise<RequestVoiceListResult> {
96
+ const requestOpenPromise = new OpenPromise<RequestVoiceListResult>()
97
+
98
+ const requestMessage: VoiceListRequestMessage = {
99
+ messageType: "VoiceListRequest",
100
+ options
101
+ }
102
+
103
+ function onResponse(responseMessage: VoiceListResponseMessage) {
104
+ if (responseMessage.messageType == "VoiceListResponse") {
105
+ requestOpenPromise.resolve(responseMessage)
106
+ }
107
+ }
108
+
109
+ function onError(e: any) {
110
+ requestOpenPromise.reject(e)
111
+ }
112
+
113
+ try {
114
+ this.sendRequest(requestMessage, onResponse, onError)
115
+ } catch (e) {
116
+ onError(e)
117
+ }
118
+
119
+ return requestOpenPromise.promise
120
+ }
121
+
122
+ async recognize(input: AudioSourceParam, options: RecognitionOptions): Promise<RecognitionResult> {
123
+ const requestOpenPromise = new OpenPromise<RecognitionResult>()
124
+
125
+ const requestMessage: RecognitionRequestMessage = {
126
+ messageType: "RecognitionRequest",
127
+ input,
128
+ options
129
+ }
130
+
131
+ function onResponse(responseMessage: RecognitionResponseMessage) {
132
+ if (responseMessage.messageType == "RecognitionResponse") {
133
+ requestOpenPromise.resolve(responseMessage)
134
+ }
135
+ }
136
+
137
+ function onError(e: any) {
138
+ requestOpenPromise.reject(e)
139
+ }
140
+
141
+ try {
142
+ this.sendRequest(requestMessage, onResponse, onError)
143
+ } catch (e) {
144
+ onError(e)
145
+ }
146
+ return requestOpenPromise.promise
147
+ }
148
+
149
+ async align(input: AudioSourceParam, transcript: string, options: AlignmentOptions): Promise<AlignmentResult> {
150
+ const requestOpenPromise = new OpenPromise<AlignmentResult>()
151
+
152
+ const requestMessage: AlignmentRequestMessage = {
153
+ messageType: "AlignmentRequest",
154
+ input,
155
+ transcript,
156
+ options
157
+ }
158
+
159
+ function onResponse(responseMessage: AlignmentResponseMessage) {
160
+ if (responseMessage.messageType == "AlignmentResponse") {
161
+ requestOpenPromise.resolve(responseMessage)
162
+ }
163
+ }
164
+
165
+ function onError(e: any) {
166
+ requestOpenPromise.reject(e)
167
+ }
168
+
169
+ try {
170
+ this.sendRequest(requestMessage, onResponse, onError)
171
+ } catch (e) {
172
+ onError(e)
173
+ }
174
+
175
+ return requestOpenPromise.promise
176
+ }
177
+
178
+ async translateSpeech(input: string | Buffer | Uint8Array |RawAudio, options: SpeechTranslationOptions): Promise<SpeechTranslationResult> {
179
+ const requestOpenPromise = new OpenPromise<SpeechTranslationResult>()
180
+
181
+ const requestMessage: SpeechTranslationRequestMessage = {
182
+ messageType: "SpeechTranslationRequest",
183
+ input,
184
+ options
185
+ }
186
+
187
+ function onResponse(responseMessage: SpeechTranslationResponseMessage) {
188
+ if (responseMessage.messageType == "SpeechTranslationResponse") {
189
+ requestOpenPromise.resolve(responseMessage)
190
+ }
191
+ }
192
+
193
+ function onError(e: any) {
194
+ requestOpenPromise.reject(e)
195
+ }
196
+
197
+ try {
198
+ this.sendRequest(requestMessage, onResponse, onError)
199
+ } catch (e) {
200
+ onError(e)
201
+ }
202
+
203
+ return requestOpenPromise.promise
204
+ }
205
+
206
+ async detectSpeechLanguage(input: AudioSourceParam, options: SpeechLanguageDetectionOptions): Promise<SpeechLanguageDetectionResult> {
207
+ const requestOpenPromise = new OpenPromise<SpeechLanguageDetectionResult>()
208
+
209
+ const requestMessage: SpeechLanguageDetectionRequestMessage = {
210
+ messageType: "SpeechLanguageDetectionRequest",
211
+ input,
212
+ options
213
+ }
214
+
215
+ function onResponse(responseMessage: SpeechLanguageDetectionResponseMessage) {
216
+ if (responseMessage.messageType == "SpeechLanguageDetectionResponse") {
217
+ requestOpenPromise.resolve(responseMessage)
218
+ }
219
+ }
220
+
221
+ function onError(e: any) {
222
+ requestOpenPromise.reject(e)
223
+ }
224
+
225
+ try {
226
+ this.sendRequest(requestMessage, onResponse, onError)
227
+ } catch (e) {
228
+ onError(e)
229
+ }
230
+
231
+ return requestOpenPromise.promise
232
+ }
233
+
234
+ async detectTextLanguage(input: string, options: TextLanguageDetectionOptions): Promise<TextLanguageDetectionResult> {
235
+ const requestOpenPromise = new OpenPromise<TextLanguageDetectionResult>()
236
+
237
+ const requestMessage: TextLanguageDetectionRequestMessage = {
238
+ messageType: "TextLanguageDetectionRequest",
239
+ input,
240
+ options
241
+ }
242
+
243
+ function onResponse(responseMessage: TextLanguageDetectionResponseMessage) {
244
+ if (responseMessage.messageType == "TextLanguageDetectionResponse") {
245
+ requestOpenPromise.resolve(responseMessage)
246
+ }
247
+ }
248
+
249
+ function onError(e: any) {
250
+ requestOpenPromise.reject(e)
251
+ }
252
+
253
+ try {
254
+ this.sendRequest(requestMessage, onResponse, onError)
255
+ } catch (e) {
256
+ onError(e)
257
+ }
258
+
259
+ return requestOpenPromise.promise
260
+ }
261
+
262
+ sendRequest(request: any, onResponse: (message: any) => void, onErrorResponse: (error: any) => void) {
263
+ const requestId = getRandomHexString()
264
+
265
+ request = {
266
+ requestId,
267
+ ...request
268
+ }
269
+
270
+ this.sendMessage(request)
271
+
272
+ function onResponseMessage(message: any) {
273
+ if (message.messageType == "Error") {
274
+ onErrorResponse(message.error)
275
+ } else {
276
+ onResponse(message)
277
+ }
278
+ }
279
+
280
+ this.responseListeners.set(requestId, onResponseMessage)
281
+ }
282
+
283
+ onMessage(incomingMessage: any) {
284
+ const requestId = incomingMessage.requestId
285
+
286
+ if (!requestId) {
287
+ log("Received a WebSocket message without a request ID")
288
+ return
289
+ }
290
+
291
+ const listener = this.responseListeners.get(requestId)
292
+
293
+ if (listener) {
294
+ listener(incomingMessage)
295
+ }
296
+ }
297
+ }
@@ -0,0 +1,178 @@
1
+ import { WebSocketServer, WebSocket, ServerOptions as WsServerOptions } from 'ws'
2
+ import { encode as encodeMsgPack, decode as decodeMsgPack } from 'msgpack-lite'
3
+ import { logToStderr } from '../utilities/Utilities.js'
4
+ import { OpenPromise } from '../utilities/OpenPromise.js'
5
+ import { readFile, existsSync } from '../utilities/FileSystem.js'
6
+ import { extendDeep } from '../utilities/ObjectUtilities.js'
7
+ import { sendMessageToWorker, addListenerToWorkerMessages, startNewWorkerThread } from './Worker.js'
8
+ import { Worker } from 'node:worker_threads'
9
+ import { IncomingMessage, ServerResponse } from 'node:http'
10
+ import { Logger } from '../utilities/Logger.js'
11
+ import chalk from 'chalk'
12
+
13
+ const log = logToStderr
14
+
15
+ export async function startServer(serverOptions: ServerOptions, onStarted: (options: ServerOptions) => void) {
16
+ serverOptions = extendDeep(defaultServerOptions, serverOptions)
17
+
18
+ const wsServerOptions: WsServerOptions = {
19
+ perMessageDeflate: serverOptions.deflate,
20
+ maxPayload: serverOptions.maxPayload
21
+ }
22
+
23
+ function onHttpRequest(request: IncomingMessage, response: ServerResponse) {
24
+ response.writeHead(200, { 'Content-Type': 'text/plain' })
25
+ response.end("This is the Echogarden HTTP server!")
26
+ }
27
+
28
+ if (serverOptions.secure) {
29
+ if (!serverOptions.certPath || !existsSync(serverOptions.certPath)) {
30
+ throw new Error(`No valid certificate file path was given`)
31
+ }
32
+
33
+ if (!serverOptions.keyPath || !existsSync(serverOptions.keyPath)) {
34
+ throw new Error(`No valid key file path was given`)
35
+ }
36
+
37
+ const { createServer } = await import('https')
38
+
39
+ const httpsServer = createServer({
40
+ cert: await readFile(serverOptions.certPath!),
41
+ key: await readFile(serverOptions.keyPath!)
42
+ }, onHttpRequest)
43
+
44
+ httpsServer.listen(serverOptions.port!)
45
+
46
+ wsServerOptions.server = httpsServer
47
+ } else {
48
+ const { createServer } = await import('http')
49
+
50
+ const httpServer = createServer({}, onHttpRequest)
51
+
52
+ httpServer.listen(serverOptions.port)
53
+
54
+ wsServerOptions.server = httpServer
55
+ }
56
+
57
+ const wss = new WebSocketServer(wsServerOptions)
58
+
59
+ const requestIdToWebSocket = new Map<string, WebSocket>()
60
+
61
+ function onWorkerMessage(message: any) {
62
+ if (message.name == "writeToStdErr") {
63
+ return
64
+ }
65
+
66
+ // Remove input raw audio property from message, if exists, when using WebSocket protocol:
67
+ message['inputRawAudio'] = undefined
68
+
69
+ if (!message.requestId) {
70
+ throw new Error("Worker message doesn't have a request ID")
71
+ }
72
+
73
+ const ws = requestIdToWebSocket.get(message.requestId)
74
+
75
+ if (!ws || ws.readyState != WebSocket.OPEN) {
76
+ return
77
+ }
78
+
79
+ const encodedWorkerMessage = encodeMsgPack(message)
80
+
81
+ ws.send(encodedWorkerMessage)
82
+ }
83
+
84
+ let workerThread: Worker | undefined
85
+
86
+ if (serverOptions.useWorkerThread) {
87
+ workerThread = await startNewWorkerThread()
88
+ workerThread.on('message', onWorkerMessage)
89
+ } else {
90
+ addListenerToWorkerMessages(onWorkerMessage)
91
+ }
92
+
93
+ const serverOpenPromise = new OpenPromise<void>
94
+
95
+ wss.on("listening", () => {
96
+ log(chalk.gray(`Started Echogarden WebSocket server on port ${serverOptions.port}`))
97
+ onStarted(serverOptions)
98
+ })
99
+
100
+ wss.on("close", () => {
101
+ serverOpenPromise.resolve()
102
+ })
103
+
104
+ wss.on('connection', async (ws, req) => {
105
+ log(chalk.gray((`Accepted incoming connection from ${req.socket.remoteAddress}`)))
106
+
107
+ ws.on('message', (messageData, isBinary) => {
108
+ if (!isBinary) {
109
+ log(chalk.gray((`Received an unexpected string WebSocket message: '${(messageData as Buffer).toString("utf-8")}'`)))
110
+ return
111
+ }
112
+
113
+ let incomingMessage: any
114
+
115
+ try {
116
+ incomingMessage = decodeMsgPack(messageData as Buffer)
117
+ } catch (e) {
118
+ log(chalk.gray(`Failed to decode binary WebSocket message. Reason: ${e}`))
119
+ return
120
+ }
121
+
122
+ const requestId = incomingMessage.requestId
123
+
124
+ if (!requestId) {
125
+ log(chalk.gray(("Received a WebSocket message without a request ID")))
126
+ return
127
+ }
128
+
129
+ requestIdToWebSocket.set(requestId, ws)
130
+
131
+ if (workerThread) {
132
+ workerThread.postMessage(incomingMessage)
133
+ } else {
134
+ sendMessageToWorker(incomingMessage)
135
+ }
136
+ })
137
+
138
+ ws.on('error', (e) => {
139
+ log(`${chalk.redBright('WebSocket error')}: ${e.message}`)
140
+ })
141
+
142
+ ws.on("close", () => {
143
+ const keysToDelete: string[] = []
144
+
145
+ requestIdToWebSocket.forEach((value, key) => {
146
+ if (value == ws) {
147
+ keysToDelete.push(key)
148
+ }
149
+ })
150
+
151
+ keysToDelete.forEach(key => requestIdToWebSocket.delete(key))
152
+
153
+ log(chalk.gray((`Incoming connection from ${ req.socket.remoteAddress } was closed`)))
154
+ })
155
+ })
156
+
157
+ return serverOpenPromise.promise
158
+ }
159
+
160
+ export interface ServerOptions {
161
+ port?: number
162
+ secure?: boolean
163
+ certPath?: string
164
+ keyPath?: string
165
+ deflate?: boolean
166
+ maxPayload?: number
167
+ useWorkerThread?: boolean
168
+ }
169
+
170
+ export const defaultServerOptions: ServerOptions = {
171
+ port: 45054,
172
+ secure: false,
173
+ certPath: undefined,
174
+ keyPath: undefined,
175
+ deflate: true,
176
+ maxPayload: 1000 * 1000000, // 1GB
177
+ useWorkerThread: true
178
+ }
@@ -0,0 +1,12 @@
1
+ import { logToStderr, setupProgramTerminationListeners, setupUnhandledExceptionListeners } from '../utilities/Utilities.js'
2
+ import { startServer } from './Server.js'
3
+
4
+ const log = logToStderr
5
+
6
+ setupUnhandledExceptionListeners()
7
+
8
+ setupProgramTerminationListeners(() => {
9
+ log('')
10
+ })
11
+
12
+ await startServer({}, (options) => { })