@dxos/plugin-transcription 0.8.3 → 0.8.4-main.1da679c
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-W6CHJPIB.mjs +11 -0
- package/dist/lib/browser/blueprint-definition-C62MH2FL.mjs +142 -0
- package/dist/lib/browser/blueprint-definition-C62MH2FL.mjs.map +7 -0
- package/dist/lib/browser/{chunk-GOF7MJNV.mjs → chunk-3X7HP44M.mjs} +9 -2
- package/dist/lib/browser/{chunk-GOF7MJNV.mjs.map → chunk-3X7HP44M.mjs.map} +1 -1
- package/dist/lib/browser/{chunk-IQ5ZRMHZ.mjs → chunk-BA64VLLR.mjs} +93 -102
- package/dist/lib/browser/chunk-BA64VLLR.mjs.map +7 -0
- package/dist/lib/browser/{chunk-53AXUEIQ.mjs → chunk-DHMLTHPB.mjs} +424 -442
- package/dist/lib/browser/chunk-DHMLTHPB.mjs.map +7 -0
- package/dist/lib/browser/chunk-HXVGV7T6.mjs +63 -0
- package/dist/lib/browser/chunk-HXVGV7T6.mjs.map +7 -0
- package/dist/lib/browser/{chunk-W2KNYJD6.mjs → chunk-TNEQFHIU.mjs} +3 -3
- package/dist/lib/browser/{chunk-W2KNYJD6.mjs.map → chunk-TNEQFHIU.mjs.map} +1 -1
- package/dist/lib/browser/{chunk-UDCCT32F.mjs → chunk-ZNCGBPXR.mjs} +3 -3
- package/dist/lib/browser/index.mjs +27 -21
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/intent-resolver-LKRGWUX2.mjs +25 -0
- package/dist/lib/browser/intent-resolver-LKRGWUX2.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-surface-HMJS5FSS.mjs → react-surface-2AGVHCYU.mjs} +11 -11
- package/dist/lib/browser/react-surface-2AGVHCYU.mjs.map +7 -0
- package/dist/lib/browser/{transcriber-OYPLZFG5.mjs → transcriber-L3NQP2OM.mjs} +8 -8
- package/dist/lib/browser/transcriber-L3NQP2OM.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +6 -8
- package/dist/lib/node-esm/{TranscriptContainer-G75LDEO5.mjs → TranscriptContainer-LJLH47VF.mjs} +4 -4
- package/dist/lib/node-esm/blueprint-definition-PH3DDDHR.mjs +143 -0
- package/dist/lib/node-esm/blueprint-definition-PH3DDDHR.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-MFJPEIVB.mjs → chunk-3QAIZGMW.mjs} +3 -3
- package/dist/lib/node-esm/{chunk-MFJPEIVB.mjs.map → chunk-3QAIZGMW.mjs.map} +1 -1
- package/dist/lib/node-esm/{chunk-PRL64SRU.mjs → chunk-J5GQ3KGX.mjs} +93 -102
- package/dist/lib/node-esm/chunk-J5GQ3KGX.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-56QHOX4A.mjs → chunk-JQARMZNW.mjs} +424 -442
- package/dist/lib/node-esm/chunk-JQARMZNW.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-MFJO7EKD.mjs → chunk-JQBXD6KX.mjs} +3 -3
- package/dist/lib/node-esm/{chunk-TXMDLLBR.mjs → chunk-QARUDLHN.mjs} +8 -2
- package/dist/lib/node-esm/{chunk-TXMDLLBR.mjs.map → chunk-QARUDLHN.mjs.map} +1 -1
- package/dist/lib/node-esm/chunk-W72HVQMD.mjs +64 -0
- package/dist/lib/node-esm/chunk-W72HVQMD.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +27 -21
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/intent-resolver-AGLWBOCO.mjs +26 -0
- package/dist/lib/node-esm/intent-resolver-AGLWBOCO.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{react-surface-JGQSYGRR.mjs → react-surface-HPQQ3WIF.mjs} +11 -11
- package/dist/lib/node-esm/react-surface-HPQQ3WIF.mjs.map +7 -0
- package/dist/lib/node-esm/{transcriber-TVG2MBBN.mjs → transcriber-KJX4U74D.mjs} +8 -8
- package/dist/lib/node-esm/transcriber-KJX4U74D.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +6 -8
- 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 +3 -3
- 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 +30 -15
- package/dist/types/src/components/Transcript/Transcript.stories.d.ts.map +1 -1
- package/dist/types/src/components/Transcript/deprecated/OldTranscript.d.ts +2 -2
- 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 +6 -5
- package/dist/types/src/components/TranscriptContainer.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +1 -4
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/stories/FileTranscription.stories.d.ts +5 -3
- package/dist/types/src/components/stories/FileTranscription.stories.d.ts.map +1 -1
- package/dist/types/src/components/stories/KeyWordRecognition.stories.d.ts +10 -5
- package/dist/types/src/components/stories/KeyWordRecognition.stories.d.ts.map +1 -1
- package/dist/types/src/components/stories/MicrophoneTranscription.stories.d.ts +7 -5
- package/dist/types/src/components/stories/MicrophoneTranscription.stories.d.ts.map +1 -1
- package/dist/types/src/components/stories/TranscriptionStory.d.ts +1 -0
- 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/useTranscriber.d.ts +1 -1
- package/dist/types/src/hooks/useVoiceInput.d.ts.map +1 -1
- package/dist/types/src/segments-normalization/normalization.d.ts +375 -243
- package/dist/types/src/segments-normalization/normalization.d.ts.map +1 -1
- package/dist/types/src/testing/testing.d.ts +1 -1
- package/dist/types/src/testing/testing.d.ts.map +1 -1
- package/dist/types/src/transcriber/index.d.ts +1 -1
- package/dist/types/src/transcriber/index.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 +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/translations.d.ts +11 -11
- package/dist/types/src/translations.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 +61 -59
- package/src/TranscriptionPlugin.tsx +13 -8
- package/src/capabilities/blueprint-definition.ts +31 -0
- package/src/capabilities/capabilities.ts +5 -5
- 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 +26 -24
- package/src/components/Transcript/Transcript.tsx +20 -27
- package/src/components/Transcript/deprecated/OldTranscript.tsx +4 -4
- package/src/components/Transcript/transcript-extension.ts +4 -41
- package/src/components/TranscriptContainer.tsx +13 -7
- package/src/components/stories/FileTranscription.stories.tsx +53 -39
- package/src/components/stories/KeyWordRecognition.stories.tsx +12 -6
- package/src/components/stories/MicrophoneTranscription.stories.tsx +41 -36
- package/src/components/stories/TranscriptionStory.tsx +9 -5
- package/src/functions/index.ts +6 -0
- package/src/functions/open.ts +37 -0
- package/src/functions/summarize.ts +97 -0
- package/src/hooks/useAudioFile.ts +1 -10
- package/src/hooks/useTranscriber.ts +5 -5
- package/src/hooks/useVoiceInput.ts +3 -2
- package/src/model/model.test.ts +9 -9
- package/src/segments-normalization/message-normalizer.ts +1 -1
- package/src/segments-normalization/normalization.test.ts +19 -21
- package/src/segments-normalization/normalization.ts +54 -44
- package/src/testing/testing.ts +13 -13
- package/src/transcriber/index.ts +1 -1
- package/src/transcriber/media-stream-recorder.ts +1 -1
- package/src/transcriber/transcriber.browser.test.ts +4 -3
- package/src/transcriber/transcriber.ts +5 -7
- package/src/transcriber/transcription-manager.ts +18 -39
- package/src/translations.ts +6 -4
- package/src/types/{schema.ts → Transcript.ts} +11 -8
- 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-H3AZQ4CQ.mjs +0 -11
- package/dist/lib/browser/chunk-53AXUEIQ.mjs.map +0 -7
- package/dist/lib/browser/chunk-IQ5ZRMHZ.mjs.map +0 -7
- package/dist/lib/browser/chunk-OSISJM2F.mjs +0 -55
- package/dist/lib/browser/chunk-OSISJM2F.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-BGADCHVM.mjs +0 -30
- package/dist/lib/browser/intent-resolver-BGADCHVM.mjs.map +0 -7
- package/dist/lib/browser/react-surface-HMJS5FSS.mjs.map +0 -7
- package/dist/lib/browser/transcriber-OYPLZFG5.mjs.map +0 -7
- package/dist/lib/node/TranscriptContainer-KIG3GMAB.cjs +0 -32
- package/dist/lib/node/TranscriptContainer-KIG3GMAB.cjs.map +0 -7
- package/dist/lib/node/chunk-3PYT3BDM.cjs +0 -40
- package/dist/lib/node/chunk-3PYT3BDM.cjs.map +0 -7
- package/dist/lib/node/chunk-6LW5RA3K.cjs +0 -75
- package/dist/lib/node/chunk-6LW5RA3K.cjs.map +0 -7
- package/dist/lib/node/chunk-AFUZI63A.cjs +0 -42
- package/dist/lib/node/chunk-AFUZI63A.cjs.map +0 -7
- package/dist/lib/node/chunk-CVUN3UO7.cjs +0 -778
- package/dist/lib/node/chunk-CVUN3UO7.cjs.map +0 -7
- package/dist/lib/node/chunk-FKDJNJ57.cjs +0 -35
- package/dist/lib/node/chunk-FKDJNJ57.cjs.map +0 -7
- package/dist/lib/node/chunk-ZFAUMZXE.cjs +0 -518
- package/dist/lib/node/chunk-ZFAUMZXE.cjs.map +0 -7
- package/dist/lib/node/index.cjs +0 -133
- package/dist/lib/node/index.cjs.map +0 -7
- package/dist/lib/node/intent-resolver-LL3TTI4H.cjs +0 -45
- package/dist/lib/node/intent-resolver-LL3TTI4H.cjs.map +0 -7
- package/dist/lib/node/meta.json +0 -1
- package/dist/lib/node/react-surface-N25TBBG4.cjs +0 -56
- package/dist/lib/node/react-surface-N25TBBG4.cjs.map +0 -7
- package/dist/lib/node/transcriber-6J4FVFSZ.cjs +0 -68
- package/dist/lib/node/transcriber-6J4FVFSZ.cjs.map +0 -7
- package/dist/lib/node/types/index.cjs +0 -36
- package/dist/lib/node/types/index.cjs.map +0 -7
- package/dist/lib/node-esm/chunk-56QHOX4A.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-FH75X4JC.mjs +0 -56
- package/dist/lib/node-esm/chunk-FH75X4JC.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-PRL64SRU.mjs.map +0 -7
- package/dist/lib/node-esm/intent-resolver-5LVCYSJS.mjs +0 -31
- package/dist/lib/node-esm/intent-resolver-5LVCYSJS.mjs.map +0 -7
- package/dist/lib/node-esm/react-surface-JGQSYGRR.mjs.map +0 -7
- package/dist/lib/node-esm/transcriber-TVG2MBBN.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-H3AZQ4CQ.mjs.map → TranscriptContainer-W6CHJPIB.mjs.map} +0 -0
- /package/dist/lib/browser/{chunk-UDCCT32F.mjs.map → chunk-ZNCGBPXR.mjs.map} +0 -0
- /package/dist/lib/node-esm/{TranscriptContainer-G75LDEO5.mjs.map → TranscriptContainer-LJLH47VF.mjs.map} +0 -0
- /package/dist/lib/node-esm/{chunk-MFJO7EKD.mjs.map → chunk-JQBXD6KX.mjs.map} +0 -0
|
@@ -8,7 +8,6 @@ import { format } from 'date-fns/format';
|
|
|
8
8
|
import { intervalToDuration } from 'date-fns/intervalToDuration';
|
|
9
9
|
|
|
10
10
|
import { type CleanupFn, addEventListener, combine } from '@dxos/async';
|
|
11
|
-
import { type RenderCallback } from '@dxos/react-ui-editor';
|
|
12
11
|
import { type DataType } from '@dxos/schema';
|
|
13
12
|
|
|
14
13
|
import { DocumentAdapter, type SerializationModel } from '../../model';
|
|
@@ -19,13 +18,12 @@ import { DocumentAdapter, type SerializationModel } from '../../model';
|
|
|
19
18
|
export type TranscriptOptions = {
|
|
20
19
|
model: SerializationModel<DataType.Message>;
|
|
21
20
|
started?: Date;
|
|
22
|
-
renderButton?: RenderCallback<{ onClick: () => void }>;
|
|
23
21
|
};
|
|
24
22
|
|
|
25
23
|
/**
|
|
26
24
|
* Scrolling transcript with timestamps.
|
|
27
25
|
*/
|
|
28
|
-
export const transcript = ({ model, started
|
|
26
|
+
export const transcript = ({ model, started }: TranscriptOptions): Extension => {
|
|
29
27
|
return [
|
|
30
28
|
// Show timestamps in the gutter.
|
|
31
29
|
gutter({
|
|
@@ -38,7 +36,7 @@ export const transcript = ({ model, started, renderButton }: TranscriptOptions):
|
|
|
38
36
|
let line = view.state.doc.lineAt(from);
|
|
39
37
|
while (line.from <= to) {
|
|
40
38
|
const block = model.getChunkAtLine(line.number)?.blocks[0];
|
|
41
|
-
const timestamp = block?.
|
|
39
|
+
const timestamp = block?._tag === 'transcript' && block.started;
|
|
42
40
|
if (timestamp) {
|
|
43
41
|
builder.add(line.from, line.from, new TimestampMarker(line.number, new Date(timestamp), start));
|
|
44
42
|
}
|
|
@@ -90,22 +88,6 @@ export const transcript = ({ model, started, renderButton }: TranscriptOptions):
|
|
|
90
88
|
});
|
|
91
89
|
};
|
|
92
90
|
|
|
93
|
-
// Scroll button.
|
|
94
|
-
if (renderButton) {
|
|
95
|
-
this._controls = document.createElement('div');
|
|
96
|
-
this._controls.classList.add('cm-controls', 'transition-opacity', 'duration-300', 'opacity-0');
|
|
97
|
-
view.dom.appendChild(this._controls);
|
|
98
|
-
renderButton(
|
|
99
|
-
this._controls,
|
|
100
|
-
{
|
|
101
|
-
onClick: () => {
|
|
102
|
-
scrollToBottom(false);
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
view,
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
91
|
// Event listeners.
|
|
110
92
|
this._cleanup = combine(
|
|
111
93
|
addEventListener(view.scrollDOM, 'scroll', () => {
|
|
@@ -131,7 +113,7 @@ export const transcript = ({ model, started, renderButton }: TranscriptOptions):
|
|
|
131
113
|
);
|
|
132
114
|
}
|
|
133
115
|
|
|
134
|
-
update(
|
|
116
|
+
update(_update: ViewUpdate) {
|
|
135
117
|
// Initial sync.
|
|
136
118
|
if (!this._initialized) {
|
|
137
119
|
this._initialized = true;
|
|
@@ -149,25 +131,6 @@ export const transcript = ({ model, started, renderButton }: TranscriptOptions):
|
|
|
149
131
|
),
|
|
150
132
|
|
|
151
133
|
EditorView.theme({
|
|
152
|
-
'.cm-scroller': {
|
|
153
|
-
overflowY: 'scroll',
|
|
154
|
-
},
|
|
155
|
-
'.cm-hide-scrollbar': {
|
|
156
|
-
scrollbarWidth: 'none',
|
|
157
|
-
'-ms-overflow-style': 'none',
|
|
158
|
-
},
|
|
159
|
-
'.cm-hide-scrollbar::-webkit-scrollbar': {
|
|
160
|
-
display: 'none',
|
|
161
|
-
},
|
|
162
|
-
'.cm-controls': {
|
|
163
|
-
position: 'absolute',
|
|
164
|
-
bottom: '0.5rem',
|
|
165
|
-
right: '0.5rem',
|
|
166
|
-
zIndex: 1000,
|
|
167
|
-
},
|
|
168
|
-
'.cm-line': {
|
|
169
|
-
paddingRight: '1rem',
|
|
170
|
-
},
|
|
171
134
|
'.cm-timestamp-gutter': {
|
|
172
135
|
width: '6rem',
|
|
173
136
|
paddingRight: '1rem',
|
|
@@ -218,7 +181,7 @@ const getStartTime = (started?: Date, message?: DataType.Message): Date | undefi
|
|
|
218
181
|
return started;
|
|
219
182
|
}
|
|
220
183
|
|
|
221
|
-
if (message?.blocks[0]?.
|
|
184
|
+
if (message?.blocks[0]?._tag === 'transcript' && message.blocks[0].started) {
|
|
222
185
|
return new Date(message.blocks[0].started);
|
|
223
186
|
}
|
|
224
187
|
|
|
@@ -2,27 +2,33 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import React
|
|
5
|
+
import React from 'react';
|
|
6
6
|
|
|
7
7
|
import { fullyQualifiedId, getSpace } from '@dxos/client/echo';
|
|
8
8
|
import { useMembers, useQueue } from '@dxos/react-client/echo';
|
|
9
9
|
import { StackItem } from '@dxos/react-ui-stack';
|
|
10
10
|
import { type DataType } from '@dxos/schema';
|
|
11
11
|
|
|
12
|
-
import { Transcript, renderMarkdown } from './Transcript';
|
|
13
12
|
import { useQueueModelAdapter } from '../hooks';
|
|
14
|
-
import { type
|
|
13
|
+
import { type Transcript } from '../types';
|
|
15
14
|
|
|
16
|
-
|
|
15
|
+
import { TranscriptView, renderByline } from './Transcript';
|
|
16
|
+
|
|
17
|
+
export type TranscriptionContainerProps = {
|
|
18
|
+
role: string;
|
|
19
|
+
transcript: Transcript.Transcript;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const TranscriptionContainer = ({ transcript }: TranscriptionContainerProps) => {
|
|
17
23
|
const attendableId = fullyQualifiedId(transcript);
|
|
18
24
|
const space = getSpace(transcript);
|
|
19
25
|
const members = useMembers(space?.key).map((member) => member.identity);
|
|
20
26
|
const queue = useQueue<DataType.Message>(transcript.queue.dxn, { pollInterval: 1_000 });
|
|
21
|
-
const model = useQueueModelAdapter(
|
|
27
|
+
const model = useQueueModelAdapter(renderByline(members), queue);
|
|
22
28
|
|
|
23
29
|
return (
|
|
24
|
-
<StackItem.Content
|
|
25
|
-
<
|
|
30
|
+
<StackItem.Content>
|
|
31
|
+
<TranscriptView attendableId={attendableId} space={space} model={model} transcript={transcript} />
|
|
26
32
|
</StackItem.Content>
|
|
27
33
|
);
|
|
28
34
|
};
|
|
@@ -4,11 +4,9 @@
|
|
|
4
4
|
|
|
5
5
|
import '@dxos-theme';
|
|
6
6
|
|
|
7
|
-
import { type Meta, type StoryObj } from '@storybook/react';
|
|
7
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
8
8
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
9
9
|
|
|
10
|
-
import { EdgeAiServiceClient } from '@dxos/ai';
|
|
11
|
-
import { AI_SERVICE_ENDPOINT } from '@dxos/ai/testing';
|
|
12
10
|
import { Events, IntentPlugin, SettingsPlugin } from '@dxos/app-framework';
|
|
13
11
|
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
14
12
|
import { scheduleTask } from '@dxos/async';
|
|
@@ -25,17 +23,18 @@ import { StorybookLayoutPlugin } from '@dxos/plugin-storybook-layout';
|
|
|
25
23
|
import { ThemePlugin } from '@dxos/plugin-theme';
|
|
26
24
|
import { defaultTx } from '@dxos/react-ui-theme';
|
|
27
25
|
import { DataType } from '@dxos/schema';
|
|
28
|
-
import {
|
|
26
|
+
import { Testing, seedTestData } from '@dxos/schema/testing';
|
|
29
27
|
import { withLayout, withTheme } from '@dxos/storybook-utils';
|
|
30
28
|
|
|
31
|
-
import { TranscriptionStory } from './TranscriptionStory';
|
|
32
|
-
import { useIsSpeaking } from './useIsSpeaking';
|
|
33
|
-
import { TranscriptionPlugin } from '../../TranscriptionPlugin';
|
|
34
29
|
import { useAudioFile, useQueueModelAdapter, useTranscriber } from '../../hooks';
|
|
35
|
-
import {
|
|
30
|
+
import { MessageNormalizer, getActorId } from '../../segments-normalization';
|
|
36
31
|
import { TestItem } from '../../testing';
|
|
37
32
|
import { type MediaStreamRecorderParams, type TranscriberParams } from '../../transcriber';
|
|
38
|
-
import {
|
|
33
|
+
import { TranscriptionPlugin } from '../../TranscriptionPlugin';
|
|
34
|
+
import { renderByline } from '../Transcript';
|
|
35
|
+
|
|
36
|
+
import { TranscriptionStory } from './TranscriptionStory';
|
|
37
|
+
import { useIsSpeaking } from './useIsSpeaking';
|
|
39
38
|
|
|
40
39
|
const AudioFile = ({
|
|
41
40
|
detectSpeaking,
|
|
@@ -69,7 +68,6 @@ const AudioFile = ({
|
|
|
69
68
|
|
|
70
69
|
useEffect(() => {
|
|
71
70
|
if (!audio) {
|
|
72
|
-
log.warn('no audio');
|
|
73
71
|
return;
|
|
74
72
|
}
|
|
75
73
|
|
|
@@ -85,11 +83,16 @@ const AudioFile = ({
|
|
|
85
83
|
const queueDxn = useMemo(() => createQueueDXN(), []);
|
|
86
84
|
const queue = useMemo(() => new MemoryQueue<DataType.Message>(queueDxn), [queueDxn]);
|
|
87
85
|
|
|
88
|
-
const model = useQueueModelAdapter(
|
|
86
|
+
const model = useQueueModelAdapter(renderByline([]), queue);
|
|
89
87
|
const handleSegments = useCallback<TranscriberParams['onSegments']>(
|
|
90
88
|
async (blocks) => {
|
|
91
|
-
|
|
92
|
-
|
|
89
|
+
void queue?.append([
|
|
90
|
+
Obj.make(DataType.Message, {
|
|
91
|
+
created: new Date().toISOString(),
|
|
92
|
+
sender: actor,
|
|
93
|
+
blocks,
|
|
94
|
+
}),
|
|
95
|
+
]);
|
|
93
96
|
},
|
|
94
97
|
[queue],
|
|
95
98
|
);
|
|
@@ -108,14 +111,14 @@ const AudioFile = ({
|
|
|
108
111
|
}
|
|
109
112
|
const executor = new FunctionExecutor(
|
|
110
113
|
new ServiceContainer().setServices({
|
|
111
|
-
ai: {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
},
|
|
114
|
+
// ai: {
|
|
115
|
+
// client: new Edge AiServiceClient({
|
|
116
|
+
// endpoint: AI_SERVICE_ENDPOINT.REMOTE,
|
|
117
|
+
// defaultGenerationOptions: {
|
|
118
|
+
// model: '@anthropic/claude-3-5-sonnet-20241022',
|
|
119
|
+
// },
|
|
120
|
+
// }),
|
|
121
|
+
// },
|
|
119
122
|
}),
|
|
120
123
|
);
|
|
121
124
|
|
|
@@ -143,10 +146,10 @@ const AudioFile = ({
|
|
|
143
146
|
}, [normalizer]);
|
|
144
147
|
|
|
145
148
|
const manageChunkRecording = () => {
|
|
146
|
-
if (running && isSpeaking) {
|
|
149
|
+
if (running && isSpeaking && transcriber) {
|
|
147
150
|
log.info('starting transcription');
|
|
148
151
|
transcriber?.startChunksRecording();
|
|
149
|
-
} else if (!isSpeaking || !running) {
|
|
152
|
+
} else if ((!isSpeaking || !running) && transcriber) {
|
|
150
153
|
log.info('stopping transcription');
|
|
151
154
|
transcriber?.stopChunksRecording();
|
|
152
155
|
}
|
|
@@ -172,10 +175,18 @@ const AudioFile = ({
|
|
|
172
175
|
manageChunkRecording();
|
|
173
176
|
}, [isSpeaking, stream]);
|
|
174
177
|
|
|
175
|
-
return
|
|
178
|
+
return (
|
|
179
|
+
<TranscriptionStory
|
|
180
|
+
disabled={!stream}
|
|
181
|
+
model={model}
|
|
182
|
+
running={running}
|
|
183
|
+
onRunningChange={setRunning}
|
|
184
|
+
audioRef={ref}
|
|
185
|
+
/>
|
|
186
|
+
);
|
|
176
187
|
};
|
|
177
188
|
|
|
178
|
-
const meta
|
|
189
|
+
const meta = {
|
|
179
190
|
title: 'plugins/plugin-transcription/FileTranscription',
|
|
180
191
|
decorators: [
|
|
181
192
|
withPluginManager({
|
|
@@ -184,7 +195,7 @@ const meta: Meta<typeof AudioFile> = {
|
|
|
184
195
|
StorybookLayoutPlugin(),
|
|
185
196
|
ClientPlugin({
|
|
186
197
|
types: [TestItem, DataType.Person, DataType.Organization, Testing.DocumentType],
|
|
187
|
-
onClientInitialized: async (
|
|
198
|
+
onClientInitialized: async ({ client }) => {
|
|
188
199
|
await client.halo.createIdentity();
|
|
189
200
|
await client.spaces.waitUntilReady();
|
|
190
201
|
await client.spaces.default.waitUntilReady();
|
|
@@ -202,10 +213,12 @@ const meta: Meta<typeof AudioFile> = {
|
|
|
202
213
|
withTheme,
|
|
203
214
|
withLayout({ fullscreen: true, classNames: 'justify-center' }),
|
|
204
215
|
],
|
|
205
|
-
};
|
|
216
|
+
} satisfies Meta;
|
|
206
217
|
|
|
207
218
|
export default meta;
|
|
208
219
|
|
|
220
|
+
type Story = StoryObj<typeof meta>;
|
|
221
|
+
|
|
209
222
|
const TRANSCRIBER_CONFIG = {
|
|
210
223
|
transcribeAfterChunksAmount: 100,
|
|
211
224
|
prefixBufferChunksAmount: 50,
|
|
@@ -228,15 +241,16 @@ export const Default: StoryObj<typeof AudioFile> = {
|
|
|
228
241
|
},
|
|
229
242
|
};
|
|
230
243
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
}
|
|
244
|
+
// TODO(mykola): Fix sentence normalization.
|
|
245
|
+
// export const WithSentenceNormalization: StoryObj<typeof AudioFile> = {
|
|
246
|
+
// render: AudioFile,
|
|
247
|
+
// args: {
|
|
248
|
+
// detectSpeaking: true,
|
|
249
|
+
// normalizeSentences: true,
|
|
250
|
+
// // https://learnenglish.britishcouncil.org/general-english/audio-zone/living-london
|
|
251
|
+
// audioUrl: 'https://dxos.network/audio-london.m4a',
|
|
252
|
+
// // textUrl: 'https://dxos.network/audio-london.txt',
|
|
253
|
+
// transcriberConfig: TRANSCRIBER_CONFIG,
|
|
254
|
+
// recorderConfig: RECORDER_CONFIG,
|
|
255
|
+
// },
|
|
256
|
+
// };
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import '@dxos-theme';
|
|
6
6
|
|
|
7
|
-
import { type
|
|
7
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
8
8
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
9
9
|
|
|
10
10
|
import { log } from '@dxos/log';
|
|
@@ -17,7 +17,11 @@ type Word = {
|
|
|
17
17
|
matched: boolean;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
type StoryProps = {
|
|
21
|
+
keywords: string[];
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const DefaultStory = ({ keywords }: StoryProps) => {
|
|
21
25
|
const [running, setRunning] = useState(false);
|
|
22
26
|
const [matchingWords, setMatchingWords] = useState<Word[]>(keywords.map((word) => ({ text: word, matched: false })));
|
|
23
27
|
|
|
@@ -113,15 +117,17 @@ const SpeechRecognition = ({ keywords }: { keywords: string[] }) => {
|
|
|
113
117
|
);
|
|
114
118
|
};
|
|
115
119
|
|
|
116
|
-
const meta
|
|
120
|
+
const meta = {
|
|
117
121
|
title: 'plugins/plugin-transcription/KeyWordDetection',
|
|
122
|
+
render: DefaultStory,
|
|
118
123
|
decorators: [withTheme, withLayout({ fullscreen: true, classNames: 'justify-center' })],
|
|
119
|
-
}
|
|
124
|
+
} satisfies Meta<typeof DefaultStory>;
|
|
120
125
|
|
|
121
126
|
export default meta;
|
|
122
127
|
|
|
123
|
-
|
|
124
|
-
|
|
128
|
+
type Story = StoryObj<typeof meta>;
|
|
129
|
+
|
|
130
|
+
export const SpeechRecognitionAPI: Story = {
|
|
125
131
|
args: {
|
|
126
132
|
keywords: ['kai', 'computer', 'hello'],
|
|
127
133
|
},
|
|
@@ -4,20 +4,18 @@
|
|
|
4
4
|
|
|
5
5
|
import '@dxos-theme';
|
|
6
6
|
|
|
7
|
-
import { type Meta, type StoryObj } from '@storybook/react';
|
|
7
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
8
8
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
9
9
|
|
|
10
|
-
import { EdgeAiServiceClient } from '@dxos/ai';
|
|
11
|
-
import { AI_SERVICE_ENDPOINT } from '@dxos/ai/testing';
|
|
12
10
|
import { Events, IntentPlugin, SettingsPlugin } from '@dxos/app-framework';
|
|
13
11
|
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
14
12
|
import {
|
|
15
|
-
extractionAnthropicFn,
|
|
16
13
|
type ExtractionFunction,
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
extractionAnthropicFunction,
|
|
15
|
+
extractionNerFunction,
|
|
19
16
|
getNer,
|
|
20
|
-
|
|
17
|
+
processTranscriptMessage,
|
|
18
|
+
} from '@dxos/assistant/extraction';
|
|
21
19
|
import { Filter, Obj, type Type } from '@dxos/echo';
|
|
22
20
|
import { MemoryQueue } from '@dxos/echo-db';
|
|
23
21
|
import { createQueueDXN } from '@dxos/echo-schema';
|
|
@@ -32,16 +30,17 @@ import { ThemePlugin } from '@dxos/plugin-theme';
|
|
|
32
30
|
import { IndexKind, useSpace } from '@dxos/react-client/echo';
|
|
33
31
|
import { defaultTx } from '@dxos/react-ui-theme';
|
|
34
32
|
import { DataType } from '@dxos/schema';
|
|
35
|
-
import {
|
|
33
|
+
import { Testing, seedTestData } from '@dxos/schema/testing';
|
|
36
34
|
import { withLayout, withTheme } from '@dxos/storybook-utils';
|
|
37
35
|
|
|
38
|
-
import { TranscriptionStory } from './TranscriptionStory';
|
|
39
|
-
import { useIsSpeaking } from './useIsSpeaking';
|
|
40
|
-
import { TranscriptionPlugin } from '../../TranscriptionPlugin';
|
|
41
36
|
import { useAudioTrack, useQueueModelAdapter, useTranscriber } from '../../hooks';
|
|
42
37
|
import { TestItem } from '../../testing';
|
|
43
38
|
import { type MediaStreamRecorderParams, type TranscriberParams } from '../../transcriber';
|
|
44
|
-
import {
|
|
39
|
+
import { TranscriptionPlugin } from '../../TranscriptionPlugin';
|
|
40
|
+
import { renderByline } from '../Transcript';
|
|
41
|
+
|
|
42
|
+
import { TranscriptionStory } from './TranscriptionStory';
|
|
43
|
+
import { useIsSpeaking } from './useIsSpeaking';
|
|
45
44
|
|
|
46
45
|
const TRANSCRIBER_CONFIG = {
|
|
47
46
|
transcribeAfterChunksAmount: 50,
|
|
@@ -79,7 +78,7 @@ const DefaultStory = ({
|
|
|
79
78
|
// TODO(dmaretskyi): Use space.queues.create() instead.
|
|
80
79
|
const queueDxn = useMemo(() => createQueueDXN(), []);
|
|
81
80
|
const queue = useMemo(() => new MemoryQueue<DataType.Message>(queueDxn), [queueDxn]);
|
|
82
|
-
const model = useQueueModelAdapter(
|
|
81
|
+
const model = useQueueModelAdapter(renderByline([]), queue);
|
|
83
82
|
const space = useSpace();
|
|
84
83
|
|
|
85
84
|
useEffect(() => {
|
|
@@ -102,9 +101,9 @@ const DefaultStory = ({
|
|
|
102
101
|
if (entityExtraction === 'ner') {
|
|
103
102
|
// Init model loading. Takes time.
|
|
104
103
|
void getNer();
|
|
105
|
-
extractionFunction =
|
|
104
|
+
extractionFunction = extractionNerFunction;
|
|
106
105
|
} else if (entityExtraction === 'llm') {
|
|
107
|
-
extractionFunction =
|
|
106
|
+
extractionFunction = extractionAnthropicFunction;
|
|
108
107
|
objects = space.db
|
|
109
108
|
.query(
|
|
110
109
|
Filter.or(
|
|
@@ -117,11 +116,15 @@ const DefaultStory = ({
|
|
|
117
116
|
.then((result) => result.objects);
|
|
118
117
|
}
|
|
119
118
|
if (entityExtraction !== 'none') {
|
|
120
|
-
const AiService = new EdgeAiServiceClient({
|
|
121
|
-
endpoint: AI_SERVICE_ENDPOINT.REMOTE,
|
|
122
|
-
});
|
|
123
119
|
executor = new FunctionExecutor(
|
|
124
|
-
new ServiceContainer().setServices({
|
|
120
|
+
new ServiceContainer().setServices({
|
|
121
|
+
// ai: {
|
|
122
|
+
// client: new Edge AiServiceClient({
|
|
123
|
+
// endpoint: AI_SERVICE_ENDPOINT.REMOTE,
|
|
124
|
+
// }),
|
|
125
|
+
// },
|
|
126
|
+
// database: { db: space!.db },
|
|
127
|
+
}),
|
|
125
128
|
);
|
|
126
129
|
}
|
|
127
130
|
|
|
@@ -190,7 +193,7 @@ const DefaultStory = ({
|
|
|
190
193
|
return <TranscriptionStory model={model} running={running} onRunningChange={setRunning} />;
|
|
191
194
|
};
|
|
192
195
|
|
|
193
|
-
const meta
|
|
196
|
+
const meta = {
|
|
194
197
|
title: 'plugins/plugin-transcription/MicrophoneTranscription',
|
|
195
198
|
render: DefaultStory,
|
|
196
199
|
decorators: [
|
|
@@ -200,7 +203,7 @@ const meta: Meta<typeof DefaultStory> = {
|
|
|
200
203
|
StorybookLayoutPlugin(),
|
|
201
204
|
ClientPlugin({
|
|
202
205
|
types: [TestItem, DataType.Person, DataType.Organization, Testing.DocumentType],
|
|
203
|
-
onClientInitialized: async (
|
|
206
|
+
onClientInitialized: async ({ client }) => {
|
|
204
207
|
await client.halo.createIdentity();
|
|
205
208
|
await client.spaces.waitUntilReady();
|
|
206
209
|
await client.spaces.default.waitUntilReady();
|
|
@@ -231,11 +234,11 @@ const meta: Meta<typeof DefaultStory> = {
|
|
|
231
234
|
withTheme,
|
|
232
235
|
withLayout({ fullscreen: true, classNames: 'justify-center' }),
|
|
233
236
|
],
|
|
234
|
-
}
|
|
237
|
+
} satisfies Meta<typeof DefaultStory>;
|
|
235
238
|
|
|
236
239
|
export default meta;
|
|
237
240
|
|
|
238
|
-
type Story = StoryObj<typeof
|
|
241
|
+
type Story = StoryObj<typeof meta>;
|
|
239
242
|
|
|
240
243
|
export const Default: Story = {
|
|
241
244
|
args: {
|
|
@@ -251,19 +254,21 @@ export const Default: Story = {
|
|
|
251
254
|
},
|
|
252
255
|
};
|
|
253
256
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
}
|
|
257
|
+
// NOTE: We are running out of free quota on hugging face entity extraction.
|
|
258
|
+
// TODO(mykola): Fix hugging face quota issues.
|
|
259
|
+
// export const EntityExtraction: Story = {
|
|
260
|
+
// args: {
|
|
261
|
+
// detectSpeaking: true,
|
|
262
|
+
// entityExtraction: 'ner',
|
|
263
|
+
// transcriberConfig: TRANSCRIBER_CONFIG,
|
|
264
|
+
// recorderConfig: RECORDER_CONFIG,
|
|
265
|
+
// audioConstraints: {
|
|
266
|
+
// echoCancellation: true,
|
|
267
|
+
// noiseSuppression: true,
|
|
268
|
+
// autoGainControl: true,
|
|
269
|
+
// },
|
|
270
|
+
// },
|
|
271
|
+
// };
|
|
267
272
|
|
|
268
273
|
export const SpeechDetection: Story = {
|
|
269
274
|
args: {
|
|
@@ -12,14 +12,15 @@ import { ScrollContainer } from '@dxos/react-ui-components';
|
|
|
12
12
|
import { type DataType } from '@dxos/schema';
|
|
13
13
|
|
|
14
14
|
import { type SerializationModel } from '../../model';
|
|
15
|
-
import {
|
|
15
|
+
import { TranscriptView } from '../Transcript';
|
|
16
16
|
|
|
17
17
|
export const TranscriptionStory: FC<{
|
|
18
18
|
model: SerializationModel<DataType.Message>;
|
|
19
|
+
disabled?: boolean;
|
|
19
20
|
running: boolean;
|
|
20
21
|
onRunningChange: Dispatch<SetStateAction<boolean>>;
|
|
21
22
|
audioRef?: RefObject<HTMLAudioElement>;
|
|
22
|
-
}> = ({ model, running, onRunningChange, audioRef }) => {
|
|
23
|
+
}> = ({ model, running, onRunningChange, audioRef, disabled }) => {
|
|
23
24
|
const space = useSpace();
|
|
24
25
|
|
|
25
26
|
return (
|
|
@@ -28,14 +29,17 @@ export const TranscriptionStory: FC<{
|
|
|
28
29
|
<Toolbar.Root>
|
|
29
30
|
<IconButton
|
|
30
31
|
iconOnly
|
|
32
|
+
disabled={disabled}
|
|
31
33
|
icon={running ? 'ph--pause--regular' : 'ph--play--regular'}
|
|
32
34
|
label={running ? 'Pause' : 'Play'}
|
|
33
35
|
onClick={() => onRunningChange((running) => !running)}
|
|
34
36
|
/>
|
|
35
37
|
</Toolbar.Root>
|
|
36
|
-
<ScrollContainer>
|
|
37
|
-
<
|
|
38
|
-
|
|
38
|
+
<ScrollContainer.Root pin>
|
|
39
|
+
<ScrollContainer.Content>
|
|
40
|
+
<TranscriptView space={space} model={model} />
|
|
41
|
+
</ScrollContainer.Content>
|
|
42
|
+
</ScrollContainer.Root>
|
|
39
43
|
</div>
|
|
40
44
|
);
|
|
41
45
|
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Effect, Schema } from 'effect';
|
|
6
|
+
|
|
7
|
+
import { ArtifactId } from '@dxos/assistant';
|
|
8
|
+
import { Obj } from '@dxos/echo';
|
|
9
|
+
import { DatabaseService, QueueService, defineFunction } from '@dxos/functions';
|
|
10
|
+
import { DataType } from '@dxos/schema';
|
|
11
|
+
|
|
12
|
+
import { renderByline } from '../components';
|
|
13
|
+
import { Transcript } from '../types';
|
|
14
|
+
|
|
15
|
+
export default defineFunction({
|
|
16
|
+
name: 'dxos.org/function/transcription/open',
|
|
17
|
+
description: 'Opens and reads the contents of a transcription object.',
|
|
18
|
+
inputSchema: Schema.Struct({
|
|
19
|
+
id: ArtifactId.annotations({
|
|
20
|
+
description: 'The ID of the transcription object.',
|
|
21
|
+
}),
|
|
22
|
+
}),
|
|
23
|
+
outputSchema: Schema.Struct({
|
|
24
|
+
content: Schema.String,
|
|
25
|
+
}),
|
|
26
|
+
handler: Effect.fn(function* ({ data: { id } }) {
|
|
27
|
+
const transcript = yield* DatabaseService.resolve(ArtifactId.toDXN(id), Transcript.Transcript);
|
|
28
|
+
const { dxn } = yield* Effect.promise(() => transcript.queue.load());
|
|
29
|
+
const queue = yield* QueueService.getQueue(dxn);
|
|
30
|
+
yield* Effect.promise(() => queue?.queryObjects());
|
|
31
|
+
const content = queue?.objects
|
|
32
|
+
.filter((message) => Obj.instanceOf(DataType.Message, message))
|
|
33
|
+
.flatMap((message, index) => renderByline([])(message, index))
|
|
34
|
+
.join('\n\n');
|
|
35
|
+
return { content };
|
|
36
|
+
}),
|
|
37
|
+
});
|