@corti/dictation-web 0.1.3 → 0.1.5
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 +45 -38
- package/dist/RecorderManager.js +1 -1
- package/dist/RecorderManager.js.map +1 -1
- package/dist/bundle.js +76 -79
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Corti Dictation SDK
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
|
+
|
|
4
5
|
The **Corti Dictation SDK** is a web component that enables real-time speech-to-text dictation using Corti's Dictation API. It provides a simple interface for capturing audio, streaming it to the API, and handling transcripts.
|
|
5
6
|
|
|
6
7
|
> **Note:** OAuth 2.0 authentication is not handled by this SDK. The client must provide an API key or authorization token before using the component.
|
|
7
8
|
|
|
8
|
-
|
|
9
9
|
## Installation
|
|
10
10
|
|
|
11
11
|
Include the SDK in your project by importing the JavaScript module:
|
|
@@ -14,6 +14,13 @@ Include the SDK in your project by importing the JavaScript module:
|
|
|
14
14
|
npm i @corti/dictation-web
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
+
```html
|
|
18
|
+
<script
|
|
19
|
+
src="https://cdn.jsdelivr.net/npm/@corti/dictation-web/dist/bundle.min.js"
|
|
20
|
+
preload
|
|
21
|
+
type="module"
|
|
22
|
+
></script>
|
|
23
|
+
```
|
|
17
24
|
|
|
18
25
|
## Usage
|
|
19
26
|
|
|
@@ -21,74 +28,74 @@ npm i @corti/dictation-web
|
|
|
21
28
|
|
|
22
29
|
🚀 [Hosted Demo](https://codepen.io/hccullen/pen/OPJmxQR)
|
|
23
30
|
|
|
24
|
-
|
|
25
31
|
### Basic Example
|
|
26
32
|
|
|
27
33
|
```html
|
|
28
34
|
<!DOCTYPE html>
|
|
29
35
|
<html lang="en">
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
document.getElementById('transcript')
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
36
|
+
<body>
|
|
37
|
+
<script
|
|
38
|
+
src="https://cdn.jsdelivr.net/npm/@corti/dictation-web/dist/bundle.min.js"
|
|
39
|
+
preload
|
|
40
|
+
type="module"
|
|
41
|
+
></script>
|
|
42
|
+
<corti-dictation authToken="xyz"></corti-dictation>
|
|
43
|
+
<textarea
|
|
44
|
+
id="transcript"
|
|
45
|
+
placeholder="Transcript will appear here..."
|
|
46
|
+
></textarea>
|
|
47
|
+
|
|
48
|
+
<script>
|
|
49
|
+
const dictationEl = document.getElementById('transcript');
|
|
50
|
+
// Listen for events
|
|
51
|
+
dictationEl.addEventListener('transcript', e => {
|
|
52
|
+
document.getElementById('transcript').value += e.detail.data.text + ' ';
|
|
53
|
+
});
|
|
54
|
+
</script>
|
|
55
|
+
</body>
|
|
47
56
|
</html>
|
|
48
57
|
```
|
|
49
58
|
|
|
50
|
-
|
|
51
59
|
## API Reference
|
|
52
60
|
|
|
53
61
|
### Properties
|
|
54
62
|
|
|
55
|
-
| Property
|
|
56
|
-
|
|
57
|
-
| `devices`
|
|
58
|
-
| `recordingState`
|
|
59
|
-
| `dictationConfig` | Object | Configuration settings for dictation.
|
|
60
|
-
| `authToken`
|
|
63
|
+
| Property | Type | Description |
|
|
64
|
+
| ----------------- | ------ | ---------------------------------------------------- |
|
|
65
|
+
| `devices` | Array | List of available recording devices. |
|
|
66
|
+
| `recordingState` | String | Current state of recording (`stopped`, `recording`). |
|
|
67
|
+
| `dictationConfig` | Object | Configuration settings for dictation. |
|
|
68
|
+
| `authToken` | String | Authentication token from OAuth server |
|
|
61
69
|
|
|
62
70
|
### Methods
|
|
63
71
|
|
|
64
|
-
| Method | Description
|
|
65
|
-
|
|
72
|
+
| Method | Description |
|
|
73
|
+
| ------------------- | -------------------------- |
|
|
66
74
|
| `toggleRecording()` | Starts or stops recording. |
|
|
67
75
|
|
|
68
76
|
### Events
|
|
69
77
|
|
|
70
|
-
| Event | Description
|
|
71
|
-
|
|
72
|
-
| `recording-state-changed` | Fired when the recording state changes. `detail.state` contains the new state.
|
|
78
|
+
| Event | Description |
|
|
79
|
+
| -------------------------- | --------------------------------------------------------------------------------------------- |
|
|
80
|
+
| `recording-state-changed` | Fired when the recording state changes. `detail.state` contains the new state. |
|
|
73
81
|
| `recording-device-changed` | Fired when the user switches recording devices. `detail.deviceId` contains the new device ID. |
|
|
74
|
-
| `transcript` | Fired when a new transcript is received. `detail.data.text` contains the transcribed text.
|
|
75
|
-
| `audio-level-changed` | Fired when the input audio level changes. `detail.audioLevel` contains the new level.
|
|
76
|
-
|
|
82
|
+
| `transcript` | Fired when a new transcript is received. `detail.data.text` contains the transcribed text. |
|
|
83
|
+
| `audio-level-changed` | Fired when the input audio level changes. `detail.audioLevel` contains the new level. |
|
|
84
|
+
| `error` | Fired on error. `detail` contains the full error. |
|
|
77
85
|
|
|
78
86
|
## Authentication
|
|
79
87
|
|
|
80
88
|
This SDK does not handle OAuth 2.0 authentication. The client must provide an API key or access token as a string in `authToken`.
|
|
81
89
|
|
|
82
|
-
|
|
83
90
|
## Notes
|
|
91
|
+
|
|
84
92
|
- Works in modern browsers that support Web Components and MediaRecorder API.
|
|
85
93
|
- Supports dark and light mode based on browser preference.
|
|
86
94
|
|
|
87
|
-
|
|
88
95
|
## License
|
|
89
|
-
This SDK is not licensed.
|
|
90
96
|
|
|
97
|
+
This SDK is not licensed.
|
|
91
98
|
|
|
92
99
|
## Support
|
|
93
|
-
For issues or questions, contact **Corti Support** at [support@corti.ai](mailto:support@corti.ai).
|
|
94
100
|
|
|
101
|
+
For issues or questions, contact **Corti Support** at [support@corti.ai](mailto:support@corti.ai).
|
package/dist/RecorderManager.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RecorderManager.js","sourceRoot":"","sources":["../src/RecorderManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGzD,MAAM,OAAO,eAAgB,SAAQ,WAAW;IAAhD;;QACS,YAAO,GAAsB,EAAE,CAAC;QAEhC,mBAAc,GAAW,EAAE,CAAC;QAE5B,mBAAc,GAAmB,SAAS,CAAC;QAE1C,iBAAY,GAAuB,IAAI,CAAC;QAExC,kBAAa,GAAwB,IAAI,CAAC;QAE1C,sBAAiB,GAA4B,IAAI,CAAC;IA8F5D,CAAC;IA1FC,KAAK,CAAC,UAAU;QACd,MAAM,cAAc,GAAG,MAAM,eAAe,EAAE,CAAC;QAC/C,IAAI,CAAC,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC;QACtC,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC,eAAe,IAAI,EAAE,CAAC;QAC3D,OAAO,cAAc,CAAC;IACxB,CAAC;IACO,mBAAmB,CAAC,SAAiB,EAAE,MAAe;QAC5D,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;IAED,KAAK,CAAC,cAAc,CAAC,MAGpB;QACC,IAAI,CAAC,qBAAqB,CAAC,cAAc,CAAC,CAAC;QAE3C,iDAAiD;QACjD,IAAI,CAAC;YACH,IAAI,CAAC,YAAY,GAAG,MAAM,SAAS,CAAC,YAAY,CAAC,YAAY,CAAC;gBAC5D,KAAK,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE;aACzC,CAAC,CAAC;YACH,IAAI,CAAC,aAAa,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC3D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YACzC,IAAI,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;YACtC,OAAO;QACT,CAAC;QAED,gCAAgC;QAChC,IAAI,CAAC;YACH,IAAI,CAAC,iBAAiB,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QAC3E,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YACzC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"RecorderManager.js","sourceRoot":"","sources":["../src/RecorderManager.ts"],"names":[],"mappings":"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","sourcesContent":["import { getAudioDevices } from './utils.js';\nimport { AudioService } from './audioService.js';\nimport { DictationService } from './DictationService.js';\nimport type { DictationConfig, RecordingState } from './types.js';\n\nexport class RecorderManager extends EventTarget {\n public devices: MediaDeviceInfo[] = [];\n\n public selectedDevice: string = '';\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 async initialize() {\n const deviceResponse = await getAudioDevices();\n this.devices = deviceResponse.devices;\n this.selectedDevice = deviceResponse.defaultDeviceId || '';\n return deviceResponse;\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 async startRecording(params: {\n dictationConfig: DictationConfig;\n authToken: string;\n }): Promise<void> {\n this._updateRecordingState('initializing');\n\n // Get media stream and initialize audio service.\n try {\n this._mediaStream = await navigator.mediaDevices.getUserMedia({\n audio: { deviceId: this.selectedDevice },\n });\n this._audioService = new AudioService(this._mediaStream);\n } catch (error) {\n this.dispatchCustomEvent('error', error);\n this._updateRecordingState('stopped');\n return;\n }\n\n // Initialize dictation service.\n try {\n this._dictationService = new DictationService(this._mediaStream, params);\n } catch (error) {\n this.dispatchCustomEvent('error', error);\n this.stopRecording();\n return;\n }\n\n // Forward dictation service events.\n this._dictationService.addEventListener('error', e =>\n this.dispatchCustomEvent('error', (e as CustomEvent).detail),\n );\n this._dictationService.addEventListener('stream-closed', () =>\n this.stopRecording(),\n );\n this._dictationService.addEventListener('transcript', e =>\n this.dispatchCustomEvent('transcript', (e as CustomEvent).detail),\n );\n\n this._dictationService.startRecording();\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 this._mediaStream = null;\n }\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"]}
|
package/dist/bundle.js
CHANGED
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
// node_modules/tslib/tslib.es6.mjs
|
|
2
|
-
function __decorate(decorators, target, key, desc) {
|
|
3
|
-
var c4 = arguments.length, r7 = c4 < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d3;
|
|
4
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r7 = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
-
else for (var i5 = decorators.length - 1; i5 >= 0; i5--) if (d3 = decorators[i5]) r7 = (c4 < 3 ? d3(r7) : c4 > 3 ? d3(target, key, r7) : d3(target, key)) || r7;
|
|
6
|
-
return c4 > 3 && r7 && Object.defineProperty(target, key, r7), r7;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
1
|
// node_modules/@lit/reactive-element/css-tag.js
|
|
10
2
|
var t = globalThis;
|
|
11
3
|
var e = t.ShadowRoot && (void 0 === t.ShadyCSS || t.ShadyCSS.nativeShadow) && "adoptedStyleSheets" in Document.prototype && "replace" in CSSStyleSheet.prototype;
|
|
@@ -645,14 +637,12 @@ function decodeToken(token) {
|
|
|
645
637
|
}
|
|
646
638
|
const base64Url = parts[1];
|
|
647
639
|
const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
|
|
648
|
-
console.log("Decoded base64:", base64);
|
|
649
640
|
let jsonPayload;
|
|
650
641
|
try {
|
|
651
642
|
jsonPayload = decodeURIComponent(atob(base64).split("").map((c4) => "%" + ("00" + c4.charCodeAt(0).toString(16)).slice(-2)).join(""));
|
|
652
643
|
} catch (error) {
|
|
653
644
|
throw new Error("Failed to decode token payload");
|
|
654
645
|
}
|
|
655
|
-
console.log("Decoded payload:", jsonPayload);
|
|
656
646
|
let tokenDetails;
|
|
657
647
|
try {
|
|
658
648
|
tokenDetails = JSON.parse(jsonPayload);
|
|
@@ -665,9 +655,7 @@ function decodeToken(token) {
|
|
|
665
655
|
}
|
|
666
656
|
const regex = /^https:\/\/(keycloak|auth)\.([^.]+)\.corti\.app\/realms\/([^/]+)/;
|
|
667
657
|
const match = issuerUrl.match(regex);
|
|
668
|
-
console.log("Matched URL pattern:", match);
|
|
669
658
|
if (match) {
|
|
670
|
-
console.log("Matched URL pattern:", match);
|
|
671
659
|
return {
|
|
672
660
|
environment: match[2],
|
|
673
661
|
tenant: match[3],
|
|
@@ -705,24 +693,26 @@ var DictationService = class extends EventTarget {
|
|
|
705
693
|
this.mediaRecorder = new MediaRecorder(mediaStream);
|
|
706
694
|
this.authToken = authToken;
|
|
707
695
|
this.dictationConfig = dictationConfig;
|
|
696
|
+
const config = decodeToken(this.authToken);
|
|
697
|
+
if (!config) {
|
|
698
|
+
throw new Error("Invalid token");
|
|
699
|
+
}
|
|
700
|
+
this.serverConfig = config;
|
|
708
701
|
this.mediaRecorder.ondataavailable = (event) => {
|
|
709
702
|
if (this.webSocket?.readyState === WebSocket.OPEN) {
|
|
710
703
|
this.webSocket.send(event.data);
|
|
711
704
|
}
|
|
712
705
|
};
|
|
713
706
|
}
|
|
707
|
+
dispatchCustomEvent(eventName, detail) {
|
|
708
|
+
this.dispatchEvent(new CustomEvent(eventName, {
|
|
709
|
+
detail,
|
|
710
|
+
bubbles: true,
|
|
711
|
+
composed: true
|
|
712
|
+
}));
|
|
713
|
+
}
|
|
714
714
|
startRecording() {
|
|
715
|
-
const
|
|
716
|
-
if (!serverConfig) {
|
|
717
|
-
this.dispatchEvent(new CustomEvent("error", {
|
|
718
|
-
detail: "Invalid token",
|
|
719
|
-
bubbles: true,
|
|
720
|
-
composed: true
|
|
721
|
-
}));
|
|
722
|
-
return;
|
|
723
|
-
}
|
|
724
|
-
console.log("serverConfig:", serverConfig);
|
|
725
|
-
const url = `wss://api.${serverConfig.environment}.corti.app/audio-bridge/v2/transcribe?tenant-name=${serverConfig.tenant}&token=Bearer%20${this.authToken}`;
|
|
715
|
+
const url = `wss://api.${this.serverConfig.environment}.corti.app/audio-bridge/v2/transcribe?tenant-name=${this.serverConfig.tenant}&token=Bearer%20${this.authToken}`;
|
|
726
716
|
this.webSocket = new WebSocket(url);
|
|
727
717
|
this.webSocket.onopen = () => {
|
|
728
718
|
this.webSocket.send(JSON.stringify({
|
|
@@ -735,43 +725,29 @@ var DictationService = class extends EventTarget {
|
|
|
735
725
|
if (message.type === "config") {
|
|
736
726
|
this.mediaRecorder.start(250);
|
|
737
727
|
} else if (message.type === "transcript") {
|
|
738
|
-
this.
|
|
739
|
-
detail: message,
|
|
740
|
-
bubbles: true,
|
|
741
|
-
composed: true
|
|
742
|
-
}));
|
|
728
|
+
this.dispatchCustomEvent("transcript", message);
|
|
743
729
|
}
|
|
744
730
|
};
|
|
745
731
|
this.webSocket.onerror = (event) => {
|
|
746
|
-
this.
|
|
747
|
-
detail: event,
|
|
748
|
-
bubbles: true,
|
|
749
|
-
composed: true
|
|
750
|
-
}));
|
|
732
|
+
this.dispatchCustomEvent("error", event);
|
|
751
733
|
};
|
|
752
734
|
this.webSocket.onclose = (event) => {
|
|
753
|
-
this.
|
|
754
|
-
detail: event,
|
|
755
|
-
bubbles: true,
|
|
756
|
-
composed: true
|
|
757
|
-
}));
|
|
735
|
+
this.dispatchCustomEvent("stream-closed", event);
|
|
758
736
|
};
|
|
759
737
|
}
|
|
760
738
|
async stopRecording() {
|
|
761
739
|
this.mediaRecorder.stop();
|
|
762
740
|
if (this.webSocket?.readyState === WebSocket.OPEN) {
|
|
763
|
-
this.webSocket.send(JSON.stringify({
|
|
764
|
-
type: "end"
|
|
765
|
-
}));
|
|
741
|
+
this.webSocket.send(JSON.stringify({ type: "end" }));
|
|
766
742
|
}
|
|
767
|
-
const
|
|
743
|
+
const timeout = setTimeout(() => {
|
|
768
744
|
if (this.webSocket?.readyState === WebSocket.OPEN) {
|
|
769
745
|
this.webSocket.close();
|
|
770
746
|
}
|
|
771
747
|
}, 1e4);
|
|
772
748
|
this.webSocket.onclose = () => {
|
|
773
749
|
this.webSocket?.close();
|
|
774
|
-
clearTimeout(
|
|
750
|
+
clearTimeout(timeout);
|
|
775
751
|
};
|
|
776
752
|
}
|
|
777
753
|
};
|
|
@@ -793,6 +769,13 @@ var RecorderManager = class extends EventTarget {
|
|
|
793
769
|
this.selectedDevice = deviceResponse.defaultDeviceId || "";
|
|
794
770
|
return deviceResponse;
|
|
795
771
|
}
|
|
772
|
+
dispatchCustomEvent(eventName, detail) {
|
|
773
|
+
this.dispatchEvent(new CustomEvent(eventName, {
|
|
774
|
+
detail,
|
|
775
|
+
bubbles: true,
|
|
776
|
+
composed: true
|
|
777
|
+
}));
|
|
778
|
+
}
|
|
796
779
|
async startRecording(params) {
|
|
797
780
|
this._updateRecordingState("initializing");
|
|
798
781
|
try {
|
|
@@ -800,36 +783,26 @@ var RecorderManager = class extends EventTarget {
|
|
|
800
783
|
audio: { deviceId: this.selectedDevice }
|
|
801
784
|
});
|
|
802
785
|
this._audioService = new AudioService(this._mediaStream);
|
|
803
|
-
this._dictationService = new DictationService(this._mediaStream, params);
|
|
804
|
-
this._dictationService.addEventListener("error", (e5) => this.dispatchEvent(new CustomEvent("error", {
|
|
805
|
-
detail: e5.detail,
|
|
806
|
-
bubbles: true,
|
|
807
|
-
composed: true
|
|
808
|
-
})));
|
|
809
|
-
this._dictationService.addEventListener("stream-closed", () => this.stopRecording());
|
|
810
|
-
this._dictationService.addEventListener("transcript", (e5) => this.dispatchEvent(new CustomEvent("transcript", {
|
|
811
|
-
detail: e5.detail,
|
|
812
|
-
bubbles: true,
|
|
813
|
-
composed: true
|
|
814
|
-
})));
|
|
815
786
|
} catch (error) {
|
|
816
|
-
this.
|
|
817
|
-
detail: error,
|
|
818
|
-
bubbles: true,
|
|
819
|
-
composed: true
|
|
820
|
-
}));
|
|
787
|
+
this.dispatchCustomEvent("error", error);
|
|
821
788
|
this._updateRecordingState("stopped");
|
|
822
789
|
return;
|
|
823
790
|
}
|
|
824
|
-
|
|
791
|
+
try {
|
|
792
|
+
this._dictationService = new DictationService(this._mediaStream, params);
|
|
793
|
+
} catch (error) {
|
|
794
|
+
this.dispatchCustomEvent("error", error);
|
|
795
|
+
this.stopRecording();
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
this._dictationService.addEventListener("error", (e5) => this.dispatchCustomEvent("error", e5.detail));
|
|
799
|
+
this._dictationService.addEventListener("stream-closed", () => this.stopRecording());
|
|
800
|
+
this._dictationService.addEventListener("transcript", (e5) => this.dispatchCustomEvent("transcript", e5.detail));
|
|
801
|
+
this._dictationService.startRecording();
|
|
825
802
|
this._updateRecordingState("recording");
|
|
826
803
|
this._visualiserInterval = window.setInterval(() => {
|
|
827
804
|
const level = this._audioService ? this._audioService.getAudioLevel() * 3 : 0;
|
|
828
|
-
this.
|
|
829
|
-
detail: { audioLevel: level },
|
|
830
|
-
bubbles: true,
|
|
831
|
-
composed: true
|
|
832
|
-
}));
|
|
805
|
+
this.dispatchCustomEvent("audio-level-changed", { audioLevel: level });
|
|
833
806
|
}, 150);
|
|
834
807
|
}
|
|
835
808
|
async stopRecording() {
|
|
@@ -986,6 +959,12 @@ var CalloutStyles = i`
|
|
|
986
959
|
var callout_default = CalloutStyles;
|
|
987
960
|
|
|
988
961
|
// dist/components/settings-menu.js
|
|
962
|
+
var __decorate = function(decorators, target, key, desc) {
|
|
963
|
+
var c4 = arguments.length, r7 = c4 < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d3;
|
|
964
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r7 = Reflect.decorate(decorators, target, key, desc);
|
|
965
|
+
else for (var i5 = decorators.length - 1; i5 >= 0; i5--) if (d3 = decorators[i5]) r7 = (c4 < 3 ? d3(r7) : c4 > 3 ? d3(target, key, r7) : d3(target, key)) || r7;
|
|
966
|
+
return c4 > 3 && r7 && Object.defineProperty(target, key, r7), r7;
|
|
967
|
+
};
|
|
989
968
|
var SettingsMenu = class SettingsMenu2 extends r4 {
|
|
990
969
|
constructor() {
|
|
991
970
|
super(...arguments);
|
|
@@ -1122,6 +1101,12 @@ SettingsMenu = __decorate([
|
|
|
1122
1101
|
], SettingsMenu);
|
|
1123
1102
|
|
|
1124
1103
|
// dist/components/audio-visualiser.js
|
|
1104
|
+
var __decorate2 = function(decorators, target, key, desc) {
|
|
1105
|
+
var c4 = arguments.length, r7 = c4 < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d3;
|
|
1106
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r7 = Reflect.decorate(decorators, target, key, desc);
|
|
1107
|
+
else for (var i5 = decorators.length - 1; i5 >= 0; i5--) if (d3 = decorators[i5]) r7 = (c4 < 3 ? d3(r7) : c4 > 3 ? d3(target, key, r7) : d3(target, key)) || r7;
|
|
1108
|
+
return c4 > 3 && r7 && Object.defineProperty(target, key, r7), r7;
|
|
1109
|
+
};
|
|
1125
1110
|
var AudioVisualiser = class AudioVisualiser2 extends r4 {
|
|
1126
1111
|
constructor() {
|
|
1127
1112
|
super(...arguments);
|
|
@@ -1167,17 +1152,23 @@ AudioVisualiser.styles = i`
|
|
|
1167
1152
|
opacity: 1;
|
|
1168
1153
|
}
|
|
1169
1154
|
`;
|
|
1170
|
-
|
|
1155
|
+
__decorate2([
|
|
1171
1156
|
n4({ type: Number })
|
|
1172
1157
|
], AudioVisualiser.prototype, "level", void 0);
|
|
1173
|
-
|
|
1158
|
+
__decorate2([
|
|
1174
1159
|
n4({ type: Boolean })
|
|
1175
1160
|
], AudioVisualiser.prototype, "active", void 0);
|
|
1176
|
-
AudioVisualiser =
|
|
1161
|
+
AudioVisualiser = __decorate2([
|
|
1177
1162
|
t3("audio-visualiser")
|
|
1178
1163
|
], AudioVisualiser);
|
|
1179
1164
|
|
|
1180
1165
|
// dist/icons/icons.js
|
|
1166
|
+
var __decorate3 = function(decorators, target, key, desc) {
|
|
1167
|
+
var c4 = arguments.length, r7 = c4 < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d3;
|
|
1168
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r7 = Reflect.decorate(decorators, target, key, desc);
|
|
1169
|
+
else for (var i5 = decorators.length - 1; i5 >= 0; i5--) if (d3 = decorators[i5]) r7 = (c4 < 3 ? d3(r7) : c4 > 3 ? d3(target, key, r7) : d3(target, key)) || r7;
|
|
1170
|
+
return c4 > 3 && r7 && Object.defineProperty(target, key, r7), r7;
|
|
1171
|
+
};
|
|
1181
1172
|
var IconMicOn = class IconMicOn2 extends r4 {
|
|
1182
1173
|
render() {
|
|
1183
1174
|
return x`
|
|
@@ -1202,7 +1193,7 @@ var IconMicOn = class IconMicOn2 extends r4 {
|
|
|
1202
1193
|
`;
|
|
1203
1194
|
}
|
|
1204
1195
|
};
|
|
1205
|
-
IconMicOn =
|
|
1196
|
+
IconMicOn = __decorate3([
|
|
1206
1197
|
t3("icon-mic-on")
|
|
1207
1198
|
], IconMicOn);
|
|
1208
1199
|
var IconMicOff = class IconMicOff2 extends r4 {
|
|
@@ -1230,7 +1221,7 @@ var IconMicOff = class IconMicOff2 extends r4 {
|
|
|
1230
1221
|
</div>`;
|
|
1231
1222
|
}
|
|
1232
1223
|
};
|
|
1233
|
-
IconMicOff =
|
|
1224
|
+
IconMicOff = __decorate3([
|
|
1234
1225
|
t3("icon-mic-off")
|
|
1235
1226
|
], IconMicOff);
|
|
1236
1227
|
var IconRecording = class IconRecording2 extends r4 {
|
|
@@ -1256,7 +1247,7 @@ var IconRecording = class IconRecording2 extends r4 {
|
|
|
1256
1247
|
`;
|
|
1257
1248
|
}
|
|
1258
1249
|
};
|
|
1259
|
-
IconRecording =
|
|
1250
|
+
IconRecording = __decorate3([
|
|
1260
1251
|
t3("icon-recording")
|
|
1261
1252
|
], IconRecording);
|
|
1262
1253
|
var IconSettings = class IconSettings2 extends r4 {
|
|
@@ -1282,7 +1273,7 @@ var IconSettings = class IconSettings2 extends r4 {
|
|
|
1282
1273
|
</div>`;
|
|
1283
1274
|
}
|
|
1284
1275
|
};
|
|
1285
|
-
IconSettings =
|
|
1276
|
+
IconSettings = __decorate3([
|
|
1286
1277
|
t3("icon-settings")
|
|
1287
1278
|
], IconSettings);
|
|
1288
1279
|
var IconLoadingSpinner = class IconLoadingSpinner2 extends r4 {
|
|
@@ -1318,7 +1309,7 @@ IconLoadingSpinner.styles = i`
|
|
|
1318
1309
|
animation: spin 1s linear infinite;
|
|
1319
1310
|
}
|
|
1320
1311
|
`;
|
|
1321
|
-
IconLoadingSpinner =
|
|
1312
|
+
IconLoadingSpinner = __decorate3([
|
|
1322
1313
|
t3("icon-loading-spinner")
|
|
1323
1314
|
], IconLoadingSpinner);
|
|
1324
1315
|
|
|
@@ -1449,6 +1440,12 @@ var ComponentStyles = i`
|
|
|
1449
1440
|
var ComponentStyles_default = ComponentStyles;
|
|
1450
1441
|
|
|
1451
1442
|
// dist/CortiDictation.js
|
|
1443
|
+
var __decorate4 = function(decorators, target, key, desc) {
|
|
1444
|
+
var c4 = arguments.length, r7 = c4 < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d3;
|
|
1445
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r7 = Reflect.decorate(decorators, target, key, desc);
|
|
1446
|
+
else for (var i5 = decorators.length - 1; i5 >= 0; i5--) if (d3 = decorators[i5]) r7 = (c4 < 3 ? d3(r7) : c4 > 3 ? d3(target, key, r7) : d3(target, key)) || r7;
|
|
1447
|
+
return c4 > 3 && r7 && Object.defineProperty(target, key, r7), r7;
|
|
1448
|
+
};
|
|
1452
1449
|
var CortiDictation = class extends r4 {
|
|
1453
1450
|
constructor() {
|
|
1454
1451
|
super(...arguments);
|
|
@@ -1557,19 +1554,19 @@ var CortiDictation = class extends r4 {
|
|
|
1557
1554
|
}
|
|
1558
1555
|
};
|
|
1559
1556
|
CortiDictation.styles = [buttons_default, theme_default, ComponentStyles_default, callout_default];
|
|
1560
|
-
|
|
1557
|
+
__decorate4([
|
|
1561
1558
|
n4({ type: Array })
|
|
1562
1559
|
], CortiDictation.prototype, "devices", void 0);
|
|
1563
|
-
|
|
1560
|
+
__decorate4([
|
|
1564
1561
|
n4({ type: String, reflect: true })
|
|
1565
1562
|
], CortiDictation.prototype, "recordingState", void 0);
|
|
1566
|
-
|
|
1563
|
+
__decorate4([
|
|
1567
1564
|
n4({ type: Object })
|
|
1568
1565
|
], CortiDictation.prototype, "dictationConfig", void 0);
|
|
1569
|
-
|
|
1566
|
+
__decorate4([
|
|
1570
1567
|
n4({ type: String })
|
|
1571
1568
|
], CortiDictation.prototype, "authToken", void 0);
|
|
1572
|
-
|
|
1569
|
+
__decorate4([
|
|
1573
1570
|
r6()
|
|
1574
1571
|
], CortiDictation.prototype, "_audioLevel", void 0);
|
|
1575
1572
|
var CortiDictation_default = CortiDictation;
|
package/package.json
CHANGED
|
@@ -2,17 +2,21 @@
|
|
|
2
2
|
"name": "@corti/dictation-web",
|
|
3
3
|
"description": "Web component for Corti Dictation",
|
|
4
4
|
"author": "Corti ApS",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.5",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"module": "dist/index.js",
|
|
9
9
|
"exports": {
|
|
10
|
-
"
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"default": "./dist/bundle.js"
|
|
11
12
|
},
|
|
13
|
+
"unpkg": "dist/bundle.js",
|
|
12
14
|
"files": ["dist"],
|
|
13
15
|
"scripts": {
|
|
14
16
|
"analyze": "cem analyze --litelement",
|
|
15
17
|
"build": "tsc && npm run analyze -- --exclude dist",
|
|
18
|
+
"build:bundle": "esbuild dist/index.js --bundle --outfile=dist/bundle.js --format=esm --platform=browser",
|
|
19
|
+
"release": "npm run build && npm run build:bundle && npm publish --access public",
|
|
16
20
|
"start": "npm run build && concurrently -k -r \"tsc --watch --preserveWatchOutput\" \"web-dev-server\"",
|
|
17
21
|
"prepublish": "tsc && npm run analyze -- --exclude dist",
|
|
18
22
|
"lint": "eslint --ext .ts,.tsx src --ignore-path .gitignore && prettier \"src/**/*.ts\" --check --ignore-path .gitignore",
|