@corti/dictation-web 0.0.0-test.571.1 → 0.0.0-test.571.2
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/dist/bundle.js +22 -9
- package/dist/components/recording-button.d.ts +2 -1
- package/dist/components/recording-button.js +22 -12
- package/dist/components/recording-button.js.map +1 -1
- package/dist/controllers/keybinding-controller.js +3 -0
- package/dist/controllers/keybinding-controller.js.map +1 -1
- package/dist/package.json +87 -7
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +1 -1
- package/dist/CortiDictation.d.ts +0 -55
- package/dist/CortiDictation.js +0 -303
- package/dist/CortiDictation.js.map +0 -1
- package/dist/DictationService.d.ts +0 -16
- package/dist/DictationService.js +0 -88
- package/dist/DictationService.js.map +0 -1
- package/dist/RecorderManager.d.ts +0 -25
- package/dist/RecorderManager.js +0 -145
- package/dist/RecorderManager.js.map +0 -1
- package/dist/audioService.d.ts +0 -6
- package/dist/audioService.js +0 -21
- package/dist/audioService.js.map +0 -1
- package/dist/controllers/DictationController.d.ts +0 -35
- package/dist/controllers/DictationController.js +0 -130
- package/dist/controllers/DictationController.js.map +0 -1
- package/dist/controllers/MediaController.d.ts +0 -31
- package/dist/controllers/MediaController.js +0 -99
- package/dist/controllers/MediaController.js.map +0 -1
- package/dist/src/components/audio-visualiser.d.ts +0 -14
- package/dist/src/components/audio-visualiser.js +0 -57
- package/dist/src/components/audio-visualiser.js.map +0 -1
- package/dist/src/components/corti-dictation.d.ts +0 -123
- package/dist/src/components/corti-dictation.js +0 -224
- package/dist/src/components/corti-dictation.js.map +0 -1
- package/dist/src/components/device-selector.d.ts +0 -24
- package/dist/src/components/device-selector.js +0 -106
- package/dist/src/components/device-selector.js.map +0 -1
- package/dist/src/components/language-selector.d.ts +0 -24
- package/dist/src/components/language-selector.js +0 -100
- package/dist/src/components/language-selector.js.map +0 -1
- package/dist/src/components/recording-button.d.ts +0 -37
- package/dist/src/components/recording-button.js +0 -203
- package/dist/src/components/recording-button.js.map +0 -1
- package/dist/src/components/settings-menu.d.ts +0 -16
- package/dist/src/components/settings-menu.js +0 -80
- package/dist/src/components/settings-menu.js.map +0 -1
- package/dist/src/constants.d.ts +0 -4
- package/dist/src/constants.js +0 -37
- package/dist/src/constants.js.map +0 -1
- package/dist/src/contexts/dictation-context.d.ts +0 -97
- package/dist/src/contexts/dictation-context.js +0 -208
- package/dist/src/contexts/dictation-context.js.map +0 -1
- package/dist/src/controllers/DictationController.d.ts +0 -35
- package/dist/src/controllers/DictationController.js +0 -130
- package/dist/src/controllers/DictationController.js.map +0 -1
- package/dist/src/controllers/MediaController.d.ts +0 -31
- package/dist/src/controllers/MediaController.js +0 -99
- package/dist/src/controllers/MediaController.js.map +0 -1
- package/dist/src/icons/icons.d.ts +0 -17
- package/dist/src/icons/icons.js +0 -158
- package/dist/src/icons/icons.js.map +0 -1
- package/dist/src/styles/ComponentStyles.d.ts +0 -2
- package/dist/src/styles/ComponentStyles.js +0 -18
- package/dist/src/styles/ComponentStyles.js.map +0 -1
- package/dist/src/styles/audio-visualiser.d.ts +0 -2
- package/dist/src/styles/audio-visualiser.js +0 -33
- package/dist/src/styles/audio-visualiser.js.map +0 -1
- package/dist/src/styles/buttons.d.ts +0 -2
- package/dist/src/styles/buttons.js +0 -52
- package/dist/src/styles/buttons.js.map +0 -1
- package/dist/src/styles/callout.d.ts +0 -2
- package/dist/src/styles/callout.js +0 -23
- package/dist/src/styles/callout.js.map +0 -1
- package/dist/src/styles/default-theme.d.ts +0 -2
- package/dist/src/styles/default-theme.js +0 -50
- package/dist/src/styles/default-theme.js.map +0 -1
- package/dist/src/styles/recording-button.d.ts +0 -2
- package/dist/src/styles/recording-button.js +0 -8
- package/dist/src/styles/recording-button.js.map +0 -1
- package/dist/src/styles/select.d.ts +0 -2
- package/dist/src/styles/select.js +0 -36
- package/dist/src/styles/select.js.map +0 -1
- package/dist/src/styles/settings-menu.d.ts +0 -2
- package/dist/src/styles/settings-menu.js +0 -34
- package/dist/src/styles/settings-menu.js.map +0 -1
- package/dist/src/types.d.ts +0 -7
- package/dist/src/types.js +0 -2
- package/dist/src/types.js.map +0 -1
- package/dist/src/utils/auth.d.ts +0 -9
- package/dist/src/utils/auth.js +0 -21
- package/dist/src/utils/auth.js.map +0 -1
- package/dist/src/utils/converters.d.ts +0 -4
- package/dist/src/utils/converters.js +0 -8
- package/dist/src/utils/converters.js.map +0 -1
- package/dist/src/utils/devices.d.ts +0 -26
- package/dist/src/utils/devices.js +0 -53
- package/dist/src/utils/devices.js.map +0 -1
- package/dist/src/utils/events.d.ts +0 -44
- package/dist/src/utils/events.js +0 -88
- package/dist/src/utils/events.js.map +0 -1
- package/dist/src/utils/languages.d.ts +0 -7
- package/dist/src/utils/languages.js +0 -29
- package/dist/src/utils/languages.js.map +0 -1
- package/dist/src/utils/media.d.ts +0 -6
- package/dist/src/utils/media.js +0 -39
- package/dist/src/utils/media.js.map +0 -1
- package/dist/src/utils/token.d.ts +0 -13
- package/dist/src/utils/token.js +0 -60
- package/dist/src/utils/token.js.map +0 -1
- package/dist/src/utils/validation.d.ts +0 -1
- package/dist/src/utils/validation.js +0 -7
- package/dist/src/utils/validation.js.map +0 -1
- package/dist/stories/audio-visualiser.stories.d.ts +0 -39
- package/dist/stories/audio-visualiser.stories.js +0 -71
- package/dist/stories/audio-visualiser.stories.js.map +0 -1
- package/dist/stories/corti-dictation.stories.d.ts +0 -27
- package/dist/stories/corti-dictation.stories.js +0 -129
- package/dist/stories/corti-dictation.stories.js.map +0 -1
- package/dist/stories/device-selector.stories.d.ts +0 -18
- package/dist/stories/device-selector.stories.js +0 -84
- package/dist/stories/device-selector.stories.js.map +0 -1
- package/dist/stories/language-selector.stories.d.ts +0 -18
- package/dist/stories/language-selector.stories.js +0 -53
- package/dist/stories/language-selector.stories.js.map +0 -1
- package/dist/stories/recording-button.stories.d.ts +0 -27
- package/dist/stories/recording-button.stories.js +0 -90
- package/dist/stories/recording-button.stories.js.map +0 -1
- package/dist/stories/settings-menu.stories.d.ts +0 -23
- package/dist/stories/settings-menu.stories.js +0 -156
- package/dist/stories/settings-menu.stories.js.map +0 -1
- package/dist/styles/ComponentStyles.d.ts +0 -2
- package/dist/styles/ComponentStyles.js +0 -18
- package/dist/styles/ComponentStyles.js.map +0 -1
- package/dist/styles/default-theme.d.ts +0 -2
- package/dist/styles/default-theme.js +0 -14
- package/dist/styles/default-theme.js.map +0 -1
- package/dist/styles/theme.d.ts +0 -2
- package/dist/styles/theme.js +0 -56
- package/dist/styles/theme.js.map +0 -1
- package/dist/tsconfig.stories.tsbuildinfo +0 -1
- package/dist/utils.d.ts +0 -59
- package/dist/utils.js +0 -179
- package/dist/utils.js.map +0 -1
package/dist/CortiDictation.js
DELETED
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
};
|
|
7
|
-
// corti-dictation.ts
|
|
8
|
-
import { html, LitElement } from 'lit';
|
|
9
|
-
import { property, state } from 'lit/decorators.js';
|
|
10
|
-
import { RecorderManager } from './RecorderManager.js';
|
|
11
|
-
import './components/settings-menu.js';
|
|
12
|
-
import './components/audio-visualiser.js';
|
|
13
|
-
import './icons/icons.js';
|
|
14
|
-
import ThemeStyles from './styles/theme.js';
|
|
15
|
-
import ButtonStyles from './styles/buttons.js';
|
|
16
|
-
import ComponentStyles from './styles/ComponentStyles.js';
|
|
17
|
-
import { DEFAULT_DICTATION_CONFIG, LANGUAGES_SUPPORTED } from './constants.js';
|
|
18
|
-
import CalloutStyles from './styles/callout.js';
|
|
19
|
-
import { decodeToken } from './utils.js';
|
|
20
|
-
export class CortiDictation extends LitElement {
|
|
21
|
-
constructor() {
|
|
22
|
-
super(...arguments);
|
|
23
|
-
this.dictationConfig = DEFAULT_DICTATION_CONFIG;
|
|
24
|
-
this.languagesSupported = LANGUAGES_SUPPORTED;
|
|
25
|
-
this.debug_displayAudio = false;
|
|
26
|
-
this.settingsEnabled = ["device", "language"];
|
|
27
|
-
this.preventButtonFocus = true;
|
|
28
|
-
this._audioLevel = 0;
|
|
29
|
-
this._recordingState = 'stopped';
|
|
30
|
-
this._devices = [];
|
|
31
|
-
this.recorderManager = new RecorderManager();
|
|
32
|
-
}
|
|
33
|
-
async connectedCallback() {
|
|
34
|
-
super.connectedCallback();
|
|
35
|
-
const devices = await this.recorderManager.initialize();
|
|
36
|
-
if (devices.selectedDevice) {
|
|
37
|
-
this._selectedDevice = this.recorderManager.selectedDevice;
|
|
38
|
-
this._devices = this.recorderManager.devices;
|
|
39
|
-
this.dispatchEvent(new CustomEvent('ready'));
|
|
40
|
-
}
|
|
41
|
-
// Map event names to any extra handling logic
|
|
42
|
-
const eventHandlers = {
|
|
43
|
-
'recording-state-changed': e => {
|
|
44
|
-
this._recordingState = e.detail.state;
|
|
45
|
-
},
|
|
46
|
-
'devices-changed': () => {
|
|
47
|
-
this._devices = [...this.recorderManager.devices];
|
|
48
|
-
this.requestUpdate();
|
|
49
|
-
},
|
|
50
|
-
'audio-level-changed': e => {
|
|
51
|
-
this._audioLevel = e.detail.audioLevel;
|
|
52
|
-
this.requestUpdate();
|
|
53
|
-
},
|
|
54
|
-
};
|
|
55
|
-
const eventsToRelay = [
|
|
56
|
-
'recording-state-changed',
|
|
57
|
-
'recording-devices-changed',
|
|
58
|
-
'audio-level-changed',
|
|
59
|
-
'error',
|
|
60
|
-
'transcript',
|
|
61
|
-
'command',
|
|
62
|
-
'ready',
|
|
63
|
-
'usage',
|
|
64
|
-
'stream-closed',
|
|
65
|
-
];
|
|
66
|
-
eventsToRelay.forEach(eventName => {
|
|
67
|
-
this.recorderManager.addEventListener(eventName, (e) => {
|
|
68
|
-
const customEvent = e;
|
|
69
|
-
// Perform any additional handling if defined
|
|
70
|
-
if (eventHandlers[eventName]) {
|
|
71
|
-
eventHandlers[eventName](customEvent);
|
|
72
|
-
}
|
|
73
|
-
// Re-dispatch the event from the component
|
|
74
|
-
this.dispatchEvent(new CustomEvent(eventName, {
|
|
75
|
-
detail: customEvent.detail,
|
|
76
|
-
bubbles: eventName !== 'error',
|
|
77
|
-
composed: true,
|
|
78
|
-
}));
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
startRecording() {
|
|
83
|
-
if (!this._serverConfig)
|
|
84
|
-
return;
|
|
85
|
-
this.recorderManager.startRecording({
|
|
86
|
-
dictationConfig: this.dictationConfig,
|
|
87
|
-
serverConfig: this._serverConfig,
|
|
88
|
-
debug_displayAudio: this.debug_displayAudio,
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
stopRecording() {
|
|
92
|
-
this.recorderManager.stopRecording();
|
|
93
|
-
}
|
|
94
|
-
toggleRecording() {
|
|
95
|
-
if (this._recordingState === 'recording') {
|
|
96
|
-
this.stopRecording();
|
|
97
|
-
}
|
|
98
|
-
else if (this._recordingState === 'stopped') {
|
|
99
|
-
this.startRecording();
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Sets the access token and returns the server configuration.
|
|
104
|
-
*
|
|
105
|
-
* NOTE: We decode the token here only for backward compatibility in return values.
|
|
106
|
-
* The SDK now handles token parsing internally, so this return value should be
|
|
107
|
-
* reduced in the future to only include necessary fields.
|
|
108
|
-
*/
|
|
109
|
-
setAccessToken(token) {
|
|
110
|
-
try {
|
|
111
|
-
const decoded = decodeToken(token);
|
|
112
|
-
this._serverConfig = decoded;
|
|
113
|
-
return decoded;
|
|
114
|
-
}
|
|
115
|
-
catch (e) {
|
|
116
|
-
throw new Error('Invalid token');
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Sets the authentication configuration and returns the server configuration.
|
|
121
|
-
*
|
|
122
|
-
* NOTE: We decode tokens here only for backward compatibility in return values.
|
|
123
|
-
* The SDK now handles token parsing internally, so this return value should be
|
|
124
|
-
* reduced in the future to only include necessary fields.
|
|
125
|
-
*/
|
|
126
|
-
async setAuthConfig(config) {
|
|
127
|
-
try {
|
|
128
|
-
const initialToken = 'accessToken' in config
|
|
129
|
-
? { accessToken: config.accessToken, refreshToken: config.refreshToken }
|
|
130
|
-
: await config.refreshAccessToken();
|
|
131
|
-
if (!initialToken?.accessToken ||
|
|
132
|
-
typeof initialToken.accessToken !== 'string') {
|
|
133
|
-
throw new Error('Access token is required and must be a string');
|
|
134
|
-
}
|
|
135
|
-
// Decode tokens only for return value compatibility
|
|
136
|
-
// The SDK handles its own token parsing internally
|
|
137
|
-
const decoded = decodeToken(initialToken.accessToken);
|
|
138
|
-
if (!decoded) {
|
|
139
|
-
throw new Error('Invalid token format');
|
|
140
|
-
}
|
|
141
|
-
this._serverConfig = {
|
|
142
|
-
environment: decoded.environment,
|
|
143
|
-
tenant: decoded.tenant,
|
|
144
|
-
accessToken: initialToken.accessToken,
|
|
145
|
-
refreshToken: config.refreshToken,
|
|
146
|
-
refreshAccessToken: async (refreshToken) => {
|
|
147
|
-
try {
|
|
148
|
-
if (!config.refreshAccessToken) {
|
|
149
|
-
return {
|
|
150
|
-
accessToken: this._serverConfig?.accessToken || 'no_token',
|
|
151
|
-
expiresIn: Infinity,
|
|
152
|
-
refreshToken,
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
const response = await config.refreshAccessToken(refreshToken);
|
|
156
|
-
if (this._serverConfig) {
|
|
157
|
-
this._serverConfig.accessToken = response.accessToken;
|
|
158
|
-
this._serverConfig.refreshToken = response.refreshToken;
|
|
159
|
-
}
|
|
160
|
-
return response;
|
|
161
|
-
}
|
|
162
|
-
catch (e) {
|
|
163
|
-
throw new Error('Error when refreshing access token');
|
|
164
|
-
}
|
|
165
|
-
},
|
|
166
|
-
};
|
|
167
|
-
return this._serverConfig;
|
|
168
|
-
}
|
|
169
|
-
catch (e) {
|
|
170
|
-
throw new Error('Invalid config');
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
get selectedDevice() {
|
|
174
|
-
return this.recorderManager.selectedDevice || null;
|
|
175
|
-
}
|
|
176
|
-
get recordingState() {
|
|
177
|
-
return this._recordingState;
|
|
178
|
-
}
|
|
179
|
-
get devices() {
|
|
180
|
-
return this._devices;
|
|
181
|
-
}
|
|
182
|
-
async setRecordingDevice(device) {
|
|
183
|
-
this.recorderManager.selectedDevice = device;
|
|
184
|
-
this._selectedDevice = device;
|
|
185
|
-
if (!this._serverConfig)
|
|
186
|
-
return;
|
|
187
|
-
if (this._recordingState === 'recording') {
|
|
188
|
-
await this.recorderManager.stopRecording();
|
|
189
|
-
await this.recorderManager.startRecording({
|
|
190
|
-
dictationConfig: this.dictationConfig,
|
|
191
|
-
serverConfig: this._serverConfig,
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
setPrimaryLanguage(language) {
|
|
196
|
-
if (LANGUAGES_SUPPORTED.includes(language)) {
|
|
197
|
-
this.dictationConfig = {
|
|
198
|
-
...this.dictationConfig,
|
|
199
|
-
primaryLanguage: language,
|
|
200
|
-
};
|
|
201
|
-
// If recording is in progress, restart to apply the language change
|
|
202
|
-
if (this._serverConfig && this._recordingState === 'recording') {
|
|
203
|
-
this.recorderManager.stopRecording();
|
|
204
|
-
this.recorderManager.startRecording({
|
|
205
|
-
dictationConfig: this.dictationConfig,
|
|
206
|
-
serverConfig: this._serverConfig,
|
|
207
|
-
debug_displayAudio: this.debug_displayAudio,
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
_onButtonMouseDown(event) {
|
|
213
|
-
// Prevent button from taking focus on mouse click
|
|
214
|
-
// This keeps focus on the textarea
|
|
215
|
-
if (this.preventButtonFocus) {
|
|
216
|
-
event.preventDefault();
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
// Handle device change events if needed
|
|
220
|
-
async _onRecordingDevicesChanged(event) {
|
|
221
|
-
const customEvent = event;
|
|
222
|
-
this.setRecordingDevice(customEvent.detail.selectedDevice);
|
|
223
|
-
}
|
|
224
|
-
// Handle language change events
|
|
225
|
-
_onLanguageChanged(event) {
|
|
226
|
-
const customEvent = event;
|
|
227
|
-
const language = customEvent.detail.language;
|
|
228
|
-
if (language) {
|
|
229
|
-
this.setPrimaryLanguage(language);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
render() {
|
|
233
|
-
if (!this._serverConfig) {
|
|
234
|
-
return html ` <div style="display: none"></div> `;
|
|
235
|
-
}
|
|
236
|
-
const isLoading = this._recordingState === 'initializing' ||
|
|
237
|
-
this._recordingState === 'stopping';
|
|
238
|
-
const isRecording = this._recordingState === 'recording';
|
|
239
|
-
return html `
|
|
240
|
-
<div class="wrapper">
|
|
241
|
-
<button
|
|
242
|
-
@click=${this.toggleRecording}
|
|
243
|
-
@mousedown=${this._onButtonMouseDown}
|
|
244
|
-
class=${isRecording ? 'red' : 'accent'}
|
|
245
|
-
>
|
|
246
|
-
${isLoading
|
|
247
|
-
? html ` <icon-loading-spinner></icon-loading-spinner>`
|
|
248
|
-
: isRecording
|
|
249
|
-
? html ` <icon-recording></icon-recording>`
|
|
250
|
-
: html ` <icon-mic-on></icon-mic-on>`}
|
|
251
|
-
<audio-visualiser
|
|
252
|
-
.level=${this._audioLevel}
|
|
253
|
-
.active=${isRecording}
|
|
254
|
-
></audio-visualiser>
|
|
255
|
-
</button>
|
|
256
|
-
|
|
257
|
-
${this.settingsEnabled.length > 0 ? html `
|
|
258
|
-
<settings-menu
|
|
259
|
-
.selectedDevice=${this._selectedDevice}
|
|
260
|
-
.selectedLanguage=${this.dictationConfig.primaryLanguage}
|
|
261
|
-
?settingsDisabled=${this._recordingState !== 'stopped'}
|
|
262
|
-
@recording-devices-changed=${this._onRecordingDevicesChanged}
|
|
263
|
-
@language-changed=${this._onLanguageChanged}
|
|
264
|
-
.settingsEnabled=${this.settingsEnabled}
|
|
265
|
-
></settings-menu>
|
|
266
|
-
` : ''}
|
|
267
|
-
</div>
|
|
268
|
-
`;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
CortiDictation.styles = [ButtonStyles, ThemeStyles, ComponentStyles, CalloutStyles];
|
|
272
|
-
__decorate([
|
|
273
|
-
property({ type: Object })
|
|
274
|
-
], CortiDictation.prototype, "dictationConfig", void 0);
|
|
275
|
-
__decorate([
|
|
276
|
-
property({ type: Array })
|
|
277
|
-
], CortiDictation.prototype, "languagesSupported", void 0);
|
|
278
|
-
__decorate([
|
|
279
|
-
property({ type: Boolean })
|
|
280
|
-
], CortiDictation.prototype, "debug_displayAudio", void 0);
|
|
281
|
-
__decorate([
|
|
282
|
-
property({ type: Array })
|
|
283
|
-
], CortiDictation.prototype, "settingsEnabled", void 0);
|
|
284
|
-
__decorate([
|
|
285
|
-
property({ type: Boolean })
|
|
286
|
-
], CortiDictation.prototype, "preventButtonFocus", void 0);
|
|
287
|
-
__decorate([
|
|
288
|
-
state()
|
|
289
|
-
], CortiDictation.prototype, "_serverConfig", void 0);
|
|
290
|
-
__decorate([
|
|
291
|
-
state()
|
|
292
|
-
], CortiDictation.prototype, "_audioLevel", void 0);
|
|
293
|
-
__decorate([
|
|
294
|
-
state()
|
|
295
|
-
], CortiDictation.prototype, "_recordingState", void 0);
|
|
296
|
-
__decorate([
|
|
297
|
-
state()
|
|
298
|
-
], CortiDictation.prototype, "_selectedDevice", void 0);
|
|
299
|
-
__decorate([
|
|
300
|
-
state()
|
|
301
|
-
], CortiDictation.prototype, "_devices", void 0);
|
|
302
|
-
export default CortiDictation;
|
|
303
|
-
//# sourceMappingURL=CortiDictation.js.map
|
|
@@ -1 +0,0 @@
|
|
|
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 { ConfigurableSettings, 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 @property({ type: Array })\n settingsEnabled: ConfigurableSettings[] = [\"device\", \"language\"];\n \n @property({ type: Boolean })\n preventButtonFocus: boolean = true;\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 startRecording() {\n if (!this._serverConfig) return;\n this.recorderManager.startRecording({\n dictationConfig: this.dictationConfig,\n serverConfig: this._serverConfig!,\n debug_displayAudio: this.debug_displayAudio,\n });\n }\n\n public stopRecording() {\n this.recorderManager.stopRecording();\n }\n\n public toggleRecording() {\n if (this._recordingState === 'recording') {\n this.stopRecording();\n } else if (this._recordingState === 'stopped') {\n this.startRecording();\n }\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 _onButtonMouseDown(event: MouseEvent) {\n // Prevent button from taking focus on mouse click\n // This keeps focus on the textarea\n if (this.preventButtonFocus) {\n event.preventDefault();\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 @mousedown=${this._onButtonMouseDown}\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 ${this.settingsEnabled.length > 0 ? html`\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 .settingsEnabled=${this.settingsEnabled}\n ></settings-menu>\n ` : ''}\n </div>\n `;\n }\n}\n\nexport default CortiDictation;\n"]}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { Corti } from '@corti/sdk';
|
|
2
|
-
import type { ServerConfig } from './types.js';
|
|
3
|
-
export declare class DictationService extends EventTarget {
|
|
4
|
-
private mediaRecorder;
|
|
5
|
-
private webSocket;
|
|
6
|
-
private serverConfig;
|
|
7
|
-
private dictationConfig;
|
|
8
|
-
private cortiClient;
|
|
9
|
-
constructor(mediaStream: MediaStream, { dictationConfig, serverConfig, }: {
|
|
10
|
-
dictationConfig: Corti.TranscribeConfig;
|
|
11
|
-
serverConfig: ServerConfig;
|
|
12
|
-
});
|
|
13
|
-
private dispatchCustomEvent;
|
|
14
|
-
startRecording(): Promise<void>;
|
|
15
|
-
stopRecording(): Promise<void>;
|
|
16
|
-
}
|
package/dist/DictationService.js
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { CortiClient } from '@corti/sdk';
|
|
2
|
-
import { getErrorMessage } from './utils.js';
|
|
3
|
-
export class DictationService extends EventTarget {
|
|
4
|
-
constructor(mediaStream, { dictationConfig, serverConfig, }) {
|
|
5
|
-
super();
|
|
6
|
-
this.mediaRecorder = new MediaRecorder(mediaStream);
|
|
7
|
-
this.serverConfig = serverConfig;
|
|
8
|
-
this.dictationConfig = dictationConfig;
|
|
9
|
-
// We're forced to remove from expiresIn/refreshExpiresIn here,
|
|
10
|
-
// because we recreate connection every time we connect
|
|
11
|
-
// => it makes expiresIn (we receive from API) out of date
|
|
12
|
-
const { expiresIn, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
13
|
-
refreshExpiresIn, // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
14
|
-
...authConfig } = serverConfig;
|
|
15
|
-
this.cortiClient = new CortiClient({
|
|
16
|
-
auth: authConfig,
|
|
17
|
-
});
|
|
18
|
-
this.mediaRecorder.ondataavailable = event => {
|
|
19
|
-
if (this.webSocket?.readyState === WebSocket.OPEN) {
|
|
20
|
-
this.webSocket.sendAudio(event.data);
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
dispatchCustomEvent(eventName, detail) {
|
|
25
|
-
this.dispatchEvent(new CustomEvent(eventName, {
|
|
26
|
-
detail,
|
|
27
|
-
bubbles: true,
|
|
28
|
-
composed: true,
|
|
29
|
-
}));
|
|
30
|
-
}
|
|
31
|
-
async startRecording() {
|
|
32
|
-
if (!this.serverConfig) {
|
|
33
|
-
this.dispatchEvent(new CustomEvent('error', {
|
|
34
|
-
detail: 'Invalid token',
|
|
35
|
-
bubbles: true,
|
|
36
|
-
composed: true,
|
|
37
|
-
}));
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
this.webSocket = await this.cortiClient.transcribe.connect({
|
|
41
|
-
configuration: this.dictationConfig,
|
|
42
|
-
});
|
|
43
|
-
this.webSocket.on('message', message => {
|
|
44
|
-
switch (message.type) {
|
|
45
|
-
case 'CONFIG_ACCEPTED':
|
|
46
|
-
this.mediaRecorder.start(250);
|
|
47
|
-
break;
|
|
48
|
-
case 'transcript':
|
|
49
|
-
this.dispatchCustomEvent('transcript', message);
|
|
50
|
-
break;
|
|
51
|
-
case 'command':
|
|
52
|
-
this.dispatchCustomEvent('command', message);
|
|
53
|
-
break;
|
|
54
|
-
case 'usage':
|
|
55
|
-
this.dispatchCustomEvent('usage', message);
|
|
56
|
-
break;
|
|
57
|
-
default:
|
|
58
|
-
console.warn(`Unhandled message type: ${message.type}`);
|
|
59
|
-
break;
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
this.webSocket.on('error', event => {
|
|
63
|
-
this.stopRecording();
|
|
64
|
-
this.dispatchCustomEvent('error', getErrorMessage(event));
|
|
65
|
-
});
|
|
66
|
-
this.webSocket.on('close', event => {
|
|
67
|
-
this.dispatchCustomEvent('stream-closed', event);
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
async stopRecording() {
|
|
71
|
-
this.mediaRecorder?.stop();
|
|
72
|
-
if (this.webSocket.readyState === WebSocket.OPEN) {
|
|
73
|
-
this.webSocket.sendEnd({
|
|
74
|
-
type: 'end',
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
const timeout = setTimeout(() => {
|
|
78
|
-
if (this.webSocket?.readyState === WebSocket.OPEN) {
|
|
79
|
-
this.webSocket.close();
|
|
80
|
-
}
|
|
81
|
-
}, 10000);
|
|
82
|
-
this.webSocket.on('close', (event) => {
|
|
83
|
-
clearTimeout(timeout);
|
|
84
|
-
this.dispatchCustomEvent('stream-closed', event);
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
//# sourceMappingURL=DictationService.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"DictationService.js","sourceRoot":"","sources":["../src/DictationService.ts"],"names":[],"mappings":"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","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"]}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { Corti } from '@corti/sdk';
|
|
2
|
-
import type { RecordingState, ServerConfig } from './types.js';
|
|
3
|
-
export declare class RecorderManager extends EventTarget {
|
|
4
|
-
devices: MediaDeviceInfo[];
|
|
5
|
-
selectedDevice: MediaDeviceInfo | undefined;
|
|
6
|
-
recordingState: RecordingState;
|
|
7
|
-
private _mediaStream;
|
|
8
|
-
private _audioService;
|
|
9
|
-
private _dictationService;
|
|
10
|
-
private _visualiserInterval?;
|
|
11
|
-
constructor();
|
|
12
|
-
initialize(): Promise<{
|
|
13
|
-
devices: MediaDeviceInfo[];
|
|
14
|
-
selectedDevice: MediaDeviceInfo | undefined;
|
|
15
|
-
}>;
|
|
16
|
-
private dispatchCustomEvent;
|
|
17
|
-
private handleDevicesChange;
|
|
18
|
-
startRecording(params: {
|
|
19
|
-
dictationConfig: Corti.TranscribeConfig;
|
|
20
|
-
serverConfig: ServerConfig;
|
|
21
|
-
debug_displayAudio?: boolean;
|
|
22
|
-
}): Promise<void>;
|
|
23
|
-
stopRecording(): Promise<void>;
|
|
24
|
-
private _updateRecordingState;
|
|
25
|
-
}
|
package/dist/RecorderManager.js
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import { getAudioDevices, getMediaStream } from './utils.js';
|
|
2
|
-
import { AudioService } from './audioService.js';
|
|
3
|
-
import { DictationService } from './DictationService.js';
|
|
4
|
-
export class RecorderManager extends EventTarget {
|
|
5
|
-
constructor() {
|
|
6
|
-
super();
|
|
7
|
-
this.devices = [];
|
|
8
|
-
this.recordingState = 'stopped';
|
|
9
|
-
this._mediaStream = null;
|
|
10
|
-
this._audioService = null;
|
|
11
|
-
this._dictationService = null;
|
|
12
|
-
navigator.mediaDevices.addEventListener('devicechange', this.handleDevicesChange.bind(this));
|
|
13
|
-
}
|
|
14
|
-
async initialize() {
|
|
15
|
-
const deviceResponse = await getAudioDevices();
|
|
16
|
-
this.devices = deviceResponse.devices;
|
|
17
|
-
this.selectedDevice = deviceResponse.defaultDevice;
|
|
18
|
-
return { devices: this.devices, selectedDevice: this.selectedDevice };
|
|
19
|
-
}
|
|
20
|
-
dispatchCustomEvent(eventName, detail) {
|
|
21
|
-
this.dispatchEvent(new CustomEvent(eventName, {
|
|
22
|
-
detail,
|
|
23
|
-
bubbles: true,
|
|
24
|
-
composed: true,
|
|
25
|
-
}));
|
|
26
|
-
}
|
|
27
|
-
async handleDevicesChange() {
|
|
28
|
-
const deviceResponse = await getAudioDevices();
|
|
29
|
-
this.devices = deviceResponse.devices;
|
|
30
|
-
if (!this.devices.find(device => device.deviceId === this.selectedDevice?.deviceId)) {
|
|
31
|
-
this.selectedDevice = deviceResponse.defaultDevice;
|
|
32
|
-
}
|
|
33
|
-
this.dispatchCustomEvent('recording-devices-changed', {
|
|
34
|
-
devices: deviceResponse.devices,
|
|
35
|
-
selectedDevice: this.selectedDevice || deviceResponse.defaultDevice,
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
async startRecording(params) {
|
|
39
|
-
this._updateRecordingState('initializing');
|
|
40
|
-
try {
|
|
41
|
-
this._mediaStream = await getMediaStream(params.debug_displayAudio
|
|
42
|
-
? 'display_audio'
|
|
43
|
-
: this.selectedDevice?.deviceId);
|
|
44
|
-
this._mediaStream.getTracks().forEach((track) => {
|
|
45
|
-
track.addEventListener('ended', () => {
|
|
46
|
-
if (this.recordingState === 'recording') {
|
|
47
|
-
this.dispatchCustomEvent('error', {
|
|
48
|
-
message: 'Microphone access was lost.',
|
|
49
|
-
});
|
|
50
|
-
this.stopRecording();
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
this._audioService = new AudioService(this._mediaStream);
|
|
55
|
-
}
|
|
56
|
-
catch (error) {
|
|
57
|
-
this.dispatchCustomEvent('error', error);
|
|
58
|
-
this.stopRecording();
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
// Initialize dictation service.
|
|
62
|
-
try {
|
|
63
|
-
this._dictationService = new DictationService(this._mediaStream, params);
|
|
64
|
-
// Forward custom events from dictation service
|
|
65
|
-
this._dictationService.addEventListener('error', e => {
|
|
66
|
-
this.dispatchEvent(new CustomEvent('error', {
|
|
67
|
-
detail: e.detail,
|
|
68
|
-
bubbles: true,
|
|
69
|
-
composed: true,
|
|
70
|
-
}));
|
|
71
|
-
this.stopRecording();
|
|
72
|
-
});
|
|
73
|
-
this._dictationService.addEventListener('stream-closed', (e) => {
|
|
74
|
-
this.dispatchEvent(new CustomEvent('stream-closed', {
|
|
75
|
-
detail: e.detail,
|
|
76
|
-
bubbles: true,
|
|
77
|
-
composed: true,
|
|
78
|
-
}));
|
|
79
|
-
this.stopRecording();
|
|
80
|
-
});
|
|
81
|
-
this._dictationService.addEventListener('transcript', e => this.dispatchEvent(new CustomEvent('transcript', {
|
|
82
|
-
detail: e.detail,
|
|
83
|
-
bubbles: true,
|
|
84
|
-
composed: true,
|
|
85
|
-
})));
|
|
86
|
-
this._dictationService.addEventListener('command', e => this.dispatchEvent(new CustomEvent('command', {
|
|
87
|
-
detail: e.detail,
|
|
88
|
-
bubbles: true,
|
|
89
|
-
composed: true,
|
|
90
|
-
})));
|
|
91
|
-
this._dictationService.addEventListener('usage', e => this.dispatchEvent(new CustomEvent('usage', {
|
|
92
|
-
detail: e.detail,
|
|
93
|
-
bubbles: true,
|
|
94
|
-
composed: true,
|
|
95
|
-
})));
|
|
96
|
-
}
|
|
97
|
-
catch (error) {
|
|
98
|
-
this.dispatchCustomEvent('error', error);
|
|
99
|
-
this.stopRecording();
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
try {
|
|
103
|
-
this._dictationService?.startRecording();
|
|
104
|
-
}
|
|
105
|
-
catch (error) {
|
|
106
|
-
this.dispatchEvent(new CustomEvent('error', {
|
|
107
|
-
detail: error,
|
|
108
|
-
bubbles: true,
|
|
109
|
-
composed: true,
|
|
110
|
-
}));
|
|
111
|
-
this.stopRecording();
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
this._updateRecordingState('recording');
|
|
115
|
-
// Update audio level visualization.
|
|
116
|
-
this._visualiserInterval = window.setInterval(() => {
|
|
117
|
-
const level = this._audioService
|
|
118
|
-
? this._audioService.getAudioLevel() * 3
|
|
119
|
-
: 0;
|
|
120
|
-
this.dispatchCustomEvent('audio-level-changed', { audioLevel: level });
|
|
121
|
-
}, 150);
|
|
122
|
-
}
|
|
123
|
-
async stopRecording() {
|
|
124
|
-
this._updateRecordingState('stopping');
|
|
125
|
-
if (this._visualiserInterval) {
|
|
126
|
-
clearInterval(this._visualiserInterval);
|
|
127
|
-
this._visualiserInterval = undefined;
|
|
128
|
-
}
|
|
129
|
-
if (this._mediaStream) {
|
|
130
|
-
this._mediaStream.getTracks().forEach(track => track.stop());
|
|
131
|
-
}
|
|
132
|
-
this.dispatchCustomEvent('audio-level-changed', { audioLevel: 0 });
|
|
133
|
-
await this._dictationService?.stopRecording();
|
|
134
|
-
this._updateRecordingState('stopped');
|
|
135
|
-
}
|
|
136
|
-
_updateRecordingState(state) {
|
|
137
|
-
this.recordingState = state;
|
|
138
|
-
this.dispatchEvent(new CustomEvent('recording-state-changed', {
|
|
139
|
-
detail: { state },
|
|
140
|
-
bubbles: true,
|
|
141
|
-
composed: true,
|
|
142
|
-
}));
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
//# sourceMappingURL=RecorderManager.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"RecorderManager.js","sourceRoot":"","sources":["../src/RecorderManager.ts"],"names":[],"mappings":"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","sourcesContent":["import { Corti } from '@corti/sdk';\n\nimport { getAudioDevices, getMediaStream } from './utils.js';\nimport { AudioService } from './audioService.js';\nimport { DictationService } from './DictationService.js';\nimport type { RecordingState, ServerConfig } from './types.js';\n\nexport class RecorderManager extends EventTarget {\n public devices: MediaDeviceInfo[] = [];\n\n public selectedDevice: MediaDeviceInfo | undefined;\n\n public recordingState: RecordingState = 'stopped';\n\n private _mediaStream: MediaStream | null = null;\n\n private _audioService: AudioService | null = null;\n\n private _dictationService: DictationService | null = null;\n\n private _visualiserInterval?: number;\n\n constructor() {\n super();\n navigator.mediaDevices.addEventListener(\n 'devicechange',\n this.handleDevicesChange.bind(this),\n );\n }\n\n async initialize() {\n const deviceResponse = await getAudioDevices();\n this.devices = deviceResponse.devices;\n this.selectedDevice = deviceResponse.defaultDevice;\n return { devices: this.devices, selectedDevice: this.selectedDevice };\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 private async handleDevicesChange() {\n const deviceResponse = await getAudioDevices();\n this.devices = deviceResponse.devices;\n if (\n !this.devices.find(\n device => device.deviceId === this.selectedDevice?.deviceId,\n )\n ) {\n this.selectedDevice = deviceResponse.defaultDevice;\n }\n this.dispatchCustomEvent('recording-devices-changed', {\n devices: deviceResponse.devices,\n selectedDevice: this.selectedDevice || deviceResponse.defaultDevice,\n });\n }\n\n async startRecording(params: {\n dictationConfig: Corti.TranscribeConfig;\n serverConfig: ServerConfig;\n debug_displayAudio?: boolean;\n }): Promise<void> {\n this._updateRecordingState('initializing');\n\n try {\n this._mediaStream = await getMediaStream(\n params.debug_displayAudio\n ? 'display_audio'\n : this.selectedDevice?.deviceId,\n );\n\n this._mediaStream.getTracks().forEach((track: MediaStreamTrack) => {\n track.addEventListener('ended', () => {\n if (this.recordingState === 'recording') {\n this.dispatchCustomEvent('error', {\n message: 'Microphone access was lost.',\n });\n this.stopRecording();\n }\n });\n });\n\n this._audioService = new AudioService(this._mediaStream);\n } catch (error) {\n this.dispatchCustomEvent('error', error);\n this.stopRecording();\n return;\n }\n\n // Initialize dictation service.\n try {\n this._dictationService = new DictationService(this._mediaStream, params);\n\n // Forward custom events from dictation service\n this._dictationService.addEventListener('error', e => {\n this.dispatchEvent(\n new CustomEvent('error', {\n detail: (e as CustomEvent).detail,\n bubbles: true,\n composed: true,\n }),\n );\n this.stopRecording();\n });\n this._dictationService.addEventListener('stream-closed', (e) => {\n this.dispatchEvent(\n new CustomEvent('stream-closed', {\n detail: (e as CustomEvent).detail,\n bubbles: true,\n composed: true,\n }),\n );\n this.stopRecording();\n });\n this._dictationService.addEventListener('transcript', e =>\n this.dispatchEvent(\n new CustomEvent('transcript', {\n detail: (e as CustomEvent).detail,\n bubbles: true,\n composed: true,\n }),\n ),\n );\n this._dictationService.addEventListener('command', e =>\n this.dispatchEvent(\n new CustomEvent('command', {\n detail: (e as CustomEvent).detail,\n bubbles: true,\n composed: true,\n }),\n ),\n );\n this._dictationService.addEventListener('usage', e =>\n this.dispatchEvent(\n new CustomEvent('usage', {\n detail: (e as CustomEvent).detail,\n bubbles: true,\n composed: true,\n }),\n ),\n );\n } catch (error) {\n this.dispatchCustomEvent('error', error);\n this.stopRecording();\n return;\n }\n\n try {\n this._dictationService?.startRecording();\n } catch (error) {\n this.dispatchEvent(\n new CustomEvent('error', {\n detail: error,\n bubbles: true,\n composed: true,\n }),\n );\n this.stopRecording();\n return;\n }\n this._updateRecordingState('recording');\n\n // Update audio level visualization.\n this._visualiserInterval = window.setInterval(() => {\n const level = this._audioService\n ? this._audioService.getAudioLevel() * 3\n : 0;\n this.dispatchCustomEvent('audio-level-changed', { audioLevel: level });\n }, 150);\n }\n\n async stopRecording() {\n this._updateRecordingState('stopping');\n if (this._visualiserInterval) {\n clearInterval(this._visualiserInterval);\n this._visualiserInterval = undefined;\n }\n if (this._mediaStream) {\n this._mediaStream.getTracks().forEach(track => track.stop());\n }\n this.dispatchCustomEvent('audio-level-changed', { audioLevel: 0 });\n await this._dictationService?.stopRecording();\n this._updateRecordingState('stopped');\n }\n\n private _updateRecordingState(state: RecordingState) {\n this.recordingState = state;\n this.dispatchEvent(\n new CustomEvent('recording-state-changed', {\n detail: { state },\n bubbles: true,\n composed: true,\n }),\n );\n }\n}\n"]}
|