skyway-stt-client 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 NTT DOCOMO BUSINESS, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # SkyWay STT Client
2
+
3
+ SkyWayの文字起こしサービス(Speech-to-Text)用のJavaScriptライブラリです。
package/dist/index.cjs ADDED
@@ -0,0 +1,292 @@
1
+ //#region rolldown:runtime
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+
23
+ //#endregion
24
+ let __skyway_sdk_common = require("@skyway-sdk/common");
25
+ let isomorphic_ws = require("isomorphic-ws");
26
+ isomorphic_ws = __toESM(isomorphic_ws);
27
+
28
+ //#region src/loggerWrapper.ts
29
+ /**
30
+ * ログレベルに基づいてログ出力を制御するラッパー
31
+ */
32
+ var LoggerWrapper = class {
33
+ #logger;
34
+ #logLevel;
35
+ constructor(logger, logLevel) {
36
+ this.#logger = logger;
37
+ this.#logLevel = logLevel;
38
+ }
39
+ debug(...args) {
40
+ this.#log("debug", ...args);
41
+ }
42
+ warn(...args) {
43
+ this.#log("warn", ...args);
44
+ }
45
+ error(...args) {
46
+ this.#log("error", ...args);
47
+ }
48
+ #log(level, ...args) {
49
+ if (__skyway_sdk_common.logLevelTypes.indexOf(level) > __skyway_sdk_common.logLevelTypes.indexOf(this.#logLevel)) return;
50
+ this.#logger[level](...args);
51
+ }
52
+ };
53
+
54
+ //#endregion
55
+ //#region src/version.ts
56
+ /**
57
+ * パッケージのバージョン番号
58
+ * この値はWebSocket接続時にサーバーに送信されます。
59
+ */
60
+ const PACKAGE_VERSION = "0.1.0";
61
+
62
+ //#endregion
63
+ //#region src/sttClient.ts
64
+ const API_DOMAIN = "stt-dispatcher.skyway.ntt.com";
65
+ const API_VERSION = "v1";
66
+ const CloseEventCode = { from: (code) => {
67
+ if (code === 1e3 || 4e3 <= code && code <= 4099) return {
68
+ code,
69
+ shouldReconnect: false,
70
+ closeCase: "normal"
71
+ };
72
+ else if (code === 1009 || 4100 <= code && code <= 4199) return {
73
+ code,
74
+ shouldReconnect: false,
75
+ closeCase: "non-normal"
76
+ };
77
+ else if (4200 <= code && code <= 4299) return {
78
+ code,
79
+ shouldReconnect: true,
80
+ closeCase: "non-normal"
81
+ };
82
+ else if (code === 1006 || code === 1012) return {
83
+ code,
84
+ shouldReconnect: true,
85
+ closeCase: "normal"
86
+ };
87
+ else return {
88
+ code,
89
+ shouldReconnect: true,
90
+ closeCase: "unexpected"
91
+ };
92
+ } };
93
+ /**
94
+ * STT (Speech-to-Text) クライアント
95
+ *
96
+ * WebSocketを使用してSTT APIサーバーに接続し、
97
+ * 文字起こし結果をリアルタイムで受信します。
98
+ * 自動再接続機能やエラーハンドリングを含みます。
99
+ *
100
+ * @internal このクラスは内部用です。直接使用せず、SkyWaySTTClientを使用してください。
101
+ */
102
+ var STTClient = class {
103
+ #options;
104
+ #token;
105
+ #ws = void 0;
106
+ #retryAttempts = 0;
107
+ #removeTokenUpdatedListener;
108
+ /** STT結果受信時に発生するイベント */
109
+ onSTTResultReceived = new __skyway_sdk_common.Event();
110
+ /** エラー発生時に発生するイベント */
111
+ onError = new __skyway_sdk_common.Event();
112
+ /** WebSocket接続成功時に発生するイベント */
113
+ onOpen = new __skyway_sdk_common.Event();
114
+ /** WebSocket接続終了時に発生するイベント */
115
+ onClose = new __skyway_sdk_common.Event();
116
+ /**
117
+ * STTクライアントを初期化します
118
+ *
119
+ * @param context - SkyWayコンテキスト
120
+ * @param options - クライアントオプション
121
+ */
122
+ constructor(context, options) {
123
+ const baseLogger = options.logger ?? new __skyway_sdk_common.Logger("skyway-stt-client");
124
+ const logLevel = options.logLevel ?? context.config.log.level;
125
+ const logger = new LoggerWrapper(baseLogger, logLevel);
126
+ this.#options = {
127
+ roomId: options.roomId,
128
+ roomName: options.roomName,
129
+ memberId: options.memberId,
130
+ memberName: options.memberName,
131
+ domain: options.domain ?? API_DOMAIN,
132
+ secure: options.secure ?? true,
133
+ logger,
134
+ logLevel,
135
+ maxRetryAttempts: options.maxRetryAttempts ?? 3,
136
+ getRetryIntervalMs: options.getRetryIntervalMs ?? ((retryCount) => {
137
+ return (2 ** retryCount + Math.random()) * 1e3;
138
+ })
139
+ };
140
+ this.#token = context.authTokenString;
141
+ const { removeListener } = context._onTokenUpdated.add(() => {
142
+ this.#token = context.authTokenString;
143
+ if (this.#ws) this.#ws.close(4200);
144
+ else this.#connect();
145
+ });
146
+ this.#removeTokenUpdatedListener = removeListener;
147
+ this.onOpen.add(() => {
148
+ this.#retryAttempts = 0;
149
+ });
150
+ this.onClose.add((closeEventCode) => {
151
+ if (closeEventCode.closeCase === "unexpected") this.#options.logger.warn(`Failed to connect to server. WebSocket closed with unexpected code ${closeEventCode.code}.`);
152
+ if (closeEventCode.shouldReconnect) {
153
+ if (this.#retryAttempts < this.#options.maxRetryAttempts) {
154
+ this.#retryAttempts++;
155
+ const interval = this.#options.getRetryIntervalMs(this.#retryAttempts);
156
+ this.#options.logger.debug(`Retrying connection in ${interval}ms... (attempts=${this.#retryAttempts})`);
157
+ setTimeout(this.#connect, interval);
158
+ return;
159
+ }
160
+ this.#options.logger.error(`Failed to connect to server. All retry attempts failed (attempts=${this.#options.maxRetryAttempts})`);
161
+ this.onError.emit(/* @__PURE__ */ new Error(`Failed to connect to server. All retry attempts failed (attempts=${this.#options.maxRetryAttempts})`));
162
+ return;
163
+ }
164
+ if (closeEventCode.closeCase === "non-normal") {
165
+ this.#options.logger.error(`Failed to connect to server. WebSocket closed with non-normal code ${closeEventCode.code}.`, /* @__PURE__ */ new Error(`Failed to connect to server. WebSocket closed with non-normal code ${closeEventCode.code}.`));
166
+ this.onError.emit(/* @__PURE__ */ new Error(`Failed to connect server.`));
167
+ return;
168
+ }
169
+ });
170
+ this.#connect();
171
+ }
172
+ #connect = () => {
173
+ const wsProtocol = this.#options.secure ? "wss" : "ws";
174
+ const queryParams = new URLSearchParams({
175
+ roomId: this.#options.roomId,
176
+ ...this.#options.roomName && { roomName: this.#options.roomName },
177
+ memberId: this.#options.memberId,
178
+ ...this.#options.memberName && { memberName: this.#options.memberName },
179
+ sdkPlatform: "js",
180
+ sdkVersion: PACKAGE_VERSION
181
+ });
182
+ this.#ws = new isomorphic_ws.default(`${wsProtocol}://${this.#options.domain}/${API_VERSION}/ws?${queryParams.toString()}`, `SkyWayAuthToken!${this.#token}`);
183
+ this.#ws.onopen = () => {
184
+ this.#options.logger.debug("WebSocket connected to server.");
185
+ this.onOpen.emit();
186
+ };
187
+ this.#ws.onmessage = ({ data }) => {
188
+ try {
189
+ const msg = JSON.parse(data.toString());
190
+ if (msg.type === "TEXT" && msg.data) {
191
+ const resultData = { ...msg.data };
192
+ if (typeof resultData.timestamp === "string") resultData.timestamp = new Date(resultData.timestamp);
193
+ resultData.mode = resultData.mode.toLowerCase();
194
+ this.onSTTResultReceived.emit({ result: resultData });
195
+ }
196
+ } catch (error) {
197
+ this.#options.logger.error("Failed to parse message from server.", error);
198
+ }
199
+ };
200
+ this.#ws.onclose = (event) => {
201
+ this.#options.logger.debug(`WebSocket closed: ${JSON.stringify({
202
+ code: event.code,
203
+ reason: event.reason,
204
+ type: event.type
205
+ })}`);
206
+ const closeEventCode = CloseEventCode.from(event.code);
207
+ this.onClose.emit(closeEventCode);
208
+ };
209
+ this.#ws.onerror = (event) => {
210
+ this.#options.logger.error("WebSocket error event:", event);
211
+ };
212
+ };
213
+ /**
214
+ * クライアントを破棄し、リソースをクリーンアップします
215
+ * WebSocket接続を閉じ、イベントリスナーを削除します。
216
+ */
217
+ dispose() {
218
+ this.#removeTokenUpdatedListener();
219
+ this.onSTTResultReceived.removeAllListeners();
220
+ this.onError.removeAllListeners();
221
+ this.#ws?.close(1e3);
222
+ this.#ws = void 0;
223
+ this.#retryAttempts = 0;
224
+ }
225
+ /**
226
+ * WebSocketの現在の接続状態を返します
227
+ * @returns WebSocketの状態(CONNECTING, OPEN, CLOSING, CLOSED)
228
+ */
229
+ get readyState() {
230
+ return this.#ws?.readyState ?? isomorphic_ws.default.CLOSED;
231
+ }
232
+ };
233
+
234
+ //#endregion
235
+ //#region src/skywaySTTClient.ts
236
+ /**
237
+ * SkyWay STT (Speech-to-Text) クライアント
238
+ *
239
+ * SkyWayのSTTサーバーに接続し、リアルタイムで文字起こし結果を受信します。
240
+ * SkyWayContextとメンバー情報を使用して初期化します。
241
+ */
242
+ var SkyWaySTTClient = class {
243
+ #sttClient;
244
+ #disposed = false;
245
+ /** 文字起こし結果受信時に発生するイベント */
246
+ onSTTResultReceived = new __skyway_sdk_common.Event();
247
+ /** エラー発生時に発生するイベント */
248
+ onError = new __skyway_sdk_common.Event();
249
+ /**
250
+ * SkyWay STTクライアントを初期化します
251
+ *
252
+ * @param context - SkyWayContextインスタンス
253
+ * @param member - LocalRoomMemberインスタンス
254
+ * @param options - クライアントオプション
255
+ */
256
+ constructor(context, member, options) {
257
+ this.#sttClient = new STTClient(context, {
258
+ ...options,
259
+ memberId: member.id,
260
+ memberName: member.name,
261
+ roomId: member.roomId,
262
+ roomName: member.roomName
263
+ });
264
+ this.#sttClient.onSTTResultReceived.add((event) => {
265
+ this.onSTTResultReceived.emit(event);
266
+ });
267
+ this.#sttClient.onError.add((error) => {
268
+ this.onError.emit(error);
269
+ });
270
+ }
271
+ /**
272
+ * クライアントを破棄し、リソースをクリーンアップします
273
+ *
274
+ * WebSocket接続を閉じ、イベントリスナーを削除します。
275
+ */
276
+ dispose() {
277
+ this.#disposed = true;
278
+ this.onSTTResultReceived.removeAllListeners();
279
+ this.onError.removeAllListeners();
280
+ this.#sttClient.dispose();
281
+ }
282
+ /**
283
+ * クライアントが破棄されているかどうかを返します
284
+ * @returns 破棄されている場合はtrue
285
+ */
286
+ get disposed() {
287
+ return this.#disposed;
288
+ }
289
+ };
290
+
291
+ //#endregion
292
+ exports.SkyWaySTTClient = SkyWaySTTClient;
@@ -0,0 +1,148 @@
1
+ import { Event, LogLevel, LogLevel as LogLevel$1 } from "@skyway-sdk/common";
2
+ import { ContextConfig, LocalRoomMember } from "@skyway-sdk/room";
3
+
4
+ //#region src/types.d.ts
5
+
6
+ /**
7
+ * STTサーバーから受信するメッセージの型定義
8
+ */
9
+ type STTResultMessage = {
10
+ /** メッセージタイプ(現在は"TEXT"のみサポート) */
11
+ type: "TEXT";
12
+ /** STT結果データ */
13
+ data: STTResult;
14
+ };
15
+ /**
16
+ * 文字起こし結果の型定義
17
+ *
18
+ * 音声をテキストに変換した結果を表します
19
+ */
20
+ type TranscriptionSTTResult = {
21
+ /** 動作モード(文字起こし) */
22
+ mode: "transcription";
23
+ /** 認識されたテキスト */
24
+ text: string;
25
+ /** 結果の一意識別子 */
26
+ id: string;
27
+ /** 音声が送信された日時 */
28
+ timestamp: Date;
29
+ /** ルームID */
30
+ roomId: string;
31
+ /** メンバーID */
32
+ memberId: string;
33
+ /** ルーム名 */
34
+ roomName?: string;
35
+ /** メンバー名 */
36
+ memberName?: string;
37
+ };
38
+ /**
39
+ * 音声翻訳結果の型定義
40
+ *
41
+ * 音声を複数の言語に翻訳した結果を表します
42
+ */
43
+ type TranslationSTTResult = {
44
+ /** 動作モード(翻訳) */
45
+ mode: "translation";
46
+ /** 各言語での翻訳結果の配列 */
47
+ texts: {
48
+ language: string;
49
+ text: string;
50
+ }[];
51
+ /** 結果の一意識別子 */
52
+ id: string;
53
+ /** 音声が送信された日時 */
54
+ timestamp: Date;
55
+ /** ルームID */
56
+ roomId: string;
57
+ /** メンバーID */
58
+ memberId: string;
59
+ /** ルーム名 */
60
+ roomName?: string;
61
+ /** メンバー名 */
62
+ memberName?: string;
63
+ };
64
+ /**
65
+ * STT結果の統合型
66
+ *
67
+ * 文字起こし結果または翻訳結果のいずれかを表します
68
+ */
69
+ type STTResult = TranscriptionSTTResult | TranslationSTTResult;
70
+ /**
71
+ * ログ出力用のインターフェース
72
+ *
73
+ * カスタムログ出力を実装する場合に使用します
74
+ */
75
+ type Logger = {
76
+ /** デバッグ情報をログ出力 */
77
+ debug(...args: unknown[]): void;
78
+ /** 警告メッセージをログ出力 */
79
+ warn(...args: unknown[]): void;
80
+ /** エラーメッセージをログ出力 */
81
+ error(...args: unknown[]): void;
82
+ };
83
+ interface SkyWayContextInterface {
84
+ authTokenString: string;
85
+ config: ContextConfig;
86
+ readonly _onTokenUpdated: Event<string>;
87
+ }
88
+ //#endregion
89
+ //#region src/event.d.ts
90
+ /**
91
+ * 文字起こし結果受信イベントの型定義
92
+ *
93
+ * STTサーバーから文字起こし結果を受信した際に発生します
94
+ */
95
+ type STTResultReceivedEvent = {
96
+ /** 受信した文字起こし結果 */
97
+ result: STTResult;
98
+ };
99
+ //#endregion
100
+ //#region src/skywaySTTClient.d.ts
101
+ /**
102
+ * SkyWay STTクライアントのオプション設定
103
+ */
104
+ type SkyWaySTTClientOptions = {
105
+ /** STT APIのドメイン(オプション) */
106
+ domain?: string;
107
+ /** WSSを使用するか(デフォルト: true) */
108
+ secure?: boolean;
109
+ /** カスタムロガー(オプション) */
110
+ logger?: Logger;
111
+ /** ログレベル(オプション、デフォルト: contextのlog level) */
112
+ logLevel?: LogLevel$1;
113
+ };
114
+ /**
115
+ * SkyWay STT (Speech-to-Text) クライアント
116
+ *
117
+ * SkyWayのSTTサーバーに接続し、リアルタイムで文字起こし結果を受信します。
118
+ * SkyWayContextとメンバー情報を使用して初期化します。
119
+ */
120
+ declare class SkyWaySTTClient {
121
+ #private;
122
+ /** 文字起こし結果受信時に発生するイベント */
123
+ readonly onSTTResultReceived: Event<STTResultReceivedEvent>;
124
+ /** エラー発生時に発生するイベント */
125
+ readonly onError: Event<Error>;
126
+ /**
127
+ * SkyWay STTクライアントを初期化します
128
+ *
129
+ * @param context - SkyWayContextインスタンス
130
+ * @param member - LocalRoomMemberインスタンス
131
+ * @param options - クライアントオプション
132
+ */
133
+ constructor(context: SkyWayContextInterface, member: LocalRoomMember, options?: SkyWaySTTClientOptions);
134
+ /**
135
+ * クライアントを破棄し、リソースをクリーンアップします
136
+ *
137
+ * WebSocket接続を閉じ、イベントリスナーを削除します。
138
+ */
139
+ dispose(): void;
140
+ /**
141
+ * クライアントが破棄されているかどうかを返します
142
+ * @returns 破棄されている場合はtrue
143
+ */
144
+ get disposed(): boolean;
145
+ }
146
+ //#endregion
147
+ export { type LogLevel, type Logger, type STTResult, type STTResultMessage, type STTResultReceivedEvent, SkyWaySTTClient, type SkyWaySTTClientOptions, type TranscriptionSTTResult, type TranslationSTTResult };
148
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/event.ts","../src/skywaySTTClient.ts"],"sourcesContent":[],"mappings":";;;;;;;AAMA;AAYY,KAZA,gBAAA,GAYsB;EAwBtB;EAwBA,IAAA,EAAA,MAAS;EAOT;EAUK,IAAA,EAzET,SAyES;;;;AC5EjB;;;KDWY,sBAAA;EERA;EAiBC,IAAA,EAAA,eAAe;EAKE;EAAA,IAAA,EAAA,MAAA;EAEZ;EAAA,EAAA,EAAA,MAAA;EAUL;EACD,SAAA,EFnBC,IEmBD;EACE;EAAsB,MAAA,EAAA,MAAA;;;;;;;;;;;;;KFJxB,oBAAA;;;;;;;;;;;aAQC;;;;;;;;;;;;;;;KAgBD,SAAA,GAAY,yBAAyB;;;;;;KAOrC,MAAA;;;;;;;;UAUK,sBAAA;;UAEP;4BACkB;;;;;;;AAhF5B;AAYA;AAwBY,KCnCA,sBAAA,GDmCoB;EAwBpB;EAOA,MAAA,EChEF,SDgEQ;AAUlB,CAAA;;;AAjEA;AAwBA;AAwBA;AAOY,KE/DA,sBAAA,GF+DM;EAUD;;;;EC5EL;WCSD;;aAEE;AARb,CAAA;AAiBA;;;;;;AAkBY,cAlBC,eAAA,CAkBD;EACE,CAAA,OAAA;EAAsB;gCAdN,MAAA;;oBAEZ,MAAA;;;;;;;;uBAUL,gCACD,2BACE"}
@@ -0,0 +1,148 @@
1
+ import { Event, LogLevel, LogLevel as LogLevel$1 } from "@skyway-sdk/common";
2
+ import { ContextConfig, LocalRoomMember } from "@skyway-sdk/room";
3
+
4
+ //#region src/types.d.ts
5
+
6
+ /**
7
+ * STTサーバーから受信するメッセージの型定義
8
+ */
9
+ type STTResultMessage = {
10
+ /** メッセージタイプ(現在は"TEXT"のみサポート) */
11
+ type: "TEXT";
12
+ /** STT結果データ */
13
+ data: STTResult;
14
+ };
15
+ /**
16
+ * 文字起こし結果の型定義
17
+ *
18
+ * 音声をテキストに変換した結果を表します
19
+ */
20
+ type TranscriptionSTTResult = {
21
+ /** 動作モード(文字起こし) */
22
+ mode: "transcription";
23
+ /** 認識されたテキスト */
24
+ text: string;
25
+ /** 結果の一意識別子 */
26
+ id: string;
27
+ /** 音声が送信された日時 */
28
+ timestamp: Date;
29
+ /** ルームID */
30
+ roomId: string;
31
+ /** メンバーID */
32
+ memberId: string;
33
+ /** ルーム名 */
34
+ roomName?: string;
35
+ /** メンバー名 */
36
+ memberName?: string;
37
+ };
38
+ /**
39
+ * 音声翻訳結果の型定義
40
+ *
41
+ * 音声を複数の言語に翻訳した結果を表します
42
+ */
43
+ type TranslationSTTResult = {
44
+ /** 動作モード(翻訳) */
45
+ mode: "translation";
46
+ /** 各言語での翻訳結果の配列 */
47
+ texts: {
48
+ language: string;
49
+ text: string;
50
+ }[];
51
+ /** 結果の一意識別子 */
52
+ id: string;
53
+ /** 音声が送信された日時 */
54
+ timestamp: Date;
55
+ /** ルームID */
56
+ roomId: string;
57
+ /** メンバーID */
58
+ memberId: string;
59
+ /** ルーム名 */
60
+ roomName?: string;
61
+ /** メンバー名 */
62
+ memberName?: string;
63
+ };
64
+ /**
65
+ * STT結果の統合型
66
+ *
67
+ * 文字起こし結果または翻訳結果のいずれかを表します
68
+ */
69
+ type STTResult = TranscriptionSTTResult | TranslationSTTResult;
70
+ /**
71
+ * ログ出力用のインターフェース
72
+ *
73
+ * カスタムログ出力を実装する場合に使用します
74
+ */
75
+ type Logger = {
76
+ /** デバッグ情報をログ出力 */
77
+ debug(...args: unknown[]): void;
78
+ /** 警告メッセージをログ出力 */
79
+ warn(...args: unknown[]): void;
80
+ /** エラーメッセージをログ出力 */
81
+ error(...args: unknown[]): void;
82
+ };
83
+ interface SkyWayContextInterface {
84
+ authTokenString: string;
85
+ config: ContextConfig;
86
+ readonly _onTokenUpdated: Event<string>;
87
+ }
88
+ //#endregion
89
+ //#region src/event.d.ts
90
+ /**
91
+ * 文字起こし結果受信イベントの型定義
92
+ *
93
+ * STTサーバーから文字起こし結果を受信した際に発生します
94
+ */
95
+ type STTResultReceivedEvent = {
96
+ /** 受信した文字起こし結果 */
97
+ result: STTResult;
98
+ };
99
+ //#endregion
100
+ //#region src/skywaySTTClient.d.ts
101
+ /**
102
+ * SkyWay STTクライアントのオプション設定
103
+ */
104
+ type SkyWaySTTClientOptions = {
105
+ /** STT APIのドメイン(オプション) */
106
+ domain?: string;
107
+ /** WSSを使用するか(デフォルト: true) */
108
+ secure?: boolean;
109
+ /** カスタムロガー(オプション) */
110
+ logger?: Logger;
111
+ /** ログレベル(オプション、デフォルト: contextのlog level) */
112
+ logLevel?: LogLevel$1;
113
+ };
114
+ /**
115
+ * SkyWay STT (Speech-to-Text) クライアント
116
+ *
117
+ * SkyWayのSTTサーバーに接続し、リアルタイムで文字起こし結果を受信します。
118
+ * SkyWayContextとメンバー情報を使用して初期化します。
119
+ */
120
+ declare class SkyWaySTTClient {
121
+ #private;
122
+ /** 文字起こし結果受信時に発生するイベント */
123
+ readonly onSTTResultReceived: Event<STTResultReceivedEvent>;
124
+ /** エラー発生時に発生するイベント */
125
+ readonly onError: Event<Error>;
126
+ /**
127
+ * SkyWay STTクライアントを初期化します
128
+ *
129
+ * @param context - SkyWayContextインスタンス
130
+ * @param member - LocalRoomMemberインスタンス
131
+ * @param options - クライアントオプション
132
+ */
133
+ constructor(context: SkyWayContextInterface, member: LocalRoomMember, options?: SkyWaySTTClientOptions);
134
+ /**
135
+ * クライアントを破棄し、リソースをクリーンアップします
136
+ *
137
+ * WebSocket接続を閉じ、イベントリスナーを削除します。
138
+ */
139
+ dispose(): void;
140
+ /**
141
+ * クライアントが破棄されているかどうかを返します
142
+ * @returns 破棄されている場合はtrue
143
+ */
144
+ get disposed(): boolean;
145
+ }
146
+ //#endregion
147
+ export { type LogLevel, type Logger, type STTResult, type STTResultMessage, type STTResultReceivedEvent, SkyWaySTTClient, type SkyWaySTTClientOptions, type TranscriptionSTTResult, type TranslationSTTResult };
148
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/types.ts","../src/event.ts","../src/skywaySTTClient.ts"],"sourcesContent":[],"mappings":";;;;;;;AAMA;AAYY,KAZA,gBAAA,GAYsB;EAwBtB;EAwBA,IAAA,EAAA,MAAS;EAOT;EAUK,IAAA,EAzET,SAyES;;;;AC5EjB;;;KDWY,sBAAA;EERA;EAiBC,IAAA,EAAA,eAAe;EAKE;EAAA,IAAA,EAAA,MAAA;EAEZ;EAAA,EAAA,EAAA,MAAA;EAUL;EACD,SAAA,EFnBC,IEmBD;EACE;EAAsB,MAAA,EAAA,MAAA;;;;;;;;;;;;;KFJxB,oBAAA;;;;;;;;;;;aAQC;;;;;;;;;;;;;;;KAgBD,SAAA,GAAY,yBAAyB;;;;;;KAOrC,MAAA;;;;;;;;UAUK,sBAAA;;UAEP;4BACkB;;;;;;;AAhF5B;AAYA;AAwBY,KCnCA,sBAAA,GDmCoB;EAwBpB;EAOA,MAAA,EChEF,SDgEQ;AAUlB,CAAA;;;AAjEA;AAwBA;AAwBA;AAOY,KE/DA,sBAAA,GF+DM;EAUD;;;;EC5EL;WCSD;;aAEE;AARb,CAAA;AAiBA;;;;;;AAkBY,cAlBC,eAAA,CAkBD;EACE,CAAA,OAAA;EAAsB;gCAdN,MAAA;;oBAEZ,MAAA;;;;;;;;uBAUL,gCACD,2BACE"}
package/dist/index.js ADDED
@@ -0,0 +1,269 @@
1
+ import { Event, Logger, logLevelTypes } from "@skyway-sdk/common";
2
+ import WebSocket from "isomorphic-ws";
3
+
4
+ //#region src/loggerWrapper.ts
5
+ /**
6
+ * ログレベルに基づいてログ出力を制御するラッパー
7
+ */
8
+ var LoggerWrapper = class {
9
+ #logger;
10
+ #logLevel;
11
+ constructor(logger, logLevel) {
12
+ this.#logger = logger;
13
+ this.#logLevel = logLevel;
14
+ }
15
+ debug(...args) {
16
+ this.#log("debug", ...args);
17
+ }
18
+ warn(...args) {
19
+ this.#log("warn", ...args);
20
+ }
21
+ error(...args) {
22
+ this.#log("error", ...args);
23
+ }
24
+ #log(level, ...args) {
25
+ if (logLevelTypes.indexOf(level) > logLevelTypes.indexOf(this.#logLevel)) return;
26
+ this.#logger[level](...args);
27
+ }
28
+ };
29
+
30
+ //#endregion
31
+ //#region src/version.ts
32
+ /**
33
+ * パッケージのバージョン番号
34
+ * この値はWebSocket接続時にサーバーに送信されます。
35
+ */
36
+ const PACKAGE_VERSION = "0.1.0";
37
+
38
+ //#endregion
39
+ //#region src/sttClient.ts
40
+ const API_DOMAIN = "stt-dispatcher.skyway.ntt.com";
41
+ const API_VERSION = "v1";
42
+ const CloseEventCode = { from: (code) => {
43
+ if (code === 1e3 || 4e3 <= code && code <= 4099) return {
44
+ code,
45
+ shouldReconnect: false,
46
+ closeCase: "normal"
47
+ };
48
+ else if (code === 1009 || 4100 <= code && code <= 4199) return {
49
+ code,
50
+ shouldReconnect: false,
51
+ closeCase: "non-normal"
52
+ };
53
+ else if (4200 <= code && code <= 4299) return {
54
+ code,
55
+ shouldReconnect: true,
56
+ closeCase: "non-normal"
57
+ };
58
+ else if (code === 1006 || code === 1012) return {
59
+ code,
60
+ shouldReconnect: true,
61
+ closeCase: "normal"
62
+ };
63
+ else return {
64
+ code,
65
+ shouldReconnect: true,
66
+ closeCase: "unexpected"
67
+ };
68
+ } };
69
+ /**
70
+ * STT (Speech-to-Text) クライアント
71
+ *
72
+ * WebSocketを使用してSTT APIサーバーに接続し、
73
+ * 文字起こし結果をリアルタイムで受信します。
74
+ * 自動再接続機能やエラーハンドリングを含みます。
75
+ *
76
+ * @internal このクラスは内部用です。直接使用せず、SkyWaySTTClientを使用してください。
77
+ */
78
+ var STTClient = class {
79
+ #options;
80
+ #token;
81
+ #ws = void 0;
82
+ #retryAttempts = 0;
83
+ #removeTokenUpdatedListener;
84
+ /** STT結果受信時に発生するイベント */
85
+ onSTTResultReceived = new Event();
86
+ /** エラー発生時に発生するイベント */
87
+ onError = new Event();
88
+ /** WebSocket接続成功時に発生するイベント */
89
+ onOpen = new Event();
90
+ /** WebSocket接続終了時に発生するイベント */
91
+ onClose = new Event();
92
+ /**
93
+ * STTクライアントを初期化します
94
+ *
95
+ * @param context - SkyWayコンテキスト
96
+ * @param options - クライアントオプション
97
+ */
98
+ constructor(context, options) {
99
+ const baseLogger = options.logger ?? new Logger("skyway-stt-client");
100
+ const logLevel = options.logLevel ?? context.config.log.level;
101
+ const logger = new LoggerWrapper(baseLogger, logLevel);
102
+ this.#options = {
103
+ roomId: options.roomId,
104
+ roomName: options.roomName,
105
+ memberId: options.memberId,
106
+ memberName: options.memberName,
107
+ domain: options.domain ?? API_DOMAIN,
108
+ secure: options.secure ?? true,
109
+ logger,
110
+ logLevel,
111
+ maxRetryAttempts: options.maxRetryAttempts ?? 3,
112
+ getRetryIntervalMs: options.getRetryIntervalMs ?? ((retryCount) => {
113
+ return (2 ** retryCount + Math.random()) * 1e3;
114
+ })
115
+ };
116
+ this.#token = context.authTokenString;
117
+ const { removeListener } = context._onTokenUpdated.add(() => {
118
+ this.#token = context.authTokenString;
119
+ if (this.#ws) this.#ws.close(4200);
120
+ else this.#connect();
121
+ });
122
+ this.#removeTokenUpdatedListener = removeListener;
123
+ this.onOpen.add(() => {
124
+ this.#retryAttempts = 0;
125
+ });
126
+ this.onClose.add((closeEventCode) => {
127
+ if (closeEventCode.closeCase === "unexpected") this.#options.logger.warn(`Failed to connect to server. WebSocket closed with unexpected code ${closeEventCode.code}.`);
128
+ if (closeEventCode.shouldReconnect) {
129
+ if (this.#retryAttempts < this.#options.maxRetryAttempts) {
130
+ this.#retryAttempts++;
131
+ const interval = this.#options.getRetryIntervalMs(this.#retryAttempts);
132
+ this.#options.logger.debug(`Retrying connection in ${interval}ms... (attempts=${this.#retryAttempts})`);
133
+ setTimeout(this.#connect, interval);
134
+ return;
135
+ }
136
+ this.#options.logger.error(`Failed to connect to server. All retry attempts failed (attempts=${this.#options.maxRetryAttempts})`);
137
+ this.onError.emit(/* @__PURE__ */ new Error(`Failed to connect to server. All retry attempts failed (attempts=${this.#options.maxRetryAttempts})`));
138
+ return;
139
+ }
140
+ if (closeEventCode.closeCase === "non-normal") {
141
+ this.#options.logger.error(`Failed to connect to server. WebSocket closed with non-normal code ${closeEventCode.code}.`, /* @__PURE__ */ new Error(`Failed to connect to server. WebSocket closed with non-normal code ${closeEventCode.code}.`));
142
+ this.onError.emit(/* @__PURE__ */ new Error(`Failed to connect server.`));
143
+ return;
144
+ }
145
+ });
146
+ this.#connect();
147
+ }
148
+ #connect = () => {
149
+ const wsProtocol = this.#options.secure ? "wss" : "ws";
150
+ const queryParams = new URLSearchParams({
151
+ roomId: this.#options.roomId,
152
+ ...this.#options.roomName && { roomName: this.#options.roomName },
153
+ memberId: this.#options.memberId,
154
+ ...this.#options.memberName && { memberName: this.#options.memberName },
155
+ sdkPlatform: "js",
156
+ sdkVersion: PACKAGE_VERSION
157
+ });
158
+ this.#ws = new WebSocket(`${wsProtocol}://${this.#options.domain}/${API_VERSION}/ws?${queryParams.toString()}`, `SkyWayAuthToken!${this.#token}`);
159
+ this.#ws.onopen = () => {
160
+ this.#options.logger.debug("WebSocket connected to server.");
161
+ this.onOpen.emit();
162
+ };
163
+ this.#ws.onmessage = ({ data }) => {
164
+ try {
165
+ const msg = JSON.parse(data.toString());
166
+ if (msg.type === "TEXT" && msg.data) {
167
+ const resultData = { ...msg.data };
168
+ if (typeof resultData.timestamp === "string") resultData.timestamp = new Date(resultData.timestamp);
169
+ resultData.mode = resultData.mode.toLowerCase();
170
+ this.onSTTResultReceived.emit({ result: resultData });
171
+ }
172
+ } catch (error) {
173
+ this.#options.logger.error("Failed to parse message from server.", error);
174
+ }
175
+ };
176
+ this.#ws.onclose = (event) => {
177
+ this.#options.logger.debug(`WebSocket closed: ${JSON.stringify({
178
+ code: event.code,
179
+ reason: event.reason,
180
+ type: event.type
181
+ })}`);
182
+ const closeEventCode = CloseEventCode.from(event.code);
183
+ this.onClose.emit(closeEventCode);
184
+ };
185
+ this.#ws.onerror = (event) => {
186
+ this.#options.logger.error("WebSocket error event:", event);
187
+ };
188
+ };
189
+ /**
190
+ * クライアントを破棄し、リソースをクリーンアップします
191
+ * WebSocket接続を閉じ、イベントリスナーを削除します。
192
+ */
193
+ dispose() {
194
+ this.#removeTokenUpdatedListener();
195
+ this.onSTTResultReceived.removeAllListeners();
196
+ this.onError.removeAllListeners();
197
+ this.#ws?.close(1e3);
198
+ this.#ws = void 0;
199
+ this.#retryAttempts = 0;
200
+ }
201
+ /**
202
+ * WebSocketの現在の接続状態を返します
203
+ * @returns WebSocketの状態(CONNECTING, OPEN, CLOSING, CLOSED)
204
+ */
205
+ get readyState() {
206
+ return this.#ws?.readyState ?? WebSocket.CLOSED;
207
+ }
208
+ };
209
+
210
+ //#endregion
211
+ //#region src/skywaySTTClient.ts
212
+ /**
213
+ * SkyWay STT (Speech-to-Text) クライアント
214
+ *
215
+ * SkyWayのSTTサーバーに接続し、リアルタイムで文字起こし結果を受信します。
216
+ * SkyWayContextとメンバー情報を使用して初期化します。
217
+ */
218
+ var SkyWaySTTClient = class {
219
+ #sttClient;
220
+ #disposed = false;
221
+ /** 文字起こし結果受信時に発生するイベント */
222
+ onSTTResultReceived = new Event();
223
+ /** エラー発生時に発生するイベント */
224
+ onError = new Event();
225
+ /**
226
+ * SkyWay STTクライアントを初期化します
227
+ *
228
+ * @param context - SkyWayContextインスタンス
229
+ * @param member - LocalRoomMemberインスタンス
230
+ * @param options - クライアントオプション
231
+ */
232
+ constructor(context, member, options) {
233
+ this.#sttClient = new STTClient(context, {
234
+ ...options,
235
+ memberId: member.id,
236
+ memberName: member.name,
237
+ roomId: member.roomId,
238
+ roomName: member.roomName
239
+ });
240
+ this.#sttClient.onSTTResultReceived.add((event) => {
241
+ this.onSTTResultReceived.emit(event);
242
+ });
243
+ this.#sttClient.onError.add((error) => {
244
+ this.onError.emit(error);
245
+ });
246
+ }
247
+ /**
248
+ * クライアントを破棄し、リソースをクリーンアップします
249
+ *
250
+ * WebSocket接続を閉じ、イベントリスナーを削除します。
251
+ */
252
+ dispose() {
253
+ this.#disposed = true;
254
+ this.onSTTResultReceived.removeAllListeners();
255
+ this.onError.removeAllListeners();
256
+ this.#sttClient.dispose();
257
+ }
258
+ /**
259
+ * クライアントが破棄されているかどうかを返します
260
+ * @returns 破棄されている場合はtrue
261
+ */
262
+ get disposed() {
263
+ return this.#disposed;
264
+ }
265
+ };
266
+
267
+ //#endregion
268
+ export { SkyWaySTTClient };
269
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["#logger","#logLevel","#log","SkyWayLogger","#options","#token","#ws","#connect","#removeTokenUpdatedListener","#retryAttempts","#sttClient","#disposed"],"sources":["../src/loggerWrapper.ts","../src/version.ts","../src/sttClient.ts","../src/skywaySTTClient.ts"],"sourcesContent":["import { type LogLevel, logLevelTypes } from \"@skyway-sdk/common\";\nimport type { Logger } from \"./types\";\n\n/**\n * ログレベルに基づいてログ出力を制御するラッパー\n */\nexport class LoggerWrapper implements Logger {\n #logger: Logger;\n #logLevel: LogLevel;\n\n constructor(logger: Logger, logLevel: LogLevel) {\n this.#logger = logger;\n this.#logLevel = logLevel;\n }\n\n debug(...args: unknown[]): void {\n this.#log(\"debug\", ...args);\n }\n\n warn(...args: unknown[]): void {\n this.#log(\"warn\", ...args);\n }\n\n error(...args: unknown[]): void {\n this.#log(\"error\", ...args);\n }\n\n #log(level: Exclude<LogLevel, \"disable\" | \"info\">, ...args: unknown[]): void {\n const logLevelIndex = logLevelTypes.indexOf(level);\n const thisLogLevelIndex = logLevelTypes.indexOf(this.#logLevel);\n\n if (logLevelIndex > thisLogLevelIndex) {\n return;\n }\n\n this.#logger[level](...args);\n }\n}\n","/**\n * パッケージのバージョン番号\n * この値はWebSocket接続時にサーバーに送信されます。\n */\nexport const PACKAGE_VERSION = \"0.1.0\";\n","import {\n Event,\n type LogLevel,\n Logger as SkyWayLogger,\n} from \"@skyway-sdk/common\";\nimport WebSocket from \"isomorphic-ws\";\nimport type { STTResultReceivedEvent } from \"./event\";\nimport { LoggerWrapper } from \"./loggerWrapper\";\nimport type { Logger, SkyWayContextInterface, STTResult } from \"./types\";\nimport { PACKAGE_VERSION } from \"./version\";\n\nconst API_DOMAIN = \"stt-dispatcher.skyway.ntt.com\";\nconst API_VERSION = \"v1\";\n\ntype CloseEventCode = {\n code: number;\n shouldReconnect: boolean;\n closeCase: \"normal\" | \"non-normal\" | \"unexpected\";\n};\n\nconst CloseEventCode = {\n from: (code: CloseEvent[\"code\"]): CloseEventCode => {\n // https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent/code\n // 1000, 4000~4099 : normal case (should not reconnect)\n // 1006(server timeout), 1012 : normal case (should reconnect)\n // 1009, 4100~4199 : non-normal case (should not reconnect)\n // 4200~4299 : non-normal case (should reconnect)\n // others : unexpected case (should reconnect)\n if (code === 1000 || (4000 <= code && code <= 4099)) {\n return {\n code,\n shouldReconnect: false,\n closeCase: \"normal\",\n };\n } else if (code === 1009 || (4100 <= code && code <= 4199)) {\n return {\n code,\n shouldReconnect: false,\n closeCase: \"non-normal\",\n };\n } else if (4200 <= code && code <= 4299) {\n return {\n code,\n shouldReconnect: true,\n closeCase: \"non-normal\",\n };\n } else if (code === 1006 || code === 1012) {\n return {\n code,\n shouldReconnect: true,\n closeCase: \"normal\",\n };\n } else {\n return {\n code,\n shouldReconnect: true,\n closeCase: \"unexpected\",\n };\n }\n },\n};\n\n/**\n * STTクライアントのオプション設定\n */\nexport type STTClientOptions = {\n /** ルームID */\n roomId: string;\n /** ルーム名(オプション) */\n roomName?: string;\n /** メンバーID */\n memberId: string;\n /** メンバー名(オプション) */\n memberName?: string;\n /** APIドメイン(デフォルト: stt-dispatcher.skyway.ntt.com) */\n domain?: string;\n /** WSSを使用するか(デフォルト: true) */\n secure?: boolean;\n /** カスタムロガー(オプション) */\n logger?: Logger;\n /** ログレベル(オプション) */\n logLevel?: LogLevel;\n /** 最大再試行回数(デフォルト: 3) */\n maxRetryAttempts?: number;\n /** 再試行間隔を算出する関数(デフォルト: 指数バックオフ) */\n getRetryIntervalMs?: (retryCount: number) => number;\n};\n\n/**\n * STT (Speech-to-Text) クライアント\n *\n * WebSocketを使用してSTT APIサーバーに接続し、\n * 文字起こし結果をリアルタイムで受信します。\n * 自動再接続機能やエラーハンドリングを含みます。\n *\n * @internal このクラスは内部用です。直接使用せず、SkyWaySTTClientを使用してください。\n */\nexport class STTClient {\n #options: Required<Omit<STTClientOptions, \"roomName\" | \"memberName\">> &\n Pick<STTClientOptions, \"roomName\" | \"memberName\">;\n #token: string;\n #ws: WebSocket | undefined = undefined;\n #retryAttempts = 0;\n #removeTokenUpdatedListener: () => void;\n\n /** STT結果受信時に発生するイベント */\n readonly onSTTResultReceived = new Event<STTResultReceivedEvent>();\n /** エラー発生時に発生するイベント */\n readonly onError = new Event<Error>();\n /** WebSocket接続成功時に発生するイベント */\n readonly onOpen = new Event<void>();\n /** WebSocket接続終了時に発生するイベント */\n readonly onClose = new Event<CloseEventCode>();\n\n /**\n * STTクライアントを初期化します\n *\n * @param context - SkyWayコンテキスト\n * @param options - クライアントオプション\n */\n constructor(context: SkyWayContextInterface, options: STTClientOptions) {\n const baseLogger = options.logger ?? new SkyWayLogger(\"skyway-stt-client\");\n const logLevel = options.logLevel ?? context.config.log.level;\n const logger = new LoggerWrapper(baseLogger, logLevel);\n\n this.#options = {\n roomId: options.roomId,\n roomName: options.roomName,\n memberId: options.memberId,\n memberName: options.memberName,\n domain: options.domain ?? API_DOMAIN,\n secure: options.secure ?? true,\n logger,\n logLevel,\n maxRetryAttempts: options.maxRetryAttempts ?? 3,\n getRetryIntervalMs:\n options.getRetryIntervalMs ??\n ((retryCount) => {\n return (2 ** retryCount + Math.random()) * 1000;\n }),\n };\n this.#token = context.authTokenString;\n const { removeListener } = context._onTokenUpdated.add(() => {\n this.#token = context.authTokenString;\n if (this.#ws) {\n this.#ws.close(4200);\n } else {\n this.#connect();\n }\n });\n this.#removeTokenUpdatedListener = removeListener;\n\n this.onOpen.add(() => {\n this.#retryAttempts = 0;\n });\n this.onClose.add((closeEventCode) => {\n if (closeEventCode.closeCase === \"unexpected\") {\n this.#options.logger.warn(\n `Failed to connect to server. WebSocket closed with unexpected code ${closeEventCode.code}.`,\n );\n }\n if (closeEventCode.shouldReconnect) {\n if (this.#retryAttempts < this.#options.maxRetryAttempts) {\n this.#retryAttempts++;\n const interval = this.#options.getRetryIntervalMs(\n this.#retryAttempts,\n );\n this.#options.logger.debug(\n `Retrying connection in ${interval}ms... (attempts=${\n this.#retryAttempts\n })`,\n );\n setTimeout(this.#connect, interval);\n return;\n }\n\n this.#options.logger.error(\n `Failed to connect to server. All retry attempts failed (attempts=${\n this.#options.maxRetryAttempts\n })`,\n );\n this.onError.emit(\n new Error(\n `Failed to connect to server. All retry attempts failed (attempts=${\n this.#options.maxRetryAttempts\n })`,\n ),\n );\n return;\n }\n if (closeEventCode.closeCase === \"non-normal\") {\n this.#options.logger.error(\n `Failed to connect to server. WebSocket closed with non-normal code ${closeEventCode.code}.`,\n new Error(\n `Failed to connect to server. WebSocket closed with non-normal code ${closeEventCode.code}.`,\n ),\n );\n this.onError.emit(new Error(`Failed to connect server.`));\n return;\n }\n });\n\n this.#connect();\n }\n\n #connect = () => {\n const wsProtocol = this.#options.secure ? \"wss\" : \"ws\";\n const queryParams = new URLSearchParams({\n roomId: this.#options.roomId,\n ...(this.#options.roomName && { roomName: this.#options.roomName }),\n memberId: this.#options.memberId,\n ...(this.#options.memberName && { memberName: this.#options.memberName }),\n sdkPlatform: \"js\",\n sdkVersion: PACKAGE_VERSION,\n });\n const wsUrl = `${wsProtocol}://${\n this.#options.domain\n }/${API_VERSION}/ws?${queryParams.toString()}`;\n\n this.#ws = new WebSocket(wsUrl, `SkyWayAuthToken!${this.#token}`);\n this.#ws.onopen = () => {\n this.#options.logger.debug(\"WebSocket connected to server.\");\n this.onOpen.emit();\n };\n this.#ws.onmessage = ({ data }) => {\n try {\n const msg = JSON.parse(data.toString());\n if (msg.type === \"TEXT\" && msg.data) {\n // Convert timestamp from number to Date if needed\n const resultData = { ...msg.data };\n if (typeof resultData.timestamp === \"string\") {\n resultData.timestamp = new Date(resultData.timestamp);\n }\n\n resultData.mode = resultData.mode.toLowerCase();\n\n this.onSTTResultReceived.emit({\n result: resultData as STTResult,\n });\n }\n } catch (error) {\n this.#options.logger.error(\n \"Failed to parse message from server.\",\n error,\n );\n }\n };\n\n this.#ws.onclose = (event) => {\n this.#options.logger.debug(\n `WebSocket closed: ${JSON.stringify({\n code: event.code,\n reason: event.reason,\n type: event.type,\n })}`,\n );\n\n const closeEventCode = CloseEventCode.from(event.code);\n this.onClose.emit(closeEventCode);\n };\n\n this.#ws.onerror = (event) => {\n this.#options.logger.error(\"WebSocket error event:\", event);\n };\n };\n\n /**\n * クライアントを破棄し、リソースをクリーンアップします\n * WebSocket接続を閉じ、イベントリスナーを削除します。\n */\n dispose() {\n this.#removeTokenUpdatedListener();\n this.onSTTResultReceived.removeAllListeners();\n this.onError.removeAllListeners();\n this.#ws?.close(1000);\n this.#ws = undefined;\n this.#retryAttempts = 0;\n }\n\n /**\n * WebSocketの現在の接続状態を返します\n * @returns WebSocketの状態(CONNECTING, OPEN, CLOSING, CLOSED)\n */\n get readyState() {\n return this.#ws?.readyState ?? WebSocket.CLOSED;\n }\n}\n","import type { LogLevel } from \"@skyway-sdk/common\";\nimport { Event } from \"@skyway-sdk/common\";\nimport type { LocalRoomMember } from \"@skyway-sdk/room\";\nimport type { STTResultReceivedEvent } from \"./event\";\nimport { STTClient } from \"./sttClient\";\nimport type { Logger, SkyWayContextInterface } from \"./types\";\n\n/**\n * SkyWay STTクライアントのオプション設定\n */\nexport type SkyWaySTTClientOptions = {\n /** STT APIのドメイン(オプション) */\n domain?: string;\n /** WSSを使用するか(デフォルト: true) */\n secure?: boolean;\n /** カスタムロガー(オプション) */\n logger?: Logger;\n /** ログレベル(オプション、デフォルト: contextのlog level) */\n logLevel?: LogLevel;\n};\n\n/**\n * SkyWay STT (Speech-to-Text) クライアント\n *\n * SkyWayのSTTサーバーに接続し、リアルタイムで文字起こし結果を受信します。\n * SkyWayContextとメンバー情報を使用して初期化します。\n */\nexport class SkyWaySTTClient {\n #sttClient: STTClient;\n #disposed: boolean = false;\n\n /** 文字起こし結果受信時に発生するイベント */\n readonly onSTTResultReceived = new Event<STTResultReceivedEvent>();\n /** エラー発生時に発生するイベント */\n readonly onError = new Event<Error>();\n\n /**\n * SkyWay STTクライアントを初期化します\n *\n * @param context - SkyWayContextインスタンス\n * @param member - LocalRoomMemberインスタンス\n * @param options - クライアントオプション\n */\n constructor(\n context: SkyWayContextInterface,\n member: LocalRoomMember,\n options?: SkyWaySTTClientOptions,\n ) {\n this.#sttClient = new STTClient(context, {\n ...options,\n memberId: member.id,\n memberName: member.name,\n roomId: member.roomId,\n roomName: member.roomName,\n });\n this.#sttClient.onSTTResultReceived.add((event) => {\n this.onSTTResultReceived.emit(event);\n });\n this.#sttClient.onError.add((error) => {\n this.onError.emit(error);\n });\n }\n\n /**\n * クライアントを破棄し、リソースをクリーンアップします\n *\n * WebSocket接続を閉じ、イベントリスナーを削除します。\n */\n dispose() {\n this.#disposed = true;\n this.onSTTResultReceived.removeAllListeners();\n this.onError.removeAllListeners();\n this.#sttClient.dispose();\n }\n\n /**\n * クライアントが破棄されているかどうかを返します\n * @returns 破棄されている場合はtrue\n */\n get disposed(): boolean {\n return this.#disposed;\n }\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "skyway-stt-client",
3
+ "version": "0.1.0",
4
+ "description": "JavaScript SDK for SkyWay STT (Speech-to-Text) service",
5
+ "homepage": "https://skyway.ntt.com/",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/skyway/skyway-stt-client-js.git"
9
+ },
10
+ "license": "MIT",
11
+ "author": "NTT DOCOMO BUSINESS, Inc.",
12
+ "type": "module",
13
+ "main": "dist/index.js",
14
+ "module": "dist/index.js",
15
+ "types": "dist/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "import": "./dist/index.js",
19
+ "require": "./dist/index.cjs"
20
+ }
21
+ },
22
+ "files": [
23
+ "dist",
24
+ "LICENSE"
25
+ ],
26
+ "scripts": {
27
+ "lint": "biome check --error-on-warnings",
28
+ "lint:fix": "biome check --fix --error-on-warnings",
29
+ "type-check": "tsc --noEmit",
30
+ "build": "tsx scripts/build.ts",
31
+ "build:prod": "pnpm build && pnpm run docs && pnpm license:generate",
32
+ "test": "vitest run",
33
+ "test:ci": "vitest run --silent",
34
+ "test:watch": "vitest",
35
+ "docs": "typedoc",
36
+ "docs:serve": "typedoc --watch",
37
+ "license:generate": "tsx scripts/license.ts generate",
38
+ "license:check": "tsx scripts/license.ts check"
39
+ },
40
+ "keywords": [
41
+ "skyway",
42
+ "speech-to-text"
43
+ ],
44
+ "packageManager": "pnpm@10.22.0",
45
+ "devDependencies": {
46
+ "@arethetypeswrong/core": "^0.18.2",
47
+ "@biomejs/biome": "^2.3.6",
48
+ "@skyway-sdk/room": "^2.1.0",
49
+ "@types/ws": "^8.18.1",
50
+ "jsdom": "^27.2.0",
51
+ "tsdown": "^0.16.5",
52
+ "tsx": "^4.20.6",
53
+ "typedoc": "^0.28.14",
54
+ "typescript": "^5.9.3",
55
+ "vitest": "^4.0.10",
56
+ "ws": "^8.18.3",
57
+ "zx": "^8.8.5"
58
+ },
59
+ "dependencies": {
60
+ "@skyway-sdk/common": "^2.0.0",
61
+ "isomorphic-ws": "^5.0.0"
62
+ }
63
+ }