@corti/dictation-web 0.1.23-rc.4 → 0.2.1
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 +6 -4
- package/dist/CortiDictation.d.ts +14 -0
- package/dist/CortiDictation.js +18 -14
- package/dist/CortiDictation.js.map +1 -1
- package/dist/DictationService.js +5 -15
- package/dist/DictationService.js.map +1 -1
- package/dist/bundle.js +1749 -300
- package/dist/types.d.ts +2 -2
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +4 -5
- package/dist/utils.js +4 -5
- package/dist/utils.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -94,6 +94,8 @@ Alternatively, use a CDN to start quickly (not recommended).
|
|
|
94
94
|
| `transcript` | Fired when a new transcript is received. `detail.data.text` contains the transcribed text. |
|
|
95
95
|
| `command` | Fired whenever a new command is detected. |
|
|
96
96
|
| `audio-level-changed` | Fired when the input audio level changes. `detail.audioLevel` contains the new level. |
|
|
97
|
+
| `usage` | Fired when usage information is received from the server. `detail.credits` contains the usage data. |
|
|
98
|
+
| `stream-closed` | Fired when the WebSocket stream is closed. `detail` contains the close event data. |
|
|
97
99
|
| `error` | Fired on error. `detail` contains the full error. |
|
|
98
100
|
|
|
99
101
|
## Authentication
|
|
@@ -114,10 +116,12 @@ dictation.setAuthConfig({
|
|
|
114
116
|
// This function runs before any API call when the access_token is near expiration
|
|
115
117
|
refreshAccessToken: async (refreshToken?: string) => {
|
|
116
118
|
// Custom refresh logic -- get new access_token from server
|
|
117
|
-
|
|
119
|
+
// if accessToken is not passed to AuthConfig, refreshToken will be `undefined` for the first call,
|
|
120
|
+
// then it will be the refreshToken returned from the previous token request
|
|
121
|
+
const response = await fetch("https://your-auth-server/token", {
|
|
118
122
|
method: "POST",
|
|
119
123
|
headers: { "Content-Type": "application/json" },
|
|
120
|
-
body: JSON.stringify({ refreshToken
|
|
124
|
+
body: JSON.stringify({ refreshToken }),
|
|
121
125
|
});
|
|
122
126
|
|
|
123
127
|
const result = await response.json();
|
|
@@ -125,9 +129,7 @@ dictation.setAuthConfig({
|
|
|
125
129
|
// Return in the expected format
|
|
126
130
|
return {
|
|
127
131
|
accessToken: result.accessToken,
|
|
128
|
-
expiresIn: result.expiresIn || 3600,
|
|
129
132
|
refreshToken: result.refreshToken,
|
|
130
|
-
refreshExpiresIn: result.refreshExpiresIn,
|
|
131
133
|
};
|
|
132
134
|
}
|
|
133
135
|
});
|
package/dist/CortiDictation.d.ts
CHANGED
|
@@ -17,12 +17,26 @@ export declare class CortiDictation extends LitElement {
|
|
|
17
17
|
private recorderManager;
|
|
18
18
|
connectedCallback(): Promise<void>;
|
|
19
19
|
toggleRecording(): void;
|
|
20
|
+
/**
|
|
21
|
+
* Sets the access token and returns the server configuration.
|
|
22
|
+
*
|
|
23
|
+
* NOTE: We decode the token here only for backward compatibility in return values.
|
|
24
|
+
* The SDK now handles token parsing internally, so this return value should be
|
|
25
|
+
* reduced in the future to only include necessary fields.
|
|
26
|
+
*/
|
|
20
27
|
setAccessToken(token: string): {
|
|
21
28
|
environment: string;
|
|
22
29
|
tenant: string;
|
|
23
30
|
accessToken: string;
|
|
24
31
|
expiresAt: number | undefined;
|
|
25
32
|
} | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Sets the authentication configuration and returns the server configuration.
|
|
35
|
+
*
|
|
36
|
+
* NOTE: We decode tokens here only for backward compatibility in return values.
|
|
37
|
+
* The SDK now handles token parsing internally, so this return value should be
|
|
38
|
+
* reduced in the future to only include necessary fields.
|
|
39
|
+
*/
|
|
26
40
|
setAuthConfig(config: Corti.BearerOptions): Promise<ServerConfig>;
|
|
27
41
|
get selectedDevice(): MediaDeviceInfo | null;
|
|
28
42
|
get recordingState(): RecordingState;
|
package/dist/CortiDictation.js
CHANGED
|
@@ -59,7 +59,7 @@ export class CortiDictation extends LitElement {
|
|
|
59
59
|
'command',
|
|
60
60
|
'ready',
|
|
61
61
|
'usage',
|
|
62
|
-
'stream-closed'
|
|
62
|
+
'stream-closed',
|
|
63
63
|
];
|
|
64
64
|
eventsToRelay.forEach(eventName => {
|
|
65
65
|
this.recorderManager.addEventListener(eventName, (e) => {
|
|
@@ -80,6 +80,13 @@ export class CortiDictation extends LitElement {
|
|
|
80
80
|
toggleRecording() {
|
|
81
81
|
this._toggleRecording();
|
|
82
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* Sets the access token and returns the server configuration.
|
|
85
|
+
*
|
|
86
|
+
* NOTE: We decode the token here only for backward compatibility in return values.
|
|
87
|
+
* The SDK now handles token parsing internally, so this return value should be
|
|
88
|
+
* reduced in the future to only include necessary fields.
|
|
89
|
+
*/
|
|
83
90
|
setAccessToken(token) {
|
|
84
91
|
try {
|
|
85
92
|
const decoded = decodeToken(token);
|
|
@@ -90,6 +97,13 @@ export class CortiDictation extends LitElement {
|
|
|
90
97
|
throw new Error('Invalid token');
|
|
91
98
|
}
|
|
92
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Sets the authentication configuration and returns the server configuration.
|
|
102
|
+
*
|
|
103
|
+
* NOTE: We decode tokens here only for backward compatibility in return values.
|
|
104
|
+
* The SDK now handles token parsing internally, so this return value should be
|
|
105
|
+
* reduced in the future to only include necessary fields.
|
|
106
|
+
*/
|
|
93
107
|
async setAuthConfig(config) {
|
|
94
108
|
try {
|
|
95
109
|
const initialToken = 'accessToken' in config
|
|
@@ -99,11 +113,9 @@ export class CortiDictation extends LitElement {
|
|
|
99
113
|
typeof initialToken.accessToken !== 'string') {
|
|
100
114
|
throw new Error('Access token is required and must be a string');
|
|
101
115
|
}
|
|
102
|
-
//
|
|
116
|
+
// Decode tokens only for return value compatibility
|
|
117
|
+
// The SDK handles its own token parsing internally
|
|
103
118
|
const decoded = decodeToken(initialToken.accessToken);
|
|
104
|
-
const refreshDecoded = initialToken.refreshToken
|
|
105
|
-
? decodeToken(initialToken.refreshToken)
|
|
106
|
-
: undefined;
|
|
107
119
|
if (!decoded) {
|
|
108
120
|
throw new Error('Invalid token format');
|
|
109
121
|
}
|
|
@@ -111,9 +123,7 @@ export class CortiDictation extends LitElement {
|
|
|
111
123
|
environment: decoded.environment,
|
|
112
124
|
tenant: decoded.tenant,
|
|
113
125
|
accessToken: initialToken.accessToken,
|
|
114
|
-
expiresAt: decoded.expiresAt,
|
|
115
126
|
refreshToken: config.refreshToken,
|
|
116
|
-
refreshExpiresAt: refreshDecoded?.expiresAt,
|
|
117
127
|
refreshAccessToken: async (refreshToken) => {
|
|
118
128
|
try {
|
|
119
129
|
if (!config.refreshAccessToken) {
|
|
@@ -124,14 +134,8 @@ export class CortiDictation extends LitElement {
|
|
|
124
134
|
};
|
|
125
135
|
}
|
|
126
136
|
const response = await config.refreshAccessToken(refreshToken);
|
|
127
|
-
const decoded = decodeToken(response.accessToken);
|
|
128
|
-
const refreshDecoded = response.refreshToken
|
|
129
|
-
? decodeToken(response.refreshToken)
|
|
130
|
-
: undefined;
|
|
131
137
|
if (this._serverConfig) {
|
|
132
138
|
this._serverConfig.accessToken = response.accessToken;
|
|
133
|
-
this._serverConfig.expiresAt = decoded?.expiresAt;
|
|
134
|
-
this._serverConfig.refreshExpiresAt = refreshDecoded?.expiresAt;
|
|
135
139
|
this._serverConfig.refreshToken = response.refreshToken;
|
|
136
140
|
}
|
|
137
141
|
return response;
|
|
@@ -144,7 +148,7 @@ export class CortiDictation extends LitElement {
|
|
|
144
148
|
return this._serverConfig;
|
|
145
149
|
}
|
|
146
150
|
catch (e) {
|
|
147
|
-
throw new Error('Invalid
|
|
151
|
+
throw new Error('Invalid config');
|
|
148
152
|
}
|
|
149
153
|
}
|
|
150
154
|
get selectedDevice() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CortiDictation.js","sourceRoot":"","sources":["../src/CortiDictation.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Corti } from '@corti/sdk';\n\n// corti-dictation.ts\nimport { html, LitElement } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { RecorderManager } from './RecorderManager.js';\nimport './components/settings-menu.js';\nimport './components/audio-visualiser.js';\nimport './icons/icons.js';\nimport ThemeStyles from './styles/theme.js';\nimport ButtonStyles from './styles/buttons.js';\nimport ComponentStyles from './styles/ComponentStyles.js';\n\nimport type { RecordingState, ServerConfig } from './types.js';\nimport { DEFAULT_DICTATION_CONFIG, LANGUAGES_SUPPORTED } from './constants.js';\nimport CalloutStyles from './styles/callout.js';\nimport { decodeToken } from './utils.js';\n\nexport class CortiDictation extends LitElement {\n static styles = [ButtonStyles, ThemeStyles, ComponentStyles, CalloutStyles];\n\n @property({ type: Object })\n dictationConfig: Corti.TranscribeConfig = DEFAULT_DICTATION_CONFIG;\n\n @property({ type: Array })\n languagesSupported: Corti.TranscribeSupportedLanguage[] = LANGUAGES_SUPPORTED;\n\n @property({ type: Boolean })\n debug_displayAudio: boolean = false;\n\n @state()\n private _serverConfig: ServerConfig | undefined;\n\n @state()\n private _audioLevel: number = 0;\n\n @state()\n private _recordingState: RecordingState = 'stopped';\n\n @state()\n private _selectedDevice: MediaDeviceInfo | undefined;\n\n @state()\n private _devices: MediaDeviceInfo[] = [];\n\n private recorderManager = new RecorderManager();\n\n async connectedCallback() {\n super.connectedCallback();\n const devices = await this.recorderManager.initialize();\n if (devices.selectedDevice) {\n this._selectedDevice = this.recorderManager.selectedDevice;\n this._devices = this.recorderManager.devices;\n this.dispatchEvent(new CustomEvent('ready'));\n }\n\n // Map event names to any extra handling logic\n const eventHandlers: Record<string, (e: CustomEvent) => void> = {\n 'recording-state-changed': e => {\n this._recordingState = e.detail.state;\n },\n 'devices-changed': () => {\n this._devices = [...this.recorderManager.devices];\n this.requestUpdate();\n },\n 'audio-level-changed': e => {\n this._audioLevel = e.detail.audioLevel;\n this.requestUpdate();\n },\n };\n\n const eventsToRelay = [\n 'recording-state-changed',\n 'recording-devices-changed',\n 'audio-level-changed',\n 'error',\n 'transcript',\n 'command',\n 'ready',\n 'usage',\n 'stream-closed'\n ];\n\n eventsToRelay.forEach(eventName => {\n this.recorderManager.addEventListener(eventName, (e: Event) => {\n const customEvent = e as CustomEvent;\n // Perform any additional handling if defined\n if (eventHandlers[eventName]) {\n eventHandlers[eventName](customEvent);\n }\n // Re-dispatch the event from the component\n this.dispatchEvent(\n new CustomEvent(eventName, {\n detail: customEvent.detail,\n bubbles: eventName !== 'error',\n composed: true,\n }),\n );\n });\n });\n }\n\n public toggleRecording() {\n this._toggleRecording();\n }\n\n public setAccessToken(token: string) {\n try {\n const decoded = decodeToken(token);\n this._serverConfig = decoded;\n return decoded;\n } catch (e) {\n throw new Error('Invalid token');\n }\n }\n\n public async setAuthConfig(\n config: Corti.BearerOptions,\n ): Promise<ServerConfig> {\n try {\n const initialToken =\n 'accessToken' in config\n ? { accessToken: config.accessToken, refreshToken: config.refreshToken }\n : await config.refreshAccessToken();\n\n if (\n !initialToken?.accessToken ||\n typeof initialToken.accessToken !== 'string'\n ) {\n throw new Error('Access token is required and must be a string');\n }\n\n // Remove all the parsing and just pass parameters when we implement token decoding on the SDK side\n const decoded = decodeToken(initialToken.accessToken);\n const refreshDecoded = initialToken.refreshToken\n ? decodeToken(initialToken.refreshToken)\n : undefined;\n\n if (!decoded) {\n throw new Error('Invalid token format');\n }\n\n this._serverConfig = {\n environment: decoded.environment,\n tenant: decoded.tenant,\n accessToken: initialToken.accessToken,\n expiresAt: decoded.expiresAt,\n refreshToken: config.refreshToken,\n refreshExpiresAt: refreshDecoded?.expiresAt,\n refreshAccessToken: async (refreshToken?: string) => {\n try {\n if (!config.refreshAccessToken) {\n return {\n accessToken: this._serverConfig?.accessToken || 'no_token',\n expiresIn: Infinity,\n refreshToken,\n };\n }\n\n const response = await config.refreshAccessToken(refreshToken);\n const decoded = decodeToken(response.accessToken);\n const refreshDecoded = response.refreshToken\n ? decodeToken(response.refreshToken)\n : undefined;\n\n if (this._serverConfig) {\n this._serverConfig.accessToken = response.accessToken;\n this._serverConfig.expiresAt = decoded?.expiresAt;\n this._serverConfig.refreshExpiresAt = refreshDecoded?.expiresAt;\n this._serverConfig.refreshToken = response.refreshToken;\n }\n\n return response;\n } catch (e) {\n throw new Error('Error when refreshing access token');\n }\n },\n };\n\n return this._serverConfig;\n } catch (e) {\n throw new Error('Invalid token');\n }\n }\n\n public get selectedDevice(): MediaDeviceInfo | null {\n return this.recorderManager.selectedDevice || null;\n }\n\n public get recordingState(): RecordingState {\n return this._recordingState;\n }\n\n public get devices(): MediaDeviceInfo[] {\n return this._devices;\n }\n\n public async setRecordingDevice(device: MediaDeviceInfo) {\n this.recorderManager.selectedDevice = device;\n this._selectedDevice = device;\n if (!this._serverConfig) return;\n if (this._recordingState === 'recording') {\n await this.recorderManager.stopRecording();\n await this.recorderManager.startRecording({\n dictationConfig: this.dictationConfig,\n serverConfig: this._serverConfig,\n });\n }\n }\n\n public setPrimaryLanguage(language: string) {\n if (LANGUAGES_SUPPORTED.includes(language)) {\n this.dictationConfig = {\n ...this.dictationConfig,\n primaryLanguage: language,\n };\n\n // If recording is in progress, restart to apply the language change\n if (this._serverConfig && this._recordingState === 'recording') {\n this.recorderManager.stopRecording();\n this.recorderManager.startRecording({\n dictationConfig: this.dictationConfig,\n serverConfig: this._serverConfig,\n debug_displayAudio: this.debug_displayAudio,\n });\n }\n }\n }\n\n _toggleRecording() {\n if (!this._serverConfig) return;\n if (this._recordingState === 'recording') {\n this.recorderManager.stopRecording();\n } else if (this._recordingState === 'stopped') {\n this.recorderManager.startRecording({\n dictationConfig: this.dictationConfig,\n serverConfig: this._serverConfig,\n debug_displayAudio: this.debug_displayAudio,\n });\n }\n }\n\n // Handle device change events if needed\n async _onRecordingDevicesChanged(event: Event) {\n const customEvent = event as CustomEvent;\n this.setRecordingDevice(customEvent.detail.selectedDevice);\n }\n\n // Handle language change events\n _onLanguageChanged(event: Event) {\n const customEvent = event as CustomEvent;\n const language = customEvent.detail.language;\n if (language) {\n this.setPrimaryLanguage(language);\n }\n }\n\n render() {\n if (!this._serverConfig) {\n return html` <div style=\"display: none\"></div> `;\n }\n\n const isLoading =\n this._recordingState === 'initializing' ||\n this._recordingState === 'stopping';\n const isRecording = this._recordingState === 'recording';\n return html`\n <div class=\"wrapper\">\n <button\n @click=${this._toggleRecording}\n class=${isRecording ? 'red' : 'accent'}\n >\n ${isLoading\n ? html` <icon-loading-spinner></icon-loading-spinner>`\n : isRecording\n ? html` <icon-recording></icon-recording>`\n : html` <icon-mic-on></icon-mic-on>`}\n <audio-visualiser\n .level=${this._audioLevel}\n .active=${isRecording}\n ></audio-visualiser>\n </button>\n\n <settings-menu\n .selectedDevice=${this._selectedDevice}\n .selectedLanguage=${this.dictationConfig.primaryLanguage}\n ?settingsDisabled=${this._recordingState !== 'stopped'}\n @recording-devices-changed=${this._onRecordingDevicesChanged}\n @language-changed=${this._onLanguageChanged}\n ></settings-menu>\n </div>\n `;\n }\n}\n\nexport default CortiDictation;\n"]}
|
|
1
|
+
{"version":3,"file":"CortiDictation.js","sourceRoot":"","sources":["../src/CortiDictation.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Corti } from '@corti/sdk';\n\n// corti-dictation.ts\nimport { html, LitElement } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { RecorderManager } from './RecorderManager.js';\nimport './components/settings-menu.js';\nimport './components/audio-visualiser.js';\nimport './icons/icons.js';\nimport ThemeStyles from './styles/theme.js';\nimport ButtonStyles from './styles/buttons.js';\nimport ComponentStyles from './styles/ComponentStyles.js';\n\nimport type { RecordingState, ServerConfig } from './types.js';\nimport { DEFAULT_DICTATION_CONFIG, LANGUAGES_SUPPORTED } from './constants.js';\nimport CalloutStyles from './styles/callout.js';\nimport { decodeToken } from './utils.js';\n\nexport class CortiDictation extends LitElement {\n static styles = [ButtonStyles, ThemeStyles, ComponentStyles, CalloutStyles];\n\n @property({ type: Object })\n dictationConfig: Corti.TranscribeConfig = DEFAULT_DICTATION_CONFIG;\n\n @property({ type: Array })\n languagesSupported: Corti.TranscribeSupportedLanguage[] = LANGUAGES_SUPPORTED;\n\n @property({ type: Boolean })\n debug_displayAudio: boolean = false;\n\n @state()\n private _serverConfig: ServerConfig | undefined;\n\n @state()\n private _audioLevel: number = 0;\n\n @state()\n private _recordingState: RecordingState = 'stopped';\n\n @state()\n private _selectedDevice: MediaDeviceInfo | undefined;\n\n @state()\n private _devices: MediaDeviceInfo[] = [];\n\n private recorderManager = new RecorderManager();\n\n async connectedCallback() {\n super.connectedCallback();\n const devices = await this.recorderManager.initialize();\n if (devices.selectedDevice) {\n this._selectedDevice = this.recorderManager.selectedDevice;\n this._devices = this.recorderManager.devices;\n this.dispatchEvent(new CustomEvent('ready'));\n }\n\n // Map event names to any extra handling logic\n const eventHandlers: Record<string, (e: CustomEvent) => void> = {\n 'recording-state-changed': e => {\n this._recordingState = e.detail.state;\n },\n 'devices-changed': () => {\n this._devices = [...this.recorderManager.devices];\n this.requestUpdate();\n },\n 'audio-level-changed': e => {\n this._audioLevel = e.detail.audioLevel;\n this.requestUpdate();\n },\n };\n\n const eventsToRelay = [\n 'recording-state-changed',\n 'recording-devices-changed',\n 'audio-level-changed',\n 'error',\n 'transcript',\n 'command',\n 'ready',\n 'usage',\n 'stream-closed',\n ];\n\n eventsToRelay.forEach(eventName => {\n this.recorderManager.addEventListener(eventName, (e: Event) => {\n const customEvent = e as CustomEvent;\n // Perform any additional handling if defined\n if (eventHandlers[eventName]) {\n eventHandlers[eventName](customEvent);\n }\n // Re-dispatch the event from the component\n this.dispatchEvent(\n new CustomEvent(eventName, {\n detail: customEvent.detail,\n bubbles: eventName !== 'error',\n composed: true,\n }),\n );\n });\n });\n }\n\n public toggleRecording() {\n this._toggleRecording();\n }\n\n /**\n * Sets the access token and returns the server configuration.\n *\n * NOTE: We decode the token here only for backward compatibility in return values.\n * The SDK now handles token parsing internally, so this return value should be\n * reduced in the future to only include necessary fields.\n */\n public setAccessToken(token: string) {\n try {\n const decoded = decodeToken(token);\n this._serverConfig = decoded;\n return decoded;\n } catch (e) {\n throw new Error('Invalid token');\n }\n }\n\n /**\n * Sets the authentication configuration and returns the server configuration.\n *\n * NOTE: We decode tokens here only for backward compatibility in return values.\n * The SDK now handles token parsing internally, so this return value should be\n * reduced in the future to only include necessary fields.\n */\n public async setAuthConfig(\n config: Corti.BearerOptions,\n ): Promise<ServerConfig> {\n try {\n const initialToken =\n 'accessToken' in config\n ? { accessToken: config.accessToken, refreshToken: config.refreshToken }\n : await config.refreshAccessToken();\n\n if (\n !initialToken?.accessToken ||\n typeof initialToken.accessToken !== 'string'\n ) {\n throw new Error('Access token is required and must be a string');\n }\n\n // Decode tokens only for return value compatibility\n // The SDK handles its own token parsing internally\n const decoded = decodeToken(initialToken.accessToken);\n\n if (!decoded) {\n throw new Error('Invalid token format');\n }\n\n this._serverConfig = {\n environment: decoded.environment,\n tenant: decoded.tenant,\n accessToken: initialToken.accessToken,\n refreshToken: config.refreshToken,\n refreshAccessToken: async (refreshToken?: string) => {\n try {\n if (!config.refreshAccessToken) {\n return {\n accessToken: this._serverConfig?.accessToken || 'no_token',\n expiresIn: Infinity,\n refreshToken,\n };\n }\n\n const response = await config.refreshAccessToken(refreshToken);\n\n if (this._serverConfig) {\n this._serverConfig.accessToken = response.accessToken;\n this._serverConfig.refreshToken = response.refreshToken;\n }\n\n return response;\n } catch (e) {\n throw new Error('Error when refreshing access token');\n }\n },\n };\n\n return this._serverConfig;\n } catch (e) {\n throw new Error('Invalid config');\n }\n }\n\n public get selectedDevice(): MediaDeviceInfo | null {\n return this.recorderManager.selectedDevice || null;\n }\n\n public get recordingState(): RecordingState {\n return this._recordingState;\n }\n\n public get devices(): MediaDeviceInfo[] {\n return this._devices;\n }\n\n public async setRecordingDevice(device: MediaDeviceInfo) {\n this.recorderManager.selectedDevice = device;\n this._selectedDevice = device;\n if (!this._serverConfig) return;\n if (this._recordingState === 'recording') {\n await this.recorderManager.stopRecording();\n await this.recorderManager.startRecording({\n dictationConfig: this.dictationConfig,\n serverConfig: this._serverConfig,\n });\n }\n }\n\n public setPrimaryLanguage(language: string) {\n if (LANGUAGES_SUPPORTED.includes(language)) {\n this.dictationConfig = {\n ...this.dictationConfig,\n primaryLanguage: language,\n };\n\n // If recording is in progress, restart to apply the language change\n if (this._serverConfig && this._recordingState === 'recording') {\n this.recorderManager.stopRecording();\n this.recorderManager.startRecording({\n dictationConfig: this.dictationConfig,\n serverConfig: this._serverConfig,\n debug_displayAudio: this.debug_displayAudio,\n });\n }\n }\n }\n\n _toggleRecording() {\n if (!this._serverConfig) return;\n if (this._recordingState === 'recording') {\n this.recorderManager.stopRecording();\n } else if (this._recordingState === 'stopped') {\n this.recorderManager.startRecording({\n dictationConfig: this.dictationConfig,\n serverConfig: this._serverConfig,\n debug_displayAudio: this.debug_displayAudio,\n });\n }\n }\n\n // Handle device change events if needed\n async _onRecordingDevicesChanged(event: Event) {\n const customEvent = event as CustomEvent;\n this.setRecordingDevice(customEvent.detail.selectedDevice);\n }\n\n // Handle language change events\n _onLanguageChanged(event: Event) {\n const customEvent = event as CustomEvent;\n const language = customEvent.detail.language;\n if (language) {\n this.setPrimaryLanguage(language);\n }\n }\n\n render() {\n if (!this._serverConfig) {\n return html` <div style=\"display: none\"></div> `;\n }\n\n const isLoading =\n this._recordingState === 'initializing' ||\n this._recordingState === 'stopping';\n const isRecording = this._recordingState === 'recording';\n return html`\n <div class=\"wrapper\">\n <button\n @click=${this._toggleRecording}\n class=${isRecording ? 'red' : 'accent'}\n >\n ${isLoading\n ? html` <icon-loading-spinner></icon-loading-spinner>`\n : isRecording\n ? html` <icon-recording></icon-recording>`\n : html` <icon-mic-on></icon-mic-on>`}\n <audio-visualiser\n .level=${this._audioLevel}\n .active=${isRecording}\n ></audio-visualiser>\n </button>\n\n <settings-menu\n .selectedDevice=${this._selectedDevice}\n .selectedLanguage=${this.dictationConfig.primaryLanguage}\n ?settingsDisabled=${this._recordingState !== 'stopped'}\n @recording-devices-changed=${this._onRecordingDevicesChanged}\n @language-changed=${this._onLanguageChanged}\n ></settings-menu>\n </div>\n `;\n }\n}\n\nexport default CortiDictation;\n"]}
|
package/dist/DictationService.js
CHANGED
|
@@ -6,24 +6,14 @@ export class DictationService extends EventTarget {
|
|
|
6
6
|
this.mediaRecorder = new MediaRecorder(mediaStream);
|
|
7
7
|
this.serverConfig = serverConfig;
|
|
8
8
|
this.dictationConfig = dictationConfig;
|
|
9
|
-
|
|
10
|
-
// We're forced to convert from expiresAt/refreshExpiresAt here,
|
|
9
|
+
// We're forced to remove from expiresIn/refreshExpiresIn here,
|
|
11
10
|
// because we recreate connection every time we connect
|
|
12
|
-
// => access_token will be called every time if we don't store it
|
|
13
11
|
// => it makes expiresIn (we receive from API) out of date
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
? refreshExpiresAt - now
|
|
18
|
-
: undefined;
|
|
12
|
+
const { expiresIn, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
13
|
+
refreshExpiresIn, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
14
|
+
...authConfig } = serverConfig;
|
|
19
15
|
this.cortiClient = new CortiClient({
|
|
20
|
-
|
|
21
|
-
tenantName,
|
|
22
|
-
auth: {
|
|
23
|
-
expiresIn,
|
|
24
|
-
refreshExpiresIn,
|
|
25
|
-
...authConfig,
|
|
26
|
-
},
|
|
16
|
+
auth: authConfig,
|
|
27
17
|
});
|
|
28
18
|
this.mediaRecorder.ondataavailable = event => {
|
|
29
19
|
if (this.webSocket?.readyState === WebSocket.OPEN) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DictationService.js","sourceRoot":"","sources":["../src/DictationService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAS,MAAM,YAAY,CAAC;AAGhD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAM7C,MAAM,OAAO,gBAAiB,SAAQ,WAAW;IAO/C,YACE,WAAwB,EACxB,EACE,eAAe,EACf,YAAY,GAC4D;QAE1E,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,aAAa,GAAG,IAAI,aAAa,CAAC,WAAW,CAAC,CAAC;QACpD,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;QAEvC
|
|
1
|
+
{"version":3,"file":"DictationService.js","sourceRoot":"","sources":["../src/DictationService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAS,MAAM,YAAY,CAAC;AAGhD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAM7C,MAAM,OAAO,gBAAiB,SAAQ,WAAW;IAO/C,YACE,WAAwB,EACxB,EACE,eAAe,EACf,YAAY,GAC4D;QAE1E,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,aAAa,GAAG,IAAI,aAAa,CAAC,WAAW,CAAC,CAAC;QACpD,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;QAEvC,+DAA+D;QAC/D,uDAAuD;QACvD,0DAA0D;QAC1D,MAAM,EACJ,SAAS,EAAE,wDAAwD;QACnE,gBAAgB,EAAE,wDAAwD;QAC1E,GAAG,UAAU,EACd,GAAG,YAAY,CAAC;QAEjB,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,CAAC;YACjC,IAAI,EAAE,UAAU;SACjB,CAAC,CAAC;QAEH,IAAI,CAAC,aAAa,CAAC,eAAe,GAAG,KAAK,CAAC,EAAE;YAC3C,IAAI,IAAI,CAAC,SAAS,EAAE,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;gBAClD,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACvC,CAAC;QACH,CAAC,CAAC;IACJ,CAAC;IAEO,mBAAmB,CAAC,SAAiB,EAAE,MAAgB;QAC7D,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,SAAS,EAAE;YACzB,MAAM;YACN,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;SACf,CAAC,CACH,CAAC;IACJ,CAAC;IAEM,KAAK,CAAC,cAAc;QACzB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,OAAO,EAAE;gBACvB,MAAM,EAAE,eAAe;gBACvB,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,IAAI;aACf,CAAC,CACH,CAAC;YACF,OAAO;QACT,CAAC;QAED,IAAI,CAAC,SAAS,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC;YACzD,aAAa,EAAE,IAAI,CAAC,eAAe;SACpC,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE;YACrC,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;gBACrB,KAAK,iBAAiB;oBACpB,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;oBAC9B,MAAM;gBACR,KAAK,YAAY;oBACf,IAAI,CAAC,mBAAmB,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;oBAChD,MAAM;gBACR,KAAK,SAAS;oBACZ,IAAI,CAAC,mBAAmB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;oBAC7C,MAAM;gBACR,KAAK,OAAO;oBACV,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;oBAC3C,MAAM;gBACR;oBACE,OAAO,CAAC,IAAI,CAAC,2BAA2B,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;oBACxD,MAAM;YACV,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE;YACjC,IAAI,CAAC,aAAa,EAAE,CAAC;YAErB,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE;YACjC,IAAI,CAAC,mBAAmB,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;IACL,CAAC;IAEM,KAAK,CAAC,aAAa;QACxB,IAAI,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC;QAE3B,IAAI,IAAI,CAAC,SAAS,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;YACjD,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;gBACrB,IAAI,EAAE,KAAK;aACZ,CAAC,CAAC;QACL,CAAC;QAED,MAAM,OAAO,GAAmB,UAAU,CAAC,GAAG,EAAE;YAC9C,IAAI,IAAI,CAAC,SAAS,EAAE,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;gBAClD,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;YACzB,CAAC;QACH,CAAC,EAAE,KAAK,CAAC,CAAC;QAEV,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACnC,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,IAAI,CAAC,mBAAmB,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["import { CortiClient, Corti } from '@corti/sdk';\n\nimport type { ServerConfig } from './types.js';\nimport { getErrorMessage } from './utils.js';\n\ntype TranscribeSocket = Awaited<\n ReturnType<CortiClient['transcribe']['connect']>\n>;\n\nexport class DictationService extends EventTarget {\n private mediaRecorder: MediaRecorder;\n private webSocket!: TranscribeSocket;\n private serverConfig: ServerConfig;\n private dictationConfig: Corti.TranscribeConfig;\n private cortiClient: CortiClient;\n\n constructor(\n mediaStream: MediaStream,\n {\n dictationConfig,\n serverConfig,\n }: { dictationConfig: Corti.TranscribeConfig; serverConfig: ServerConfig },\n ) {\n super();\n this.mediaRecorder = new MediaRecorder(mediaStream);\n this.serverConfig = serverConfig;\n this.dictationConfig = dictationConfig;\n\n // We're forced to remove from expiresIn/refreshExpiresIn here,\n // because we recreate connection every time we connect\n // => it makes expiresIn (we receive from API) out of date\n const {\n expiresIn, // eslint-disable-line @typescript-eslint/no-unused-vars\n refreshExpiresIn, // eslint-disable-line @typescript-eslint/no-unused-vars\n ...authConfig\n } = serverConfig;\n\n this.cortiClient = new CortiClient({\n auth: authConfig,\n });\n\n this.mediaRecorder.ondataavailable = event => {\n if (this.webSocket?.readyState === WebSocket.OPEN) {\n this.webSocket.sendAudio(event.data);\n }\n };\n }\n\n private dispatchCustomEvent(eventName: string, detail?: unknown): void {\n this.dispatchEvent(\n new CustomEvent(eventName, {\n detail,\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n public async startRecording() {\n if (!this.serverConfig) {\n this.dispatchEvent(\n new CustomEvent('error', {\n detail: 'Invalid token',\n bubbles: true,\n composed: true,\n }),\n );\n return;\n }\n\n this.webSocket = await this.cortiClient.transcribe.connect({\n configuration: this.dictationConfig,\n });\n\n this.webSocket.on('message', message => {\n switch (message.type) {\n case 'CONFIG_ACCEPTED':\n this.mediaRecorder.start(250);\n break;\n case 'transcript':\n this.dispatchCustomEvent('transcript', message);\n break;\n case 'command':\n this.dispatchCustomEvent('command', message);\n break;\n case 'usage':\n this.dispatchCustomEvent('usage', message);\n break;\n default:\n console.warn(`Unhandled message type: ${message.type}`);\n break;\n }\n });\n\n this.webSocket.on('error', event => {\n this.stopRecording();\n\n this.dispatchCustomEvent('error', getErrorMessage(event));\n });\n\n this.webSocket.on('close', event => {\n this.dispatchCustomEvent('stream-closed', event);\n });\n }\n\n public async stopRecording(): Promise<void> {\n this.mediaRecorder?.stop();\n\n if (this.webSocket.readyState === WebSocket.OPEN) {\n this.webSocket.sendEnd({\n type: 'end',\n });\n }\n\n const timeout: NodeJS.Timeout = setTimeout(() => {\n if (this.webSocket?.readyState === WebSocket.OPEN) {\n this.webSocket.close();\n }\n }, 10000);\n\n this.webSocket.on('close', (event) => {\n clearTimeout(timeout);\n this.dispatchCustomEvent('stream-closed', event);\n });\n }\n}\n"]}
|