@dxos/plugin-transcription 0.8.4-main.67995b8 → 0.8.4-main.ae835ea
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/lib/browser/TranscriptContainer-2GSL2XB5.mjs +11 -0
- package/dist/lib/browser/blueprint-definition-UAAJYVLZ.mjs +150 -0
- package/dist/lib/browser/blueprint-definition-UAAJYVLZ.mjs.map +7 -0
- package/dist/lib/browser/{chunk-U6QBOGTN.mjs → chunk-3MKZ2MNQ.mjs} +5 -5
- package/dist/lib/browser/chunk-3MKZ2MNQ.mjs.map +7 -0
- package/dist/lib/browser/{chunk-4FJIYH7T.mjs → chunk-535OJKFO.mjs} +2 -2
- package/dist/lib/browser/{chunk-5KPYIC3N.mjs → chunk-7DR6HZEF.mjs} +332 -363
- package/dist/lib/browser/chunk-7DR6HZEF.mjs.map +7 -0
- package/dist/lib/browser/chunk-VBUIO677.mjs +29 -0
- package/dist/lib/browser/chunk-VBUIO677.mjs.map +7 -0
- package/dist/lib/browser/chunk-W7WKZTM4.mjs +63 -0
- package/dist/lib/browser/chunk-W7WKZTM4.mjs.map +7 -0
- package/dist/lib/browser/{chunk-FFEPEPCU.mjs → chunk-WH36ENNE.mjs} +49 -78
- package/dist/lib/browser/chunk-WH36ENNE.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +24 -19
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/intent-resolver-ZTKTEAQX.mjs +25 -0
- package/dist/lib/browser/intent-resolver-ZTKTEAQX.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-surface-E5D5AE3F.mjs → react-surface-KA32A72I.mjs} +10 -10
- package/dist/lib/browser/react-surface-KA32A72I.mjs.map +7 -0
- package/dist/lib/browser/{transcriber-PXT4QBFY.mjs → transcriber-LWOLYQHC.mjs} +7 -7
- package/dist/lib/browser/transcriber-LWOLYQHC.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +6 -8
- package/dist/lib/node-esm/{TranscriptContainer-VBAOM5DG.mjs → TranscriptContainer-GRLDCESB.mjs} +4 -4
- package/dist/lib/node-esm/blueprint-definition-Z3LTZ3ID.mjs +151 -0
- package/dist/lib/node-esm/blueprint-definition-Z3LTZ3ID.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-TJKAO7VR.mjs → chunk-K4AZOB5Y.mjs} +332 -363
- package/dist/lib/node-esm/chunk-K4AZOB5Y.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-OLMSTF3M.mjs +64 -0
- package/dist/lib/node-esm/chunk-OLMSTF3M.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-Y2B4HWSS.mjs → chunk-Q6WD7L2J.mjs} +2 -2
- package/dist/lib/node-esm/{chunk-RHF2ALML.mjs → chunk-SWUVPFKR.mjs} +5 -5
- package/dist/lib/node-esm/chunk-SWUVPFKR.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-HT3W7LDP.mjs → chunk-YFN4FJFK.mjs} +49 -78
- package/dist/lib/node-esm/chunk-YFN4FJFK.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-YVNQN2J6.mjs +30 -0
- package/dist/lib/node-esm/chunk-YVNQN2J6.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +24 -19
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/intent-resolver-55WH2GY6.mjs +26 -0
- package/dist/lib/node-esm/intent-resolver-55WH2GY6.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{react-surface-QRDJOHN5.mjs → react-surface-GU7LW2JO.mjs} +10 -10
- package/dist/lib/node-esm/react-surface-GU7LW2JO.mjs.map +7 -0
- package/dist/lib/node-esm/{transcriber-YUTEVANE.mjs → transcriber-UGB7ECX6.mjs} +7 -7
- package/dist/lib/node-esm/transcriber-UGB7ECX6.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +6 -8
- package/dist/types/src/TranscriptionPlugin.d.ts +1 -1
- package/dist/types/src/TranscriptionPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/blueprint-definition.d.ts +5 -0
- package/dist/types/src/capabilities/blueprint-definition.d.ts.map +1 -0
- package/dist/types/src/capabilities/capabilities.d.ts +1 -1
- package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +3 -2
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts +1 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts +1 -1
- package/dist/types/src/capabilities/transcriber.d.ts +1 -1
- package/dist/types/src/capabilities/transcriber.d.ts.map +1 -1
- package/dist/types/src/components/Transcript/Transcript.d.ts +5 -5
- package/dist/types/src/components/Transcript/Transcript.d.ts.map +1 -1
- package/dist/types/src/components/Transcript/Transcript.stories.d.ts +31 -16
- package/dist/types/src/components/Transcript/Transcript.stories.d.ts.map +1 -1
- package/dist/types/src/components/Transcript/deprecated/OldTranscript.d.ts +3 -3
- package/dist/types/src/components/Transcript/deprecated/OldTranscript.d.ts.map +1 -1
- package/dist/types/src/components/Transcript/transcript-extension.d.ts +1 -5
- package/dist/types/src/components/Transcript/transcript-extension.d.ts.map +1 -1
- package/dist/types/src/components/TranscriptContainer.d.ts +2 -2
- package/dist/types/src/components/TranscriptContainer.d.ts.map +1 -1
- package/dist/types/src/components/stories/FileTranscription.stories.d.ts +5 -4
- package/dist/types/src/components/stories/FileTranscription.stories.d.ts.map +1 -1
- package/dist/types/src/components/stories/KeyWordRecognition.stories.d.ts +10 -6
- package/dist/types/src/components/stories/KeyWordRecognition.stories.d.ts.map +1 -1
- package/dist/types/src/components/stories/MicrophoneTranscription.stories.d.ts +7 -6
- package/dist/types/src/components/stories/MicrophoneTranscription.stories.d.ts.map +1 -1
- package/dist/types/src/components/stories/TranscriptionStory.d.ts +2 -1
- package/dist/types/src/components/stories/TranscriptionStory.d.ts.map +1 -1
- package/dist/types/src/functions/index.d.ts +3 -0
- package/dist/types/src/functions/index.d.ts.map +1 -0
- package/dist/types/src/functions/open.d.ts +7 -0
- package/dist/types/src/functions/open.d.ts.map +1 -0
- package/dist/types/src/functions/summarize.d.ts +11 -0
- package/dist/types/src/functions/summarize.d.ts.map +1 -0
- package/dist/types/src/hooks/useAudioFile.d.ts.map +1 -1
- package/dist/types/src/hooks/useVoiceInput.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +0 -1
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/segments-normalization/normalization.d.ts +388 -328
- package/dist/types/src/segments-normalization/normalization.d.ts.map +1 -1
- package/dist/types/src/testing/testing.d.ts +2 -2
- package/dist/types/src/testing/testing.d.ts.map +1 -1
- package/dist/types/src/transcriber/media-stream-recorder.d.ts +1 -1
- package/dist/types/src/transcriber/media-stream-recorder.d.ts.map +1 -1
- package/dist/types/src/transcriber/transcriber.d.ts.map +1 -1
- package/dist/types/src/transcriber/transcription-manager.d.ts +3 -7
- package/dist/types/src/transcriber/transcription-manager.d.ts.map +1 -1
- package/dist/types/src/types/Transcript.d.ts +30 -0
- package/dist/types/src/types/Transcript.d.ts.map +1 -0
- package/dist/types/src/types/TranscriptAction.d.ts +23 -0
- package/dist/types/src/types/TranscriptAction.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +2 -1
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/types/types.d.ts +0 -26
- package/dist/types/src/types/types.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +65 -66
- package/src/TranscriptionPlugin.tsx +58 -53
- package/src/capabilities/blueprint-definition.ts +31 -0
- package/src/capabilities/capabilities.ts +6 -6
- package/src/capabilities/index.ts +1 -0
- package/src/capabilities/intent-resolver.ts +5 -11
- package/src/capabilities/react-surface.tsx +2 -2
- package/src/capabilities/transcriber.ts +3 -2
- package/src/components/Transcript/Transcript.stories.tsx +34 -31
- package/src/components/Transcript/Transcript.tsx +20 -27
- package/src/components/Transcript/deprecated/OldTranscript.tsx +9 -9
- package/src/components/Transcript/transcript-extension.ts +2 -39
- package/src/components/TranscriptContainer.tsx +7 -6
- package/src/components/stories/FileTranscription.stories.tsx +47 -36
- package/src/components/stories/KeyWordRecognition.stories.tsx +14 -10
- package/src/components/stories/MicrophoneTranscription.stories.tsx +40 -37
- package/src/components/stories/TranscriptionStory.tsx +10 -6
- package/src/functions/index.ts +6 -0
- package/src/functions/open.ts +39 -0
- package/src/functions/summarize.ts +103 -0
- package/src/hooks/useAudioFile.ts +49 -53
- package/src/hooks/useVoiceInput.ts +3 -2
- package/src/meta.ts +7 -4
- package/src/model/model.test.ts +1 -1
- package/src/segments-normalization/message-normalizer.ts +1 -1
- package/src/segments-normalization/normalization.test.ts +5 -5
- package/src/segments-normalization/normalization.ts +38 -37
- package/src/testing/testing.ts +7 -7
- package/src/transcriber/media-stream-recorder.ts +1 -1
- package/src/transcriber/transcriber.browser.test.ts +2 -1
- package/src/transcriber/transcriber.ts +2 -1
- package/src/transcriber/transcription-manager.ts +17 -38
- package/src/types/{schema.ts → Transcript.ts} +12 -9
- package/src/types/TranscriptAction.ts +24 -0
- package/src/types/index.ts +2 -1
- package/src/types/types.ts +0 -23
- package/dist/lib/browser/TranscriptContainer-6WCKCXQ6.mjs +0 -11
- package/dist/lib/browser/chunk-5KPYIC3N.mjs.map +0 -7
- package/dist/lib/browser/chunk-5WH45KBY.mjs +0 -19
- package/dist/lib/browser/chunk-5WH45KBY.mjs.map +0 -7
- package/dist/lib/browser/chunk-FFEPEPCU.mjs.map +0 -7
- package/dist/lib/browser/chunk-R7INNNUQ.mjs +0 -55
- package/dist/lib/browser/chunk-R7INNNUQ.mjs.map +0 -7
- package/dist/lib/browser/chunk-U6QBOGTN.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-3O33MMP5.mjs +0 -30
- package/dist/lib/browser/intent-resolver-3O33MMP5.mjs.map +0 -7
- package/dist/lib/browser/react-surface-E5D5AE3F.mjs.map +0 -7
- package/dist/lib/browser/transcriber-PXT4QBFY.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-HT3W7LDP.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-RHF2ALML.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-TJKAO7VR.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-U65ZWK3L.mjs +0 -56
- package/dist/lib/node-esm/chunk-U65ZWK3L.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-XMUCZBP3.mjs +0 -21
- package/dist/lib/node-esm/chunk-XMUCZBP3.mjs.map +0 -7
- package/dist/lib/node-esm/intent-resolver-YMN5SXNC.mjs +0 -31
- package/dist/lib/node-esm/intent-resolver-YMN5SXNC.mjs.map +0 -7
- package/dist/lib/node-esm/react-surface-QRDJOHN5.mjs.map +0 -7
- package/dist/lib/node-esm/transcriber-YUTEVANE.mjs.map +0 -7
- package/dist/types/src/types/schema.d.ts +0 -41
- package/dist/types/src/types/schema.d.ts.map +0 -1
- /package/dist/lib/browser/{TranscriptContainer-6WCKCXQ6.mjs.map → TranscriptContainer-2GSL2XB5.mjs.map} +0 -0
- /package/dist/lib/browser/{chunk-4FJIYH7T.mjs.map → chunk-535OJKFO.mjs.map} +0 -0
- /package/dist/lib/node-esm/{TranscriptContainer-VBAOM5DG.mjs.map → TranscriptContainer-GRLDCESB.mjs.map} +0 -0
- /package/dist/lib/node-esm/{chunk-Y2B4HWSS.mjs.map → chunk-Q6WD7L2J.mjs.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TranscriptionCapabilities
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-3MKZ2MNQ.mjs";
|
|
4
4
|
|
|
5
5
|
// src/components/TranscriptContainer.tsx
|
|
6
6
|
import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
|
|
@@ -9,28 +9,134 @@ import { fullyQualifiedId, getSpace } from "@dxos/client/echo";
|
|
|
9
9
|
import { useMembers, useQueue } from "@dxos/react-client/echo";
|
|
10
10
|
import { StackItem } from "@dxos/react-ui-stack";
|
|
11
11
|
|
|
12
|
-
// src/
|
|
13
|
-
import {
|
|
14
|
-
import
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
// src/hooks/useAudioFile.ts
|
|
13
|
+
import { useEffect, useState } from "react";
|
|
14
|
+
import { scheduleTask } from "@dxos/async";
|
|
15
|
+
import { Context } from "@dxos/context";
|
|
16
|
+
import { log } from "@dxos/log";
|
|
17
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/plugins/plugin-transcription/src/hooks/useAudioFile.ts";
|
|
18
|
+
var useAudioFile = (audioUrl, constraints) => {
|
|
19
|
+
const [{ audio, stream, track }, setStream] = useState({});
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
const ctx = new Context(void 0, {
|
|
22
|
+
F: __dxlog_file,
|
|
23
|
+
L: 20
|
|
24
|
+
});
|
|
25
|
+
scheduleTask(ctx, async () => {
|
|
26
|
+
try {
|
|
27
|
+
const response = await fetch(audioUrl);
|
|
28
|
+
const blob = await response.blob();
|
|
29
|
+
const objectUrl = URL.createObjectURL(blob);
|
|
30
|
+
ctx.onDispose(() => {
|
|
31
|
+
URL.revokeObjectURL(objectUrl);
|
|
32
|
+
});
|
|
33
|
+
const audio2 = new Audio();
|
|
34
|
+
audio2.src = objectUrl;
|
|
35
|
+
await new Promise((resolve, reject) => {
|
|
36
|
+
audio2.addEventListener("error", (err) => {
|
|
37
|
+
log.error("error", {
|
|
38
|
+
err
|
|
39
|
+
}, {
|
|
40
|
+
F: __dxlog_file,
|
|
41
|
+
L: 39,
|
|
42
|
+
S: void 0,
|
|
43
|
+
C: (f, a) => f(...a)
|
|
44
|
+
});
|
|
45
|
+
reject(err);
|
|
46
|
+
}, {
|
|
47
|
+
once: true
|
|
48
|
+
});
|
|
49
|
+
audio2.addEventListener("canplay", async () => {
|
|
50
|
+
resolve();
|
|
51
|
+
}, {
|
|
52
|
+
once: true
|
|
53
|
+
});
|
|
54
|
+
audio2.load();
|
|
55
|
+
});
|
|
56
|
+
const audioCtx = new AudioContext();
|
|
57
|
+
if (audioCtx.state === "suspended") {
|
|
58
|
+
await audioCtx.resume();
|
|
59
|
+
}
|
|
60
|
+
const destination = audioCtx.createMediaStreamDestination();
|
|
61
|
+
destination.channelCount = 1;
|
|
62
|
+
const source = audioCtx.createMediaElementSource(audio2);
|
|
63
|
+
source.connect(destination);
|
|
64
|
+
const track2 = destination.stream.getAudioTracks()[0];
|
|
65
|
+
if (constraints) {
|
|
66
|
+
await track2.applyConstraints(constraints).catch((err) => log.catch(err, void 0, {
|
|
67
|
+
F: __dxlog_file,
|
|
68
|
+
L: 68,
|
|
69
|
+
S: void 0,
|
|
70
|
+
C: (f, a) => f(...a)
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
73
|
+
setStream({
|
|
74
|
+
audio: audio2,
|
|
75
|
+
stream: destination.stream,
|
|
76
|
+
track: destination.stream.getAudioTracks()[0]
|
|
77
|
+
});
|
|
78
|
+
} catch (err) {
|
|
79
|
+
log.catch(err, void 0, {
|
|
80
|
+
F: __dxlog_file,
|
|
81
|
+
L: 78,
|
|
82
|
+
S: void 0,
|
|
83
|
+
C: (f, a) => f(...a)
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
return () => {
|
|
88
|
+
void ctx.dispose();
|
|
89
|
+
};
|
|
90
|
+
}, [
|
|
91
|
+
audioUrl
|
|
92
|
+
]);
|
|
93
|
+
return {
|
|
94
|
+
audio,
|
|
95
|
+
stream,
|
|
96
|
+
track
|
|
97
|
+
};
|
|
98
|
+
};
|
|
19
99
|
|
|
20
|
-
// src/
|
|
21
|
-
import {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
100
|
+
// src/hooks/useAudioTrack.ts
|
|
101
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
102
|
+
var useAudioTrack = (active, constraints) => {
|
|
103
|
+
const [track, setTrack] = useState2();
|
|
104
|
+
useEffect2(() => {
|
|
105
|
+
if (!active) {
|
|
106
|
+
track?.stop();
|
|
107
|
+
setTrack(void 0);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const initAudio = async () => {
|
|
111
|
+
const audio = new Audio();
|
|
112
|
+
audio.srcObject = await navigator.mediaDevices.getUserMedia({
|
|
113
|
+
audio: constraints ?? true
|
|
114
|
+
});
|
|
115
|
+
const [track2] = audio.srcObject.getAudioTracks();
|
|
116
|
+
if (track2) {
|
|
117
|
+
setTrack(track2);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
if (active) {
|
|
121
|
+
void initAudio();
|
|
122
|
+
}
|
|
123
|
+
}, [
|
|
124
|
+
active
|
|
125
|
+
]);
|
|
126
|
+
return track;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
// src/hooks/useQueueModelAdapter.ts
|
|
130
|
+
import { useEffect as useEffect3, useMemo, useState as useState3 } from "react";
|
|
26
131
|
|
|
27
132
|
// src/model/model.ts
|
|
28
133
|
import { Text } from "@codemirror/state";
|
|
29
134
|
import { Event } from "@dxos/async";
|
|
30
135
|
import { invariant } from "@dxos/invariant";
|
|
31
|
-
import { log } from "@dxos/log";
|
|
32
|
-
var
|
|
136
|
+
import { log as log2 } from "@dxos/log";
|
|
137
|
+
var __dxlog_file2 = "/__w/dxos/dxos/packages/plugins/plugin-transcription/src/model/model.ts";
|
|
33
138
|
var DocumentAdapter = class {
|
|
139
|
+
_view;
|
|
34
140
|
constructor(_view) {
|
|
35
141
|
this._view = _view;
|
|
36
142
|
}
|
|
@@ -39,13 +145,13 @@ var DocumentAdapter = class {
|
|
|
39
145
|
return this._view.state.doc.lines - 1;
|
|
40
146
|
}
|
|
41
147
|
replaceLines(from, remove, insert) {
|
|
42
|
-
|
|
148
|
+
log2("replaceLines", {
|
|
43
149
|
count: this._view.state.doc.lines,
|
|
44
150
|
from,
|
|
45
151
|
remove,
|
|
46
152
|
insert
|
|
47
153
|
}, {
|
|
48
|
-
F:
|
|
154
|
+
F: __dxlog_file2,
|
|
49
155
|
L: 39,
|
|
50
156
|
S: this,
|
|
51
157
|
C: (f, a) => f(...a)
|
|
@@ -67,13 +173,19 @@ var DocumentAdapter = class {
|
|
|
67
173
|
}
|
|
68
174
|
};
|
|
69
175
|
var SerializationModel = class {
|
|
176
|
+
_renderer;
|
|
177
|
+
/** Ordered set of chunks. */
|
|
178
|
+
_chunks = [];
|
|
179
|
+
/** Map of chunk IDs to their current line counts. */
|
|
180
|
+
_chunkLineCounts = /* @__PURE__ */ new Map();
|
|
181
|
+
/** Map of line numbers to chunk IDs. */
|
|
182
|
+
_lineToChunk = /* @__PURE__ */ new Map();
|
|
183
|
+
/** Track chunk changes since last sync. */
|
|
184
|
+
_changes = [];
|
|
185
|
+
/** Emits when the document is updated. */
|
|
186
|
+
update = new Event();
|
|
70
187
|
constructor(_renderer, initialChunks = []) {
|
|
71
188
|
this._renderer = _renderer;
|
|
72
|
-
this._chunks = [];
|
|
73
|
-
this._chunkLineCounts = /* @__PURE__ */ new Map();
|
|
74
|
-
this._lineToChunk = /* @__PURE__ */ new Map();
|
|
75
|
-
this._changes = [];
|
|
76
|
-
this.update = new Event();
|
|
77
189
|
initialChunks.forEach((chunk) => {
|
|
78
190
|
this.appendChunk(chunk);
|
|
79
191
|
});
|
|
@@ -120,7 +232,7 @@ var SerializationModel = class {
|
|
|
120
232
|
updateChunk(chunk) {
|
|
121
233
|
const index = this._chunks.findIndex((c) => c.id === chunk.id);
|
|
122
234
|
invariant(index !== -1, void 0, {
|
|
123
|
-
F:
|
|
235
|
+
F: __dxlog_file2,
|
|
124
236
|
L: 147,
|
|
125
237
|
S: this,
|
|
126
238
|
A: [
|
|
@@ -140,7 +252,7 @@ var SerializationModel = class {
|
|
|
140
252
|
deleteBlock(id) {
|
|
141
253
|
const index = this._chunks.findIndex((c) => c.id === id);
|
|
142
254
|
invariant(index !== -1, void 0, {
|
|
143
|
-
F:
|
|
255
|
+
F: __dxlog_file2,
|
|
144
256
|
L: 156,
|
|
145
257
|
S: this,
|
|
146
258
|
A: [
|
|
@@ -161,10 +273,10 @@ var SerializationModel = class {
|
|
|
161
273
|
* Syncs the tracked changes with the ChunkDocument.
|
|
162
274
|
*/
|
|
163
275
|
sync(document2) {
|
|
164
|
-
|
|
276
|
+
log2("sync", {
|
|
165
277
|
changes: this._changes
|
|
166
278
|
}, {
|
|
167
|
-
F:
|
|
279
|
+
F: __dxlog_file2,
|
|
168
280
|
L: 167,
|
|
169
281
|
S: this,
|
|
170
282
|
C: (f, a) => f(...a)
|
|
@@ -217,8 +329,172 @@ var SerializationModel = class {
|
|
|
217
329
|
}
|
|
218
330
|
};
|
|
219
331
|
|
|
332
|
+
// src/hooks/useQueueModelAdapter.ts
|
|
333
|
+
var useQueueModelAdapter = (renderer, queue, initialChunks = []) => {
|
|
334
|
+
const model = useMemo(() => new SerializationModel(renderer, initialChunks), [
|
|
335
|
+
queue
|
|
336
|
+
]);
|
|
337
|
+
const [loaded, setLoaded] = useState3(false);
|
|
338
|
+
useEffect3(() => {
|
|
339
|
+
if (!queue) {
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
const update = () => {
|
|
343
|
+
for (const block of queue?.objects ?? []) {
|
|
344
|
+
model.appendChunk(block);
|
|
345
|
+
}
|
|
346
|
+
setLoaded(true);
|
|
347
|
+
};
|
|
348
|
+
let i;
|
|
349
|
+
if (queue.isLoading) {
|
|
350
|
+
i = setInterval(() => {
|
|
351
|
+
if (!queue?.isLoading) {
|
|
352
|
+
clearInterval(i);
|
|
353
|
+
update();
|
|
354
|
+
}
|
|
355
|
+
}, 1e3);
|
|
356
|
+
} else {
|
|
357
|
+
update();
|
|
358
|
+
}
|
|
359
|
+
return () => clearTimeout(i);
|
|
360
|
+
}, [
|
|
361
|
+
model,
|
|
362
|
+
queue
|
|
363
|
+
]);
|
|
364
|
+
useEffect3(() => {
|
|
365
|
+
if (!loaded || !queue || model.chunks.length === queue.objects.length) {
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
const chunk = queue.objects.at(-1);
|
|
369
|
+
if (chunk) {
|
|
370
|
+
model.appendChunk(chunk);
|
|
371
|
+
}
|
|
372
|
+
}, [
|
|
373
|
+
model,
|
|
374
|
+
loaded,
|
|
375
|
+
queue?.objects.length
|
|
376
|
+
]);
|
|
377
|
+
return model;
|
|
378
|
+
};
|
|
379
|
+
|
|
380
|
+
// src/hooks/useTranscriber.ts
|
|
381
|
+
import { useEffect as useEffect4, useMemo as useMemo2 } from "react";
|
|
382
|
+
import { useCapabilities } from "@dxos/app-framework";
|
|
383
|
+
|
|
384
|
+
// src/capabilities/index.ts
|
|
385
|
+
import { lazy } from "@dxos/app-framework";
|
|
386
|
+
var BlueprintDefinition = lazy(() => import("./blueprint-definition-UAAJYVLZ.mjs"));
|
|
387
|
+
var IntentResolver = lazy(() => import("./intent-resolver-ZTKTEAQX.mjs"));
|
|
388
|
+
var ReactSurface = lazy(() => import("./react-surface-KA32A72I.mjs"));
|
|
389
|
+
var Transcriber = lazy(() => import("./transcriber-LWOLYQHC.mjs"));
|
|
390
|
+
|
|
391
|
+
// src/hooks/useTranscriber.ts
|
|
392
|
+
var useTranscriber = ({ audioStreamTrack, recorderConfig, transcriberConfig, onSegments }) => {
|
|
393
|
+
const [getTranscriber] = useCapabilities(TranscriptionCapabilities.Transcriber);
|
|
394
|
+
const transcriber = useMemo2(() => {
|
|
395
|
+
if (!getTranscriber || !audioStreamTrack || !onSegments) {
|
|
396
|
+
return void 0;
|
|
397
|
+
}
|
|
398
|
+
return getTranscriber({
|
|
399
|
+
audioStreamTrack,
|
|
400
|
+
recorderConfig,
|
|
401
|
+
transcriberConfig,
|
|
402
|
+
onSegments
|
|
403
|
+
});
|
|
404
|
+
}, [
|
|
405
|
+
getTranscriber,
|
|
406
|
+
audioStreamTrack,
|
|
407
|
+
recorderConfig,
|
|
408
|
+
transcriberConfig,
|
|
409
|
+
onSegments
|
|
410
|
+
]);
|
|
411
|
+
useEffect4(() => {
|
|
412
|
+
return () => {
|
|
413
|
+
void transcriber?.close();
|
|
414
|
+
};
|
|
415
|
+
}, [
|
|
416
|
+
transcriber
|
|
417
|
+
]);
|
|
418
|
+
return transcriber;
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
// src/hooks/useVoiceInput.ts
|
|
422
|
+
import { useCallback, useEffect as useEffect5, useState as useState4 } from "react";
|
|
423
|
+
import { scheduleMicroTask } from "@dxos/async";
|
|
424
|
+
import { Context as Context2 } from "@dxos/context";
|
|
425
|
+
import { log as log3 } from "@dxos/log";
|
|
426
|
+
import { useSoundEffect } from "@dxos/react-ui-sfx";
|
|
427
|
+
var __dxlog_file3 = "/__w/dxos/dxos/packages/plugins/plugin-transcription/src/hooks/useVoiceInput.ts";
|
|
428
|
+
var useVoiceInput = ({ active, onUpdate }) => {
|
|
429
|
+
const soundStart = useSoundEffect("StartRecording");
|
|
430
|
+
const soundStop = useSoundEffect("StopRecording");
|
|
431
|
+
const handleSegments = useCallback(async (segments) => {
|
|
432
|
+
const text = segments.map((str) => str.text.trim().replace(/[^\w\s]/g, "")).join(" ");
|
|
433
|
+
onUpdate(text);
|
|
434
|
+
}, []);
|
|
435
|
+
const [recording, setRecording] = useState4(false);
|
|
436
|
+
const track = useAudioTrack(active);
|
|
437
|
+
const transcriber = useTranscriber({
|
|
438
|
+
audioStreamTrack: track,
|
|
439
|
+
onSegments: handleSegments
|
|
440
|
+
});
|
|
441
|
+
useEffect5(() => {
|
|
442
|
+
const ctx = new Context2(void 0, {
|
|
443
|
+
F: __dxlog_file3,
|
|
444
|
+
L: 44
|
|
445
|
+
});
|
|
446
|
+
scheduleMicroTask(ctx, async () => {
|
|
447
|
+
if (active && transcriber) {
|
|
448
|
+
await transcriber.open();
|
|
449
|
+
log3.info("starting...", void 0, {
|
|
450
|
+
F: __dxlog_file3,
|
|
451
|
+
L: 48,
|
|
452
|
+
S: void 0,
|
|
453
|
+
C: (f, a) => f(...a)
|
|
454
|
+
});
|
|
455
|
+
setRecording(true);
|
|
456
|
+
void soundStart.play();
|
|
457
|
+
transcriber.startChunksRecording();
|
|
458
|
+
} else if (!active && transcriber?.isOpen) {
|
|
459
|
+
transcriber?.stopChunksRecording();
|
|
460
|
+
await transcriber?.close();
|
|
461
|
+
log3.info("stopped", void 0, {
|
|
462
|
+
F: __dxlog_file3,
|
|
463
|
+
L: 55,
|
|
464
|
+
S: void 0,
|
|
465
|
+
C: (f, a) => f(...a)
|
|
466
|
+
});
|
|
467
|
+
setRecording(false);
|
|
468
|
+
void soundStop.play();
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
return () => {
|
|
472
|
+
void ctx.dispose();
|
|
473
|
+
};
|
|
474
|
+
}, [
|
|
475
|
+
active,
|
|
476
|
+
transcriber
|
|
477
|
+
]);
|
|
478
|
+
return {
|
|
479
|
+
recording
|
|
480
|
+
};
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
// src/components/Transcript/Transcript.tsx
|
|
484
|
+
import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
|
|
485
|
+
import React from "react";
|
|
486
|
+
import { useThemeContext } from "@dxos/react-ui";
|
|
487
|
+
import { autoScroll, createBasicExtensions, createMarkdownExtensions, createThemeExtensions, decorateMarkdown, preview, useTextEditor } from "@dxos/react-ui-editor";
|
|
488
|
+
import { mx } from "@dxos/react-ui-theme";
|
|
489
|
+
import { isTruthy } from "@dxos/util";
|
|
490
|
+
|
|
220
491
|
// src/components/Transcript/transcript-extension.ts
|
|
221
|
-
|
|
492
|
+
import { RangeSetBuilder } from "@codemirror/state";
|
|
493
|
+
import { EditorView, GutterMarker, ViewPlugin, gutter } from "@codemirror/view";
|
|
494
|
+
import { format } from "date-fns/format";
|
|
495
|
+
import { intervalToDuration } from "date-fns/intervalToDuration";
|
|
496
|
+
import { addEventListener, combine } from "@dxos/async";
|
|
497
|
+
var transcript = ({ model, started }) => {
|
|
222
498
|
return [
|
|
223
499
|
// Show timestamps in the gutter.
|
|
224
500
|
gutter({
|
|
@@ -246,8 +522,11 @@ var transcript = ({ model, started, renderButton }) => {
|
|
|
246
522
|
}),
|
|
247
523
|
// Listen for model updates.
|
|
248
524
|
ViewPlugin.fromClass(class {
|
|
525
|
+
_controls;
|
|
526
|
+
_cleanup;
|
|
527
|
+
_adapter;
|
|
528
|
+
_initialized = false;
|
|
249
529
|
constructor(view) {
|
|
250
|
-
this._initialized = false;
|
|
251
530
|
this._adapter = new DocumentAdapter(view);
|
|
252
531
|
const scroller = view.scrollDOM;
|
|
253
532
|
let isAutoScrolling = false;
|
|
@@ -269,30 +548,20 @@ var transcript = ({ model, started, renderButton }) => {
|
|
|
269
548
|
})
|
|
270
549
|
});
|
|
271
550
|
};
|
|
272
|
-
if (renderButton) {
|
|
273
|
-
this._controls = document.createElement("div");
|
|
274
|
-
this._controls.classList.add("cm-controls", "transition-opacity", "duration-300", "opacity-0");
|
|
275
|
-
view.dom.appendChild(this._controls);
|
|
276
|
-
renderButton(this._controls, {
|
|
277
|
-
onClick: () => {
|
|
278
|
-
scrollToBottom(false);
|
|
279
|
-
}
|
|
280
|
-
}, view);
|
|
281
|
-
}
|
|
282
551
|
this._cleanup = combine(addEventListener(view.scrollDOM, "scroll", () => {
|
|
283
552
|
if (!isAutoScrolling) {
|
|
284
553
|
hasScrolled = true;
|
|
285
554
|
this._controls?.classList.remove("opacity-0");
|
|
286
555
|
}
|
|
287
556
|
}), model.update.on(() => {
|
|
288
|
-
const
|
|
557
|
+
const autoScroll2 = scroller.scrollHeight - scroller.scrollTop - scroller.clientHeight === 0 || !hasScrolled;
|
|
289
558
|
model.sync(this._adapter);
|
|
290
|
-
if (
|
|
559
|
+
if (autoScroll2) {
|
|
291
560
|
scrollToBottom(true);
|
|
292
561
|
}
|
|
293
562
|
}));
|
|
294
563
|
}
|
|
295
|
-
update(
|
|
564
|
+
update(_update) {
|
|
296
565
|
if (!this._initialized) {
|
|
297
566
|
this._initialized = true;
|
|
298
567
|
setTimeout(() => {
|
|
@@ -306,25 +575,6 @@ var transcript = ({ model, started, renderButton }) => {
|
|
|
306
575
|
}
|
|
307
576
|
}),
|
|
308
577
|
EditorView.theme({
|
|
309
|
-
".cm-scroller": {
|
|
310
|
-
overflowY: "scroll"
|
|
311
|
-
},
|
|
312
|
-
".cm-hide-scrollbar": {
|
|
313
|
-
scrollbarWidth: "none",
|
|
314
|
-
"-ms-overflow-style": "none"
|
|
315
|
-
},
|
|
316
|
-
".cm-hide-scrollbar::-webkit-scrollbar": {
|
|
317
|
-
display: "none"
|
|
318
|
-
},
|
|
319
|
-
".cm-controls": {
|
|
320
|
-
position: "absolute",
|
|
321
|
-
bottom: "0.5rem",
|
|
322
|
-
right: "0.5rem",
|
|
323
|
-
zIndex: 1e3
|
|
324
|
-
},
|
|
325
|
-
".cm-line": {
|
|
326
|
-
paddingRight: "1rem"
|
|
327
|
-
},
|
|
328
578
|
".cm-timestamp-gutter": {
|
|
329
579
|
width: "6rem",
|
|
330
580
|
paddingRight: "1rem"
|
|
@@ -338,6 +588,9 @@ var transcript = ({ model, started, renderButton }) => {
|
|
|
338
588
|
];
|
|
339
589
|
};
|
|
340
590
|
var TimestampMarker = class extends GutterMarker {
|
|
591
|
+
_line;
|
|
592
|
+
_timestamp;
|
|
593
|
+
_started;
|
|
341
594
|
constructor(_line, _timestamp, _started) {
|
|
342
595
|
super(), this._line = _line, this._timestamp = _timestamp, this._started = _started;
|
|
343
596
|
}
|
|
@@ -382,7 +635,7 @@ var formatTimestamp = (timestamp, relative) => {
|
|
|
382
635
|
};
|
|
383
636
|
|
|
384
637
|
// src/components/Transcript/Transcript.tsx
|
|
385
|
-
var
|
|
638
|
+
var renderByline = (identities) => (message, index, debug = false) => {
|
|
386
639
|
if (message.sender.role === "assistant") {
|
|
387
640
|
return [
|
|
388
641
|
message.blocks.find((block) => block._tag === "transcript")?.text ?? "",
|
|
@@ -393,12 +646,13 @@ var renderMarkdown = (identities) => (message, index, debug = false) => {
|
|
|
393
646
|
const name = identity?.profile?.displayName ?? message.sender.contact?.target?.fullName ?? message.sender.name ?? message.sender.email ?? message.sender.identityDid;
|
|
394
647
|
const blocks = message.blocks.filter((block) => block._tag === "transcript");
|
|
395
648
|
return [
|
|
649
|
+
// TODO(thure): Use an XML tag with the bits needed here.
|
|
396
650
|
`###### ${name}` + (debug ? ` [${index}]:${message.id}` : ""),
|
|
397
651
|
blocks.map((block) => block.text.trim()).join(" "),
|
|
398
652
|
""
|
|
399
653
|
];
|
|
400
654
|
};
|
|
401
|
-
var
|
|
655
|
+
var TranscriptView = ({ classNames, space, transcript: object, model }) => {
|
|
402
656
|
var _effect = _useSignals();
|
|
403
657
|
try {
|
|
404
658
|
const { themeMode } = useThemeContext();
|
|
@@ -407,27 +661,21 @@ var Transcript = ({ classNames, transcript: object, space, model, attendableId,
|
|
|
407
661
|
extensions: [
|
|
408
662
|
createBasicExtensions({
|
|
409
663
|
readOnly: true,
|
|
410
|
-
lineWrapping: true
|
|
411
|
-
|
|
412
|
-
createMarkdownExtensions({
|
|
413
|
-
themeMode
|
|
664
|
+
lineWrapping: true,
|
|
665
|
+
search: true
|
|
414
666
|
}),
|
|
667
|
+
createMarkdownExtensions(),
|
|
415
668
|
createThemeExtensions({
|
|
416
669
|
themeMode
|
|
417
670
|
}),
|
|
418
671
|
decorateMarkdown(),
|
|
419
|
-
|
|
672
|
+
preview(),
|
|
420
673
|
transcript({
|
|
421
674
|
model,
|
|
422
|
-
started: object?.started ? new Date(object.started) : void 0
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
label: "Scroll to bottom",
|
|
427
|
-
onClick
|
|
428
|
-
}))
|
|
429
|
-
})
|
|
430
|
-
].filter(isNotFalsy)
|
|
675
|
+
started: object?.started ? new Date(object.started) : void 0
|
|
676
|
+
}),
|
|
677
|
+
autoScroll()
|
|
678
|
+
].filter(isTruthy)
|
|
431
679
|
};
|
|
432
680
|
}, [
|
|
433
681
|
space,
|
|
@@ -435,7 +683,7 @@ var Transcript = ({ classNames, transcript: object, space, model, attendableId,
|
|
|
435
683
|
]);
|
|
436
684
|
return /* @__PURE__ */ React.createElement("div", {
|
|
437
685
|
ref: parentRef,
|
|
438
|
-
className: mx("flex grow overflow-hidden",
|
|
686
|
+
className: mx("flex grow overflow-hidden container-max-width", classNames),
|
|
439
687
|
"data-popover-collision-boundary": true
|
|
440
688
|
});
|
|
441
689
|
} finally {
|
|
@@ -443,284 +691,6 @@ var Transcript = ({ classNames, transcript: object, space, model, attendableId,
|
|
|
443
691
|
}
|
|
444
692
|
};
|
|
445
693
|
|
|
446
|
-
// src/hooks/useAudioFile.ts
|
|
447
|
-
import { useEffect, useState } from "react";
|
|
448
|
-
import { scheduleTask } from "@dxos/async";
|
|
449
|
-
import { Context } from "@dxos/context";
|
|
450
|
-
import { log as log2 } from "@dxos/log";
|
|
451
|
-
var __dxlog_file2 = "/__w/dxos/dxos/packages/plugins/plugin-transcription/src/hooks/useAudioFile.ts";
|
|
452
|
-
var useAudioFile = (audioUrl, constraints) => {
|
|
453
|
-
const [{ audio, stream, track }, setStream] = useState({});
|
|
454
|
-
useEffect(() => {
|
|
455
|
-
const ctx = new Context(void 0, {
|
|
456
|
-
F: __dxlog_file2,
|
|
457
|
-
L: 20
|
|
458
|
-
});
|
|
459
|
-
scheduleTask(ctx, async () => {
|
|
460
|
-
const response = await fetch(audioUrl);
|
|
461
|
-
const blob = await response.blob();
|
|
462
|
-
const objectUrl = URL.createObjectURL(blob);
|
|
463
|
-
ctx.onDispose(() => {
|
|
464
|
-
URL.revokeObjectURL(objectUrl);
|
|
465
|
-
});
|
|
466
|
-
const audio2 = new Audio();
|
|
467
|
-
audio2.src = objectUrl;
|
|
468
|
-
await new Promise((resolve, reject) => {
|
|
469
|
-
audio2.addEventListener("error", (err) => {
|
|
470
|
-
log2.error("error", {
|
|
471
|
-
err
|
|
472
|
-
}, {
|
|
473
|
-
F: __dxlog_file2,
|
|
474
|
-
L: 37,
|
|
475
|
-
S: void 0,
|
|
476
|
-
C: (f, a) => f(...a)
|
|
477
|
-
});
|
|
478
|
-
reject(err);
|
|
479
|
-
}, {
|
|
480
|
-
once: true
|
|
481
|
-
});
|
|
482
|
-
audio2.addEventListener("canplay", async () => {
|
|
483
|
-
log2.info("starting...", void 0, {
|
|
484
|
-
F: __dxlog_file2,
|
|
485
|
-
L: 45,
|
|
486
|
-
S: void 0,
|
|
487
|
-
C: (f, a) => f(...a)
|
|
488
|
-
});
|
|
489
|
-
try {
|
|
490
|
-
await audio2.play();
|
|
491
|
-
resolve();
|
|
492
|
-
} catch (playError) {
|
|
493
|
-
log2.error("Play failed", {
|
|
494
|
-
playError
|
|
495
|
-
}, {
|
|
496
|
-
F: __dxlog_file2,
|
|
497
|
-
L: 51,
|
|
498
|
-
S: void 0,
|
|
499
|
-
C: (f, a) => f(...a)
|
|
500
|
-
});
|
|
501
|
-
resolve();
|
|
502
|
-
}
|
|
503
|
-
}, {
|
|
504
|
-
once: true
|
|
505
|
-
});
|
|
506
|
-
audio2.load();
|
|
507
|
-
});
|
|
508
|
-
const audioCtx = new AudioContext();
|
|
509
|
-
if (audioCtx.state === "suspended") {
|
|
510
|
-
await audioCtx.resume();
|
|
511
|
-
}
|
|
512
|
-
const destination = audioCtx.createMediaStreamDestination();
|
|
513
|
-
destination.channelCount = 1;
|
|
514
|
-
const source = audioCtx.createMediaElementSource(audio2);
|
|
515
|
-
source.connect(destination);
|
|
516
|
-
const track2 = destination.stream.getAudioTracks()[0];
|
|
517
|
-
if (constraints) {
|
|
518
|
-
await track2.applyConstraints(constraints).catch((err) => log2.catch(err, void 0, {
|
|
519
|
-
F: __dxlog_file2,
|
|
520
|
-
L: 75,
|
|
521
|
-
S: void 0,
|
|
522
|
-
C: (f, a) => f(...a)
|
|
523
|
-
}));
|
|
524
|
-
}
|
|
525
|
-
setStream({
|
|
526
|
-
audio: audio2,
|
|
527
|
-
stream: destination.stream,
|
|
528
|
-
track: destination.stream.getAudioTracks()[0]
|
|
529
|
-
});
|
|
530
|
-
});
|
|
531
|
-
return () => {
|
|
532
|
-
void ctx.dispose();
|
|
533
|
-
};
|
|
534
|
-
}, [
|
|
535
|
-
audioUrl
|
|
536
|
-
]);
|
|
537
|
-
return {
|
|
538
|
-
audio,
|
|
539
|
-
stream,
|
|
540
|
-
track
|
|
541
|
-
};
|
|
542
|
-
};
|
|
543
|
-
|
|
544
|
-
// src/hooks/useAudioTrack.ts
|
|
545
|
-
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
546
|
-
var useAudioTrack = (active, constraints) => {
|
|
547
|
-
const [track, setTrack] = useState2();
|
|
548
|
-
useEffect2(() => {
|
|
549
|
-
if (!active) {
|
|
550
|
-
track?.stop();
|
|
551
|
-
setTrack(void 0);
|
|
552
|
-
return;
|
|
553
|
-
}
|
|
554
|
-
const initAudio = async () => {
|
|
555
|
-
const audio = new Audio();
|
|
556
|
-
audio.srcObject = await navigator.mediaDevices.getUserMedia({
|
|
557
|
-
audio: constraints ?? true
|
|
558
|
-
});
|
|
559
|
-
const [track2] = audio.srcObject.getAudioTracks();
|
|
560
|
-
if (track2) {
|
|
561
|
-
setTrack(track2);
|
|
562
|
-
}
|
|
563
|
-
};
|
|
564
|
-
if (active) {
|
|
565
|
-
void initAudio();
|
|
566
|
-
}
|
|
567
|
-
}, [
|
|
568
|
-
active
|
|
569
|
-
]);
|
|
570
|
-
return track;
|
|
571
|
-
};
|
|
572
|
-
|
|
573
|
-
// src/hooks/useQueueModelAdapter.ts
|
|
574
|
-
import { useEffect as useEffect3, useMemo, useState as useState3 } from "react";
|
|
575
|
-
var useQueueModelAdapter = (renderer, queue, initialChunks = []) => {
|
|
576
|
-
const model = useMemo(() => new SerializationModel(renderer, initialChunks), [
|
|
577
|
-
queue
|
|
578
|
-
]);
|
|
579
|
-
const [loaded, setLoaded] = useState3(false);
|
|
580
|
-
useEffect3(() => {
|
|
581
|
-
if (!queue) {
|
|
582
|
-
return;
|
|
583
|
-
}
|
|
584
|
-
const update = () => {
|
|
585
|
-
for (const block of queue?.objects ?? []) {
|
|
586
|
-
model.appendChunk(block);
|
|
587
|
-
}
|
|
588
|
-
setLoaded(true);
|
|
589
|
-
};
|
|
590
|
-
let i;
|
|
591
|
-
if (queue.isLoading) {
|
|
592
|
-
i = setInterval(() => {
|
|
593
|
-
if (!queue?.isLoading) {
|
|
594
|
-
clearInterval(i);
|
|
595
|
-
update();
|
|
596
|
-
}
|
|
597
|
-
}, 1e3);
|
|
598
|
-
} else {
|
|
599
|
-
update();
|
|
600
|
-
}
|
|
601
|
-
return () => clearTimeout(i);
|
|
602
|
-
}, [
|
|
603
|
-
model,
|
|
604
|
-
queue
|
|
605
|
-
]);
|
|
606
|
-
useEffect3(() => {
|
|
607
|
-
if (!loaded || !queue || model.chunks.length === queue.objects.length) {
|
|
608
|
-
return;
|
|
609
|
-
}
|
|
610
|
-
const chunk = queue.objects.at(-1);
|
|
611
|
-
if (chunk) {
|
|
612
|
-
model.appendChunk(chunk);
|
|
613
|
-
}
|
|
614
|
-
}, [
|
|
615
|
-
model,
|
|
616
|
-
loaded,
|
|
617
|
-
queue?.objects.length
|
|
618
|
-
]);
|
|
619
|
-
return model;
|
|
620
|
-
};
|
|
621
|
-
|
|
622
|
-
// src/hooks/useTranscriber.ts
|
|
623
|
-
import { useEffect as useEffect4, useMemo as useMemo2 } from "react";
|
|
624
|
-
import { useCapabilities } from "@dxos/app-framework";
|
|
625
|
-
|
|
626
|
-
// src/capabilities/index.ts
|
|
627
|
-
import { lazy } from "@dxos/app-framework";
|
|
628
|
-
var IntentResolver = lazy(() => import("./intent-resolver-3O33MMP5.mjs"));
|
|
629
|
-
var ReactSurface = lazy(() => import("./react-surface-E5D5AE3F.mjs"));
|
|
630
|
-
var Transcriber = lazy(() => import("./transcriber-PXT4QBFY.mjs"));
|
|
631
|
-
|
|
632
|
-
// src/hooks/useTranscriber.ts
|
|
633
|
-
var useTranscriber = ({ audioStreamTrack, recorderConfig, transcriberConfig, onSegments }) => {
|
|
634
|
-
const [getTranscriber] = useCapabilities(TranscriptionCapabilities.Transcriber);
|
|
635
|
-
const transcriber = useMemo2(() => {
|
|
636
|
-
if (!getTranscriber || !audioStreamTrack || !onSegments) {
|
|
637
|
-
return void 0;
|
|
638
|
-
}
|
|
639
|
-
return getTranscriber({
|
|
640
|
-
audioStreamTrack,
|
|
641
|
-
recorderConfig,
|
|
642
|
-
transcriberConfig,
|
|
643
|
-
onSegments
|
|
644
|
-
});
|
|
645
|
-
}, [
|
|
646
|
-
getTranscriber,
|
|
647
|
-
audioStreamTrack,
|
|
648
|
-
recorderConfig,
|
|
649
|
-
transcriberConfig,
|
|
650
|
-
onSegments
|
|
651
|
-
]);
|
|
652
|
-
useEffect4(() => {
|
|
653
|
-
return () => {
|
|
654
|
-
void transcriber?.close();
|
|
655
|
-
};
|
|
656
|
-
}, [
|
|
657
|
-
transcriber
|
|
658
|
-
]);
|
|
659
|
-
return transcriber;
|
|
660
|
-
};
|
|
661
|
-
|
|
662
|
-
// src/hooks/useVoiceInput.ts
|
|
663
|
-
import { useState as useState4, useEffect as useEffect5, useCallback } from "react";
|
|
664
|
-
import { scheduleMicroTask } from "@dxos/async";
|
|
665
|
-
import { Context as Context2 } from "@dxos/context";
|
|
666
|
-
import { log as log3 } from "@dxos/log";
|
|
667
|
-
import { useSoundEffect } from "@dxos/react-ui-sfx";
|
|
668
|
-
var __dxlog_file3 = "/__w/dxos/dxos/packages/plugins/plugin-transcription/src/hooks/useVoiceInput.ts";
|
|
669
|
-
var useVoiceInput = ({ active, onUpdate }) => {
|
|
670
|
-
const soundStart = useSoundEffect("StartRecording");
|
|
671
|
-
const soundStop = useSoundEffect("StopRecording");
|
|
672
|
-
const handleSegments = useCallback(async (segments) => {
|
|
673
|
-
const text = segments.map((str) => str.text.trim().replace(/[^\w\s]/g, "")).join(" ");
|
|
674
|
-
onUpdate(text);
|
|
675
|
-
}, []);
|
|
676
|
-
const [recording, setRecording] = useState4(false);
|
|
677
|
-
const track = useAudioTrack(active);
|
|
678
|
-
const transcriber = useTranscriber({
|
|
679
|
-
audioStreamTrack: track,
|
|
680
|
-
onSegments: handleSegments
|
|
681
|
-
});
|
|
682
|
-
useEffect5(() => {
|
|
683
|
-
const ctx = new Context2(void 0, {
|
|
684
|
-
F: __dxlog_file3,
|
|
685
|
-
L: 43
|
|
686
|
-
});
|
|
687
|
-
scheduleMicroTask(ctx, async () => {
|
|
688
|
-
if (active && transcriber) {
|
|
689
|
-
await transcriber.open();
|
|
690
|
-
log3.info("starting...", void 0, {
|
|
691
|
-
F: __dxlog_file3,
|
|
692
|
-
L: 47,
|
|
693
|
-
S: void 0,
|
|
694
|
-
C: (f, a) => f(...a)
|
|
695
|
-
});
|
|
696
|
-
setRecording(true);
|
|
697
|
-
void soundStart.play();
|
|
698
|
-
transcriber.startChunksRecording();
|
|
699
|
-
} else if (!active && transcriber?.isOpen) {
|
|
700
|
-
transcriber?.stopChunksRecording();
|
|
701
|
-
await transcriber?.close();
|
|
702
|
-
log3.info("stopped", void 0, {
|
|
703
|
-
F: __dxlog_file3,
|
|
704
|
-
L: 54,
|
|
705
|
-
S: void 0,
|
|
706
|
-
C: (f, a) => f(...a)
|
|
707
|
-
});
|
|
708
|
-
setRecording(false);
|
|
709
|
-
void soundStop.play();
|
|
710
|
-
}
|
|
711
|
-
});
|
|
712
|
-
return () => {
|
|
713
|
-
void ctx.dispose();
|
|
714
|
-
};
|
|
715
|
-
}, [
|
|
716
|
-
active,
|
|
717
|
-
transcriber
|
|
718
|
-
]);
|
|
719
|
-
return {
|
|
720
|
-
recording
|
|
721
|
-
};
|
|
722
|
-
};
|
|
723
|
-
|
|
724
694
|
// src/components/TranscriptContainer.tsx
|
|
725
695
|
var TranscriptionContainer = ({ transcript: transcript2 }) => {
|
|
726
696
|
var _effect = _useSignals2();
|
|
@@ -731,10 +701,8 @@ var TranscriptionContainer = ({ transcript: transcript2 }) => {
|
|
|
731
701
|
const queue = useQueue(transcript2.queue.dxn, {
|
|
732
702
|
pollInterval: 1e3
|
|
733
703
|
});
|
|
734
|
-
const model = useQueueModelAdapter(
|
|
735
|
-
return /* @__PURE__ */ React2.createElement(StackItem.Content, {
|
|
736
|
-
classNames: "container-max-width pli-2"
|
|
737
|
-
}, /* @__PURE__ */ React2.createElement(Transcript, {
|
|
704
|
+
const model = useQueueModelAdapter(renderByline(members), queue);
|
|
705
|
+
return /* @__PURE__ */ React2.createElement(StackItem.Content, null, /* @__PURE__ */ React2.createElement(TranscriptView, {
|
|
738
706
|
attendableId,
|
|
739
707
|
space,
|
|
740
708
|
model,
|
|
@@ -747,8 +715,8 @@ var TranscriptionContainer = ({ transcript: transcript2 }) => {
|
|
|
747
715
|
var TranscriptContainer_default = TranscriptionContainer;
|
|
748
716
|
|
|
749
717
|
export {
|
|
750
|
-
|
|
751
|
-
|
|
718
|
+
renderByline,
|
|
719
|
+
TranscriptView,
|
|
752
720
|
useAudioFile,
|
|
753
721
|
useAudioTrack,
|
|
754
722
|
useQueueModelAdapter,
|
|
@@ -756,8 +724,9 @@ export {
|
|
|
756
724
|
useVoiceInput,
|
|
757
725
|
TranscriptionContainer,
|
|
758
726
|
TranscriptContainer_default,
|
|
727
|
+
BlueprintDefinition,
|
|
759
728
|
IntentResolver,
|
|
760
729
|
ReactSurface,
|
|
761
730
|
Transcriber
|
|
762
731
|
};
|
|
763
|
-
//# sourceMappingURL=chunk-
|
|
732
|
+
//# sourceMappingURL=chunk-7DR6HZEF.mjs.map
|