@dxos/plugin-transcription 0.8.4-main.72ec0f3 → 0.8.4-main.937b3ca
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-6EHKWVS4.mjs +12 -0
- package/dist/lib/browser/blueprint-definition-FTRNMLJZ.mjs +18 -0
- package/dist/lib/browser/blueprint-definition-FTRNMLJZ.mjs.map +7 -0
- package/dist/lib/browser/blueprints/index.mjs +9 -0
- package/dist/lib/browser/chunk-HOOPZ7EM.mjs +35 -0
- package/dist/lib/browser/chunk-HOOPZ7EM.mjs.map +7 -0
- package/dist/lib/browser/{chunk-EHT3TE6U.mjs → chunk-ICM7JRCO.mjs} +57 -97
- package/dist/lib/browser/chunk-ICM7JRCO.mjs.map +7 -0
- package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
- package/dist/lib/browser/chunk-J5LGTIGS.mjs.map +7 -0
- package/dist/lib/browser/chunk-Q5OC3WVG.mjs +72 -0
- package/dist/lib/browser/chunk-Q5OC3WVG.mjs.map +7 -0
- package/dist/lib/browser/{chunk-OCI42DWB.mjs → chunk-SYGEFDWO.mjs} +2 -2
- package/dist/lib/browser/{chunk-PVU4XCKI.mjs → chunk-TKFU53OZ.mjs} +17 -23
- package/dist/lib/browser/chunk-TKFU53OZ.mjs.map +7 -0
- package/dist/lib/browser/{blueprint-definition-WBWHO4OH.mjs → chunk-ZZF7ICVM.mjs} +30 -30
- package/dist/lib/browser/chunk-ZZF7ICVM.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +59 -72
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/operation-resolver-ZUWTU7C5.mjs +22 -0
- package/dist/lib/browser/operation-resolver-ZUWTU7C5.mjs.map +7 -0
- package/dist/lib/browser/react-surface-ZXH5267I.mjs +34 -0
- package/dist/lib/browser/react-surface-ZXH5267I.mjs.map +7 -0
- package/dist/lib/browser/{transcriber-E2KAOXPS.mjs → transcriber-EZZTUCPE.mjs} +17 -13
- package/dist/lib/browser/transcriber-EZZTUCPE.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +7 -5
- package/dist/lib/node-esm/{TranscriptContainer-WU3EDQR3.mjs → TranscriptContainer-5YT5W73I.mjs} +5 -4
- package/dist/lib/node-esm/TranscriptContainer-5YT5W73I.mjs.map +7 -0
- package/dist/lib/node-esm/blueprint-definition-IOX35YUX.mjs +19 -0
- package/dist/lib/node-esm/blueprint-definition-IOX35YUX.mjs.map +7 -0
- package/dist/lib/node-esm/blueprints/index.mjs +10 -0
- package/dist/lib/node-esm/blueprints/index.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-4BFY6P2D.mjs +73 -0
- package/dist/lib/node-esm/chunk-4BFY6P2D.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-7XASA7DX.mjs → chunk-BX2AB7S7.mjs} +57 -97
- package/dist/lib/node-esm/chunk-BX2AB7S7.mjs.map +7 -0
- package/dist/lib/node-esm/{blueprint-definition-WUHZFRWZ.mjs → chunk-CWP22IHV.mjs} +30 -30
- package/dist/lib/node-esm/chunk-CWP22IHV.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-UVOYXXDJ.mjs → chunk-EPC27WWV.mjs} +17 -23
- package/dist/lib/node-esm/chunk-EPC27WWV.mjs.map +7 -0
- package/dist/lib/node-esm/{chunk-X5BKN32O.mjs → chunk-GVAVEVZ6.mjs} +2 -2
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-NVM2QUMX.mjs +37 -0
- package/dist/lib/node-esm/chunk-NVM2QUMX.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +59 -72
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/operation-resolver-Z72B4H2Q.mjs +23 -0
- package/dist/lib/node-esm/operation-resolver-Z72B4H2Q.mjs.map +7 -0
- package/dist/lib/node-esm/react-surface-6GUBZX2V.mjs +35 -0
- package/dist/lib/node-esm/react-surface-6GUBZX2V.mjs.map +7 -0
- package/dist/lib/node-esm/{transcriber-ZPJM4U2W.mjs → transcriber-RGW3YYT4.mjs} +17 -13
- package/dist/lib/node-esm/transcriber-RGW3YYT4.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +7 -5
- package/dist/types/src/TranscriptionPlugin.d.ts +2 -1
- package/dist/types/src/TranscriptionPlugin.d.ts.map +1 -1
- package/dist/types/src/blueprints/index.d.ts +2 -0
- package/dist/types/src/blueprints/index.d.ts.map +1 -0
- package/dist/types/src/blueprints/transcription-blueprint.d.ts +21 -0
- package/dist/types/src/blueprints/transcription-blueprint.d.ts.map +1 -0
- package/dist/types/src/capabilities/blueprint-definition/blueprint-definition.d.ts +9 -0
- package/dist/types/src/capabilities/blueprint-definition/blueprint-definition.d.ts.map +1 -0
- package/dist/types/src/capabilities/blueprint-definition/index.d.ts +3 -0
- package/dist/types/src/capabilities/blueprint-definition/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +4 -5
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/operation-handler/index.d.ts +3 -0
- package/dist/types/src/capabilities/operation-handler/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/operation-handler/operation-handler.d.ts +5 -0
- package/dist/types/src/capabilities/operation-handler/operation-handler.d.ts.map +1 -0
- package/dist/types/src/capabilities/operation-resolver/index.d.ts +3 -0
- package/dist/types/src/capabilities/operation-resolver/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts +5 -0
- package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface/index.d.ts +3 -0
- package/dist/types/src/capabilities/react-surface/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface/react-surface.d.ts +5 -0
- package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +1 -0
- package/dist/types/src/capabilities/transcriber/index.d.ts +3 -0
- package/dist/types/src/capabilities/transcriber/index.d.ts.map +1 -0
- package/dist/types/src/capabilities/transcriber/transcriber.d.ts +9 -0
- package/dist/types/src/capabilities/transcriber/transcriber.d.ts.map +1 -0
- package/dist/types/src/components/Transcript/Transcript.d.ts +4 -7
- package/dist/types/src/components/Transcript/Transcript.d.ts.map +1 -1
- package/dist/types/src/components/Transcript/Transcript.stories.d.ts +2 -1
- package/dist/types/src/components/Transcript/Transcript.stories.d.ts.map +1 -1
- package/dist/types/src/components/Transcript/deprecated/OldTranscript.d.ts +9 -9
- package/dist/types/src/components/Transcript/deprecated/OldTranscript.d.ts.map +1 -1
- package/dist/types/src/components/TranscriptContainer.d.ts +4 -6
- package/dist/types/src/components/TranscriptContainer.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +1 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/stories/FileTranscription.stories.d.ts +3 -3
- package/dist/types/src/components/stories/FileTranscription.stories.d.ts.map +1 -1
- package/dist/types/src/components/stories/MicrophoneTranscription.stories.d.ts +3 -3
- package/dist/types/src/components/stories/MicrophoneTranscription.stories.d.ts.map +1 -1
- package/dist/types/src/components/stories/TranscriptionStory.d.ts.map +1 -1
- package/dist/types/src/hooks/useQueueModelAdapter.d.ts +1 -1
- package/dist/types/src/hooks/useQueueModelAdapter.d.ts.map +1 -1
- package/dist/types/src/hooks/useTranscriber.d.ts +1 -1
- package/dist/types/src/hooks/useTranscriber.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +2 -2
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/segments-normalization/message-normalizer.d.ts +2 -2
- package/dist/types/src/segments-normalization/message-normalizer.d.ts.map +1 -1
- package/dist/types/src/segments-normalization/normalization.d.ts +501 -456
- package/dist/types/src/segments-normalization/normalization.d.ts.map +1 -1
- package/dist/types/src/testing/testing.d.ts +4 -4
- package/dist/types/src/testing/testing.d.ts.map +1 -1
- package/dist/types/src/transcriber/media-stream-recorder.d.ts +2 -2
- package/dist/types/src/transcriber/media-stream-recorder.d.ts.map +1 -1
- package/dist/types/src/transcriber/transcriber.d.ts +2 -2
- package/dist/types/src/transcriber/transcriber.d.ts.map +1 -1
- package/dist/types/src/transcriber/transcription-manager.d.ts +6 -3
- package/dist/types/src/transcriber/transcription-manager.d.ts.map +1 -1
- package/dist/types/src/types/TranscriptAction.d.ts +22 -20
- package/dist/types/src/types/TranscriptAction.d.ts.map +1 -1
- package/dist/types/src/types/capabilities.d.ts +18 -0
- package/dist/types/src/types/capabilities.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/util/index.d.ts +1 -0
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/render-byline.d.ts +4 -0
- package/dist/types/src/util/render-byline.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +83 -71
- package/src/TranscriptionPlugin.tsx +34 -58
- package/src/blueprints/index.ts +5 -0
- package/src/blueprints/transcription-blueprint.ts +25 -0
- package/src/capabilities/blueprint-definition/blueprint-definition.ts +23 -0
- package/src/capabilities/blueprint-definition/index.ts +7 -0
- package/src/capabilities/index.ts +4 -8
- package/src/capabilities/operation-handler/index.ts +7 -0
- package/src/capabilities/operation-handler/operation-handler.ts +25 -0
- package/src/capabilities/operation-resolver/index.ts +7 -0
- package/src/capabilities/operation-resolver/operation-resolver.ts +25 -0
- package/src/capabilities/react-surface/index.ts +7 -0
- package/src/capabilities/react-surface/react-surface.tsx +27 -0
- package/src/capabilities/transcriber/index.ts +7 -0
- package/src/capabilities/transcriber/transcriber.ts +85 -0
- package/src/components/Transcript/Transcript.stories.tsx +31 -32
- package/src/components/Transcript/Transcript.tsx +8 -36
- package/src/components/Transcript/deprecated/OldTranscript.tsx +2 -2
- package/src/components/TranscriptContainer.tsx +12 -15
- package/src/components/stories/FileTranscription.stories.tsx +21 -26
- package/src/components/stories/KeyWordRecognition.stories.tsx +2 -2
- package/src/components/stories/MicrophoneTranscription.stories.tsx +41 -45
- package/src/components/stories/TranscriptionStory.tsx +1 -4
- package/src/functions/open.ts +5 -5
- package/src/hooks/useQueueModelAdapter.ts +1 -1
- package/src/hooks/useTranscriber.ts +1 -1
- package/src/hooks/useVoiceInput.ts +2 -2
- package/src/index.ts +1 -1
- package/src/meta.ts +2 -2
- package/src/model/model.test.ts +9 -3
- package/src/segments-normalization/message-normalizer.ts +12 -7
- package/src/segments-normalization/normalization.test.ts +0 -5
- package/src/testing/testing.ts +10 -5
- package/src/transcriber/media-stream-recorder.ts +3 -3
- package/src/transcriber/transcriber.browser.test.ts +1 -1
- package/src/transcriber/transcriber.ts +3 -3
- package/src/transcriber/transcription-manager.ts +15 -9
- package/src/types/TranscriptAction.ts +21 -13
- package/src/{capabilities → types}/capabilities.ts +8 -8
- package/src/types/index.ts +2 -1
- package/src/util/index.ts +1 -0
- package/src/util/render-byline.ts +33 -0
- package/dist/lib/browser/TranscriptContainer-EKSP5DQ6.mjs +0 -11
- package/dist/lib/browser/blueprint-definition-WBWHO4OH.mjs.map +0 -7
- package/dist/lib/browser/chunk-3MKZ2MNQ.mjs +0 -16
- package/dist/lib/browser/chunk-3MKZ2MNQ.mjs.map +0 -7
- package/dist/lib/browser/chunk-EHT3TE6U.mjs.map +0 -7
- package/dist/lib/browser/chunk-PVU4XCKI.mjs.map +0 -7
- package/dist/lib/browser/chunk-VBUIO677.mjs +0 -29
- package/dist/lib/browser/chunk-VBUIO677.mjs.map +0 -7
- package/dist/lib/browser/chunk-W7WKZTM4.mjs +0 -63
- package/dist/lib/browser/chunk-W7WKZTM4.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-ZTKTEAQX.mjs +0 -25
- package/dist/lib/browser/intent-resolver-ZTKTEAQX.mjs.map +0 -7
- package/dist/lib/browser/react-surface-NARMYO2O.mjs +0 -34
- package/dist/lib/browser/react-surface-NARMYO2O.mjs.map +0 -7
- package/dist/lib/browser/transcriber-E2KAOXPS.mjs.map +0 -7
- package/dist/lib/node-esm/blueprint-definition-WUHZFRWZ.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-7XASA7DX.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-OLMSTF3M.mjs +0 -64
- package/dist/lib/node-esm/chunk-OLMSTF3M.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-SWUVPFKR.mjs +0 -17
- package/dist/lib/node-esm/chunk-SWUVPFKR.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-UVOYXXDJ.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-YVNQN2J6.mjs +0 -30
- package/dist/lib/node-esm/chunk-YVNQN2J6.mjs.map +0 -7
- package/dist/lib/node-esm/intent-resolver-55WH2GY6.mjs +0 -26
- package/dist/lib/node-esm/intent-resolver-55WH2GY6.mjs.map +0 -7
- package/dist/lib/node-esm/react-surface-5MQA3IUS.mjs +0 -35
- package/dist/lib/node-esm/react-surface-5MQA3IUS.mjs.map +0 -7
- package/dist/lib/node-esm/transcriber-ZPJM4U2W.mjs.map +0 -7
- package/dist/types/src/capabilities/blueprint-definition.d.ts +0 -5
- package/dist/types/src/capabilities/blueprint-definition.d.ts.map +0 -1
- package/dist/types/src/capabilities/capabilities.d.ts +0 -17
- package/dist/types/src/capabilities/capabilities.d.ts.map +0 -1
- package/dist/types/src/capabilities/intent-resolver.d.ts +0 -4
- package/dist/types/src/capabilities/intent-resolver.d.ts.map +0 -1
- package/dist/types/src/capabilities/react-surface.d.ts +0 -4
- package/dist/types/src/capabilities/react-surface.d.ts.map +0 -1
- package/dist/types/src/capabilities/transcriber.d.ts +0 -8
- package/dist/types/src/capabilities/transcriber.d.ts.map +0 -1
- package/dist/types/src/types/Transcript.d.ts +0 -30
- package/dist/types/src/types/Transcript.d.ts.map +0 -1
- package/src/capabilities/blueprint-definition.ts +0 -31
- package/src/capabilities/intent-resolver.ts +0 -18
- package/src/capabilities/react-surface.tsx +0 -22
- package/src/capabilities/transcriber.ts +0 -77
- package/src/types/Transcript.ts +0 -44
- /package/dist/lib/browser/{TranscriptContainer-EKSP5DQ6.mjs.map → TranscriptContainer-6EHKWVS4.mjs.map} +0 -0
- /package/dist/lib/{node-esm/TranscriptContainer-WU3EDQR3.mjs.map → browser/blueprints/index.mjs.map} +0 -0
- /package/dist/lib/browser/{chunk-OCI42DWB.mjs.map → chunk-SYGEFDWO.mjs.map} +0 -0
- /package/dist/lib/node-esm/{chunk-X5BKN32O.mjs.map → chunk-GVAVEVZ6.mjs.map} +0 -0
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
renderByline
|
|
4
|
+
} from "./chunk-NVM2QUMX.mjs";
|
|
2
5
|
import {
|
|
3
6
|
TranscriptionCapabilities
|
|
4
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-4BFY6P2D.mjs";
|
|
5
8
|
|
|
6
9
|
// src/components/TranscriptContainer.tsx
|
|
7
|
-
import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
|
|
8
10
|
import React2 from "react";
|
|
9
|
-
import { getSpace } from "@dxos/client/echo";
|
|
10
11
|
import { Obj } from "@dxos/echo";
|
|
11
12
|
import { useMembers, useQueue } from "@dxos/react-client/echo";
|
|
12
|
-
import {
|
|
13
|
+
import { Layout } from "@dxos/react-ui-mosaic";
|
|
13
14
|
|
|
14
15
|
// src/hooks/useAudioFile.ts
|
|
15
16
|
import { useEffect, useState } from "react";
|
|
@@ -382,15 +383,6 @@ var useQueueModelAdapter = (renderer, queue, initialChunks = []) => {
|
|
|
382
383
|
// src/hooks/useTranscriber.ts
|
|
383
384
|
import { useEffect as useEffect4, useMemo as useMemo2 } from "react";
|
|
384
385
|
import { useCapabilities } from "@dxos/app-framework/react";
|
|
385
|
-
|
|
386
|
-
// src/capabilities/index.ts
|
|
387
|
-
import { lazy } from "@dxos/app-framework";
|
|
388
|
-
var BlueprintDefinition = lazy(() => import("./blueprint-definition-WUHZFRWZ.mjs"));
|
|
389
|
-
var IntentResolver = lazy(() => import("./intent-resolver-55WH2GY6.mjs"));
|
|
390
|
-
var ReactSurface = lazy(() => import("./react-surface-5MQA3IUS.mjs"));
|
|
391
|
-
var Transcriber = lazy(() => import("./transcriber-ZPJM4U2W.mjs"));
|
|
392
|
-
|
|
393
|
-
// src/hooks/useTranscriber.ts
|
|
394
386
|
var useTranscriber = ({ audioStreamTrack, recorderConfig, transcriberConfig, onSegments }) => {
|
|
395
387
|
const [getTranscriber] = useCapabilities(TranscriptionCapabilities.Transcriber);
|
|
396
388
|
const transcriber = useMemo2(() => {
|
|
@@ -483,11 +475,11 @@ var useVoiceInput = ({ active, onUpdate }) => {
|
|
|
483
475
|
};
|
|
484
476
|
|
|
485
477
|
// src/components/Transcript/Transcript.tsx
|
|
486
|
-
import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
|
|
487
478
|
import React from "react";
|
|
488
479
|
import { useThemeContext } from "@dxos/react-ui";
|
|
489
|
-
import {
|
|
490
|
-
import {
|
|
480
|
+
import { useTextEditor } from "@dxos/react-ui-editor";
|
|
481
|
+
import { autoScroll, createBasicExtensions, createMarkdownExtensions, createThemeExtensions, decorateMarkdown, editorSlots, preview } from "@dxos/ui-editor";
|
|
482
|
+
import { mx } from "@dxos/ui-theme";
|
|
491
483
|
import { isTruthy } from "@dxos/util";
|
|
492
484
|
|
|
493
485
|
// src/components/Transcript/transcript-extension.ts
|
|
@@ -641,88 +633,60 @@ var formatTimestamp = (timestamp, relative) => {
|
|
|
641
633
|
};
|
|
642
634
|
|
|
643
635
|
// src/components/Transcript/Transcript.tsx
|
|
644
|
-
var
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
slots: editorSlots
|
|
677
|
-
}),
|
|
678
|
-
decorateMarkdown(),
|
|
679
|
-
preview(),
|
|
680
|
-
transcript({
|
|
681
|
-
model,
|
|
682
|
-
started: object?.started ? new Date(object.started) : void 0
|
|
683
|
-
}),
|
|
684
|
-
autoScroll()
|
|
685
|
-
].filter(isTruthy)
|
|
686
|
-
};
|
|
687
|
-
}, [
|
|
688
|
-
space,
|
|
689
|
-
model
|
|
690
|
-
]);
|
|
691
|
-
return /* @__PURE__ */ React.createElement("div", {
|
|
692
|
-
ref: parentRef,
|
|
693
|
-
className: mx("flex grow overflow-hidden container-max-width", classNames),
|
|
694
|
-
"data-popover-collision-boundary": true
|
|
695
|
-
});
|
|
696
|
-
} finally {
|
|
697
|
-
_effect.f();
|
|
698
|
-
}
|
|
636
|
+
var TranscriptView = ({ classNames, transcript: object, model }) => {
|
|
637
|
+
const { themeMode } = useThemeContext();
|
|
638
|
+
const { parentRef } = useTextEditor(() => {
|
|
639
|
+
return {
|
|
640
|
+
extensions: [
|
|
641
|
+
createBasicExtensions({
|
|
642
|
+
readOnly: true,
|
|
643
|
+
lineWrapping: true,
|
|
644
|
+
search: true
|
|
645
|
+
}),
|
|
646
|
+
createMarkdownExtensions(),
|
|
647
|
+
createThemeExtensions({
|
|
648
|
+
themeMode,
|
|
649
|
+
slots: editorSlots
|
|
650
|
+
}),
|
|
651
|
+
decorateMarkdown(),
|
|
652
|
+
preview(),
|
|
653
|
+
transcript({
|
|
654
|
+
model,
|
|
655
|
+
started: object?.started ? new Date(object.started) : void 0
|
|
656
|
+
}),
|
|
657
|
+
autoScroll()
|
|
658
|
+
].filter(isTruthy)
|
|
659
|
+
};
|
|
660
|
+
}, [
|
|
661
|
+
model
|
|
662
|
+
]);
|
|
663
|
+
return /* @__PURE__ */ React.createElement("div", {
|
|
664
|
+
ref: parentRef,
|
|
665
|
+
className: mx("flex grow overflow-hidden container-max-width", classNames),
|
|
666
|
+
"data-popover-collision-boundary": true
|
|
667
|
+
});
|
|
699
668
|
};
|
|
700
669
|
|
|
701
670
|
// src/components/TranscriptContainer.tsx
|
|
702
|
-
var TranscriptionContainer = ({
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
}));
|
|
718
|
-
} finally {
|
|
719
|
-
_effect.f();
|
|
720
|
-
}
|
|
671
|
+
var TranscriptionContainer = ({ role, subject: transcript2 }) => {
|
|
672
|
+
const attendableId = Obj.getDXN(transcript2).toString();
|
|
673
|
+
const db = Obj.getDatabase(transcript2);
|
|
674
|
+
const members = useMembers(db?.spaceId).map((member) => member.identity);
|
|
675
|
+
const queue = useQueue(transcript2.queue.dxn, {
|
|
676
|
+
pollInterval: 1e3
|
|
677
|
+
});
|
|
678
|
+
const model = useQueueModelAdapter(renderByline(members), queue);
|
|
679
|
+
return /* @__PURE__ */ React2.createElement(Layout.Main, {
|
|
680
|
+
role
|
|
681
|
+
}, /* @__PURE__ */ React2.createElement(TranscriptView, {
|
|
682
|
+
attendableId,
|
|
683
|
+
model,
|
|
684
|
+
transcript: transcript2
|
|
685
|
+
}));
|
|
721
686
|
};
|
|
722
687
|
var TranscriptContainer_default = TranscriptionContainer;
|
|
723
688
|
|
|
724
689
|
export {
|
|
725
|
-
renderByline,
|
|
726
690
|
TranscriptView,
|
|
727
691
|
useAudioFile,
|
|
728
692
|
useAudioTrack,
|
|
@@ -730,10 +694,6 @@ export {
|
|
|
730
694
|
useTranscriber,
|
|
731
695
|
useVoiceInput,
|
|
732
696
|
TranscriptionContainer,
|
|
733
|
-
TranscriptContainer_default
|
|
734
|
-
BlueprintDefinition,
|
|
735
|
-
IntentResolver,
|
|
736
|
-
ReactSurface,
|
|
737
|
-
Transcriber
|
|
697
|
+
TranscriptContainer_default
|
|
738
698
|
};
|
|
739
|
-
//# sourceMappingURL=chunk-
|
|
699
|
+
//# sourceMappingURL=chunk-BX2AB7S7.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/components/TranscriptContainer.tsx", "../../../src/hooks/useAudioFile.ts", "../../../src/hooks/useAudioTrack.ts", "../../../src/hooks/useQueueModelAdapter.ts", "../../../src/model/model.ts", "../../../src/hooks/useTranscriber.ts", "../../../src/hooks/useVoiceInput.ts", "../../../src/components/Transcript/Transcript.tsx", "../../../src/components/Transcript/transcript-extension.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport React from 'react';\n\nimport { type SurfaceComponentProps } from '@dxos/app-framework/react';\nimport { Obj } from '@dxos/echo';\nimport { useMembers, useQueue } from '@dxos/react-client/echo';\nimport { Layout } from '@dxos/react-ui-mosaic';\nimport { type Message, type Transcript } from '@dxos/types';\n\nimport { useQueueModelAdapter } from '../hooks';\nimport { renderByline } from '../util';\n\nimport { TranscriptView } from './Transcript';\n\nexport type TranscriptionContainerProps = SurfaceComponentProps<Transcript.Transcript>;\n\nexport const TranscriptionContainer = ({ role, subject: transcript }: TranscriptionContainerProps) => {\n const attendableId = Obj.getDXN(transcript).toString();\n const db = Obj.getDatabase(transcript);\n const members = useMembers(db?.spaceId).map((member) => member.identity);\n const queue = useQueue<Message.Message>(transcript.queue.dxn, { pollInterval: 1_000 });\n const model = useQueueModelAdapter(renderByline(members), queue);\n\n return (\n <Layout.Main role={role}>\n <TranscriptView attendableId={attendableId} model={model} transcript={transcript} />\n </Layout.Main>\n );\n};\n\nexport default TranscriptionContainer;\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useEffect, useState } from 'react';\n\nimport { scheduleTask } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { log } from '@dxos/log';\n\nexport type UseAudioState = {\n audio?: HTMLAudioElement;\n stream?: MediaStream;\n track?: MediaStreamTrack;\n};\n\nexport const useAudioFile = (audioUrl: string, constraints?: MediaTrackConstraints): UseAudioState => {\n const [{ audio, stream, track }, setStream] = useState<UseAudioState>({});\n useEffect(() => {\n const ctx = new Context();\n\n scheduleTask(ctx, async () => {\n // TODO(wittjosiah): Fetch to external url fails in headless storybook test.\n try {\n const response = await fetch(audioUrl);\n const blob = await response.blob();\n const objectUrl = URL.createObjectURL(blob);\n ctx.onDispose(() => {\n URL.revokeObjectURL(objectUrl);\n });\n\n const audio = new Audio();\n audio.src = objectUrl;\n\n await new Promise<void>((resolve, reject) => {\n audio.addEventListener(\n 'error',\n (err) => {\n log.error('error', { err });\n reject(err);\n },\n { once: true },\n );\n audio.addEventListener(\n 'canplay',\n async () => {\n resolve();\n },\n { once: true },\n );\n audio.load();\n });\n\n const audioCtx = new AudioContext();\n\n // Resume AudioContext if it's suspended.\n if (audioCtx.state === 'suspended') {\n await audioCtx.resume();\n }\n\n const destination = audioCtx.createMediaStreamDestination();\n destination.channelCount = 1;\n\n const source = audioCtx.createMediaElementSource(audio);\n source.connect(destination);\n const track = destination.stream.getAudioTracks()[0];\n if (constraints) {\n await track.applyConstraints(constraints).catch((err) => log.catch(err));\n }\n\n // Also connect to speakers so audio is audible.\n setStream({\n audio,\n stream: destination.stream,\n track: destination.stream.getAudioTracks()[0],\n });\n } catch (err) {\n log.catch(err);\n }\n });\n\n return () => {\n void ctx.dispose();\n };\n }, [audioUrl]);\n\n return { audio, stream, track };\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useEffect, useState } from 'react';\n\n/**\n *\n */\n// TODO(burdon): Reconcile with react-ui-sfx and plugin-calls.\nexport const useAudioTrack = (active?: boolean, constraints?: MediaTrackConstraints): MediaStreamTrack | undefined => {\n const [track, setTrack] = useState<MediaStreamTrack>();\n useEffect(() => {\n if (!active) {\n track?.stop();\n setTrack(undefined);\n return;\n }\n\n const initAudio = async () => {\n const audio = new Audio();\n audio.srcObject = await navigator.mediaDevices.getUserMedia({ audio: constraints ?? true });\n const [track] = audio.srcObject.getAudioTracks();\n if (track) {\n setTrack(track);\n }\n };\n\n if (active) {\n void initAudio();\n }\n }, [active]);\n\n return track;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useEffect, useMemo, useState } from 'react';\n\nimport type { Obj } from '@dxos/echo';\nimport { type Queue } from '@dxos/react-client/echo';\n\nimport { type ChunkRenderer, SerializationModel } from '../model';\n\n/**\n * Model adapter for a queue.\n */\nexport const useQueueModelAdapter = <T extends Obj.Unknown>(\n renderer: ChunkRenderer<T>,\n queue: Queue<T> | undefined,\n initialChunks: T[] = [],\n): SerializationModel<T> => {\n const model = useMemo(() => new SerializationModel<T>(renderer, initialChunks), [queue]);\n const [loaded, setLoaded] = useState(false);\n\n // Set initial blocks.\n useEffect(() => {\n if (!queue) {\n return;\n }\n\n const update = () => {\n for (const block of queue?.objects ?? []) {\n model.appendChunk(block);\n }\n\n setLoaded(true);\n };\n\n // TODO(burdon): This is a hack to ensure the queue is loaded.\n let i: NodeJS.Timeout | undefined;\n if (queue.isLoading) {\n i = setInterval(() => {\n if (!queue?.isLoading) {\n clearInterval(i);\n update();\n }\n }, 1_000);\n } else {\n update();\n }\n\n return () => clearTimeout(i);\n }, [model, queue]);\n\n // TODO(burdon): Can we listen for queue events?\n useEffect(() => {\n if (!loaded || !queue || model.chunks.length === queue.objects.length) {\n return;\n }\n\n const chunk = queue.objects.at(-1);\n if (chunk) {\n model.appendChunk(chunk);\n }\n }, [model, loaded, queue?.objects.length]);\n\n return model;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { Text } from '@codemirror/state';\nimport { type EditorView } from '@codemirror/view';\n\nimport { Event } from '@dxos/async';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\n\nexport type Chunk = { id: string };\n\n/**\n * Covert block to a set of markdown lines.\n */\nexport type ChunkRenderer<T extends Chunk> = (chunk: T, index: number, debug?: boolean) => string[];\n\n/**\n * Abstract representation of the document model.\n */\nexport interface ChunkDocument {\n lineCount(): number;\n replaceLines(from: number, remove: number, insert: string[]): void;\n}\n\n/**\n * Codemirror document adapter.\n */\nexport class DocumentAdapter implements ChunkDocument {\n constructor(private readonly _view: EditorView) {}\n\n /** The document must always have at least one line. */\n lineCount(): number {\n return this._view.state.doc.lines - 1;\n }\n\n replaceLines(from: number, remove: number, insert: string[]): void {\n log('replaceLines', { count: this._view.state.doc.lines, from, remove, insert });\n\n const numLines = this._view.state.doc.lines;\n const posFrom = this._view.state.doc.line(from).from;\n const posTo = remove === 0 ? posFrom : this._view.state.doc.line(Math.min(numLines, from + remove)).from;\n\n // Don't remove the last line.\n let text = insert.join('\\n');\n if (posTo === this._view.state.doc.length) {\n text += '\\n';\n }\n\n this._view.dispatch({\n changes: { from: posFrom, to: posTo, insert: text },\n });\n }\n}\n\ntype ChunkChange<T extends Chunk> =\n | {\n type: 'append';\n index: number;\n chunk: T;\n }\n | {\n type: 'update';\n index: number;\n chunk: T;\n }\n | {\n type: 'delete';\n index: number;\n id: string;\n };\n\n/**\n * Each Chunk can be converted into a set of lines.\n * Chunks can be added, updated or deleted from the Queue.\n * A Document is an immutable projection that represents a flat list of lines corresponding to the Queue.\n *\n * Ideally we would implement a custom virtual Text model for the View, but this currently isn't possible in Codemirror.\n * Instead this model tracks changes and syncs them with the ChunkDocument.\n */\nexport class SerializationModel<T extends Chunk> {\n /** Ordered set of chunks. */\n private readonly _chunks: T[] = [];\n\n /** Map of chunk IDs to their current line counts. */\n private readonly _chunkLineCounts = new Map<string, number>();\n\n /** Map of line numbers to chunk IDs. */\n private readonly _lineToChunk = new Map<number, T>();\n\n /** Track chunk changes since last sync. */\n private readonly _changes: Array<ChunkChange<T>> = [];\n\n /** Emits when the document is updated. */\n public readonly update = new Event<void>();\n\n constructor(\n private readonly _renderer: ChunkRenderer<T>,\n initialChunks: T[] = [],\n ) {\n initialChunks.forEach((chunk) => {\n this.appendChunk(chunk);\n });\n }\n\n toJSON(): { chunks: number; changes: number } {\n return {\n chunks: this._chunks.length,\n changes: this._changes.length,\n };\n }\n\n get doc() {\n return Text.of([...this._chunks.flatMap((chunk, index) => this._renderer(chunk, index)), '']);\n }\n\n get chunks() {\n return this._chunks;\n }\n\n /**\n * Get the block ID at the given line number.\n */\n getChunkAtLine(line: number): T | undefined {\n return this._lineToChunk.get(line);\n }\n\n reset(): this {\n this._chunks.length = 0;\n this._chunkLineCounts.clear();\n this._lineToChunk.clear();\n this.update.emit();\n return this;\n }\n\n appendChunk(chunk: T): this {\n const index = this._chunks.length;\n this._chunks.push(chunk);\n this._changes.push({ type: 'append', index, chunk });\n this.update.emit();\n return this;\n }\n\n updateChunk(chunk: T): this {\n const index = this._chunks.findIndex((c) => c.id === chunk.id);\n invariant(index !== -1);\n this._chunks[index] = chunk;\n this._changes.push({ type: 'update', index, chunk });\n this.update.emit();\n return this;\n }\n\n deleteBlock(id: string): this {\n const index = this._chunks.findIndex((c) => c.id === id);\n invariant(index !== -1);\n this._chunks.splice(index, 1);\n this._changes.push({ type: 'delete', index, id });\n this.update.emit();\n return this;\n }\n\n /**\n * Syncs the tracked changes with the ChunkDocument.\n */\n sync(document: ChunkDocument): this {\n log('sync', { changes: this._changes });\n\n // Process each change in order.\n for (const change of this._changes) {\n switch (change.type) {\n case 'append': {\n // For appends, convert block to lines and add at the end.\n const lines = this._renderer(change.chunk, change.index);\n const lastLine = document.lineCount();\n document.replaceLines(lastLine + 1, 0, lines);\n break;\n }\n\n case 'update': {\n // For updates, find the block's line range and replace with new lines.\n let lineStart = 1;\n for (let i = 0; i < change.index; i++) {\n lineStart += this._chunkLineCounts.get(this._chunks[i].id)!;\n }\n const previousLineCount = this._chunkLineCounts.get(change.chunk.id)!;\n const newLines = this._renderer(change.chunk, change.index);\n document.replaceLines(lineStart, previousLineCount, newLines);\n break;\n }\n\n case 'delete': {\n // For deletes, find the block's line range and remove those lines.\n let lineStart = 1;\n for (let i = 0; i < change.index; i++) {\n lineStart += this._chunkLineCounts.get(this._chunks[i].id)!;\n }\n const previousLineCount = this._chunkLineCounts.get(change.id)!;\n document.replaceLines(lineStart, previousLineCount, []);\n break;\n }\n }\n }\n\n // Clear the line-to-block mapping.\n this._lineToChunk.clear();\n\n // Update all block line counts and line-to-block mapping after processing changes.\n let currentLine = 1;\n for (const [index, chunk] of this._chunks.entries()) {\n const lineCount = this._renderer(chunk, index).length;\n this._chunkLineCounts.set(chunk.id, lineCount);\n this._lineToChunk.set(currentLine, chunk);\n currentLine += lineCount;\n }\n\n // Clean up deleted blocks.\n const chunkIds = new Set(this._chunks.map((chunk) => chunk.id));\n for (const id of this._chunkLineCounts.keys()) {\n if (!chunkIds.has(id)) {\n this._chunkLineCounts.delete(id);\n }\n }\n\n // Clear changes after sync.\n this._changes.length = 0;\n return this;\n }\n}\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useEffect, useMemo } from 'react';\n\nimport { useCapabilities } from '@dxos/app-framework/react';\n\nimport { type Transcriber } from '../transcriber';\nimport { TranscriptionCapabilities } from '../types';\n\n/**\n * Records audio while user is speaking and transcribes it after user is done speaking.\n */\nexport const useTranscriber = ({\n audioStreamTrack,\n recorderConfig,\n transcriberConfig,\n onSegments,\n}: Partial<TranscriptionCapabilities.GetTranscriberProps>) => {\n const [getTranscriber] = useCapabilities(TranscriptionCapabilities.Transcriber);\n\n // Initialize audio transcription.\n const transcriber = useMemo<Transcriber | undefined>(() => {\n if (!getTranscriber || !audioStreamTrack || !onSegments) {\n return undefined;\n }\n\n return getTranscriber({\n audioStreamTrack,\n recorderConfig,\n transcriberConfig,\n onSegments,\n });\n }, [getTranscriber, audioStreamTrack, recorderConfig, transcriberConfig, onSegments]);\n\n useEffect(() => {\n return () => {\n void transcriber?.close();\n };\n }, [transcriber]);\n\n return transcriber;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { useCallback, useEffect, useState } from 'react';\n\nimport { scheduleMicroTask } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { log } from '@dxos/log';\nimport { useSoundEffect } from '@dxos/react-ui-sfx';\n\nimport { type TranscriberProps } from '../transcriber';\n\nimport { useAudioTrack } from './useAudioTrack';\nimport { useTranscriber } from './useTranscriber';\n\nexport type UseVoiceInputProps = {\n active?: boolean;\n onUpdate: (text: string) => void;\n};\n\n/**\n * Hook for voice input.\n */\nexport const useVoiceInput = ({ active, onUpdate }: UseVoiceInputProps) => {\n const soundStart = useSoundEffect('StartRecording');\n const soundStop = useSoundEffect('StopRecording');\n\n const handleSegments = useCallback<TranscriberProps['onSegments']>(async (segments) => {\n const text = segments.map((str) => str.text.trim().replace(/[^\\w\\s]/g, '')).join(' ');\n onUpdate(text);\n }, []);\n\n // Audio/transcription.\n const [recording, setRecording] = useState(false);\n const track = useAudioTrack(active);\n const transcriber = useTranscriber({\n audioStreamTrack: track,\n onSegments: handleSegments,\n });\n\n // Start/stop transcription.\n useEffect(() => {\n const ctx = new Context();\n scheduleMicroTask(ctx, async () => {\n if (active && transcriber) {\n await transcriber.open();\n log.info('starting...');\n setRecording(true);\n void soundStart.play();\n transcriber.startChunksRecording();\n } else if (!active && transcriber?.isOpen) {\n transcriber?.stopChunksRecording();\n await transcriber?.close();\n log.info('stopped');\n setRecording(false);\n void soundStop.play();\n }\n });\n\n return () => {\n void ctx.dispose();\n };\n }, [active, transcriber]);\n\n return { recording };\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport React from 'react';\n\nimport { type ThemedClassName, useThemeContext } from '@dxos/react-ui';\nimport { useTextEditor } from '@dxos/react-ui-editor';\nimport { type Message, type Transcript } from '@dxos/types';\nimport {\n autoScroll,\n createBasicExtensions,\n createMarkdownExtensions,\n createThemeExtensions,\n decorateMarkdown,\n editorSlots,\n preview,\n} from '@dxos/ui-editor';\nimport { mx } from '@dxos/ui-theme';\nimport { isTruthy } from '@dxos/util';\n\nimport { type SerializationModel } from '../../model';\nimport { renderByline } from '../../util';\n\nimport { transcript } from './transcript-extension';\n\nexport { renderByline };\n\nexport type TranscriptViewProps = ThemedClassName<{\n transcript?: Transcript.Transcript;\n model: SerializationModel<Message.Message>;\n // TODO(burdon): Are these still in use?\n attendableId?: string;\n ignoreAttention?: boolean;\n}>;\n\n/**\n * Transcript component implemented using the editor.\n */\nexport const TranscriptView = ({ classNames, transcript: object, model }: TranscriptViewProps) => {\n const { themeMode } = useThemeContext();\n const { parentRef } = useTextEditor(() => {\n return {\n extensions: [\n createBasicExtensions({ readOnly: true, lineWrapping: true, search: true }),\n createMarkdownExtensions(),\n createThemeExtensions({ themeMode, slots: editorSlots }),\n decorateMarkdown(),\n preview(),\n transcript({\n model,\n started: object?.started ? new Date(object.started) : undefined,\n }),\n autoScroll(),\n ].filter(isTruthy),\n };\n }, [model]);\n\n return (\n <div\n ref={parentRef}\n className={mx('flex grow overflow-hidden container-max-width', classNames)}\n data-popover-collision-boundary={true /* TODO(thure): Make this a constant and document it. */}\n />\n );\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { type Extension, RangeSetBuilder } from '@codemirror/state';\nimport { EditorView, GutterMarker, ViewPlugin, type ViewUpdate, gutter } from '@codemirror/view';\nimport { format } from 'date-fns/format';\nimport { intervalToDuration } from 'date-fns/intervalToDuration';\n\nimport { type CleanupFn, addEventListener, combine } from '@dxos/async';\nimport { type Message } from '@dxos/types';\n\nimport { DocumentAdapter, type SerializationModel } from '../../model';\n\n/**\n * Data structure that maps Chunks queue to lines with transcript state.\n */\nexport type TranscriptOptions = {\n model: SerializationModel<Message.Message>;\n started?: Date;\n};\n\n/**\n * Scrolling transcript with timestamps.\n */\nexport const transcript = ({ model, started }: TranscriptOptions): Extension => {\n return [\n // Show timestamps in the gutter.\n gutter({\n class: 'cm-timestamp-gutter',\n lineMarkerChange: (update) => update.docChanged || update.viewportChanged,\n markers: (view) => {\n const start = getStartTime(started, model.chunks[0]);\n const builder = new RangeSetBuilder<GutterMarker>();\n for (const { from, to } of view.visibleRanges) {\n let line = view.state.doc.lineAt(from);\n while (line.from <= to) {\n const block = model.getChunkAtLine(line.number)?.blocks[0];\n const timestamp = block?._tag === 'transcript' && block.started;\n if (timestamp) {\n builder.add(line.from, line.from, new TimestampMarker(line.number, new Date(timestamp), start));\n }\n\n if (line.to + 1 > view.state.doc.length) {\n break;\n }\n\n line = view.state.doc.lineAt(line.to + 1);\n }\n }\n\n return builder.finish();\n },\n }),\n\n // Listen for model updates.\n ViewPlugin.fromClass(\n class {\n private readonly _controls?: HTMLDivElement;\n private readonly _cleanup: CleanupFn;\n private readonly _adapter: DocumentAdapter;\n private _initialized = false;\n\n constructor(view: EditorView) {\n this._adapter = new DocumentAdapter(view);\n\n const scroller = view.scrollDOM;\n let isAutoScrolling = false;\n let hasScrolled = false;\n\n let timeout: NodeJS.Timeout | undefined;\n const scrollToBottom = (smooth = false) => {\n scroller.style.scrollBehavior = smooth ? 'smooth' : '';\n\n // Temporarily hide scrollbar to prevent flicker.\n scroller.classList.add('cm-hide-scrollbar');\n isAutoScrolling = true;\n clearTimeout(timeout);\n timeout = setTimeout(() => {\n this._controls?.classList.add('opacity-0');\n scroller.classList.remove('cm-hide-scrollbar');\n isAutoScrolling = false;\n }, 500);\n\n // Scroll to bottom.\n view.dispatch({\n effects: EditorView.scrollIntoView(view.state.doc.length, { y: 'end' }),\n });\n };\n\n // Event listeners.\n this._cleanup = combine(\n addEventListener(view.scrollDOM, 'scroll', () => {\n if (!isAutoScrolling) {\n hasScrolled = true;\n this._controls?.classList.remove('opacity-0');\n }\n }),\n\n model.update.on(() => {\n // Check if clamped to bottom.\n const autoScroll =\n scroller.scrollHeight - scroller.scrollTop - scroller.clientHeight === 0 || !hasScrolled;\n\n // Sync.\n model.sync(this._adapter);\n\n // Scroll.\n if (autoScroll) {\n scrollToBottom(true);\n }\n }),\n );\n }\n\n update(_update: ViewUpdate) {\n // Initial sync.\n if (!this._initialized) {\n this._initialized = true;\n setTimeout(() => {\n model.sync(this._adapter);\n });\n }\n }\n\n destroy() {\n this._controls?.remove();\n this._cleanup();\n }\n },\n ),\n\n EditorView.theme({\n '.cm-gutters': {\n backgroundColor: 'var(--dx-baseSurface)',\n },\n '.cm-timestamp-gutter': {\n width: '6rem',\n paddingLeft: '0.5rem',\n paddingRight: '1rem',\n },\n '.cm-timestamp-gutter > .cm-gutterElement > div': {\n display: 'inline-flex',\n textAlign: 'right',\n padding: '3px',\n },\n }),\n ];\n};\n\n/**\n * Gutter marker that displays a timestamp.\n */\nclass TimestampMarker extends GutterMarker {\n constructor(\n readonly _line: number,\n readonly _timestamp: Date,\n readonly _started?: Date,\n ) {\n super();\n }\n\n override eq(other: this) {\n return this._timestamp === other._timestamp;\n }\n\n override toDOM(view: EditorView) {\n const el = document.createElement('div');\n el.className = 'text-sm text-subdued hover:bg-hoverSurface cursor-pointer';\n el.textContent = formatTimestamp(this._timestamp, this._started);\n // TODO(burdon): Click to bookmark or copy hyperlink.\n el.onclick = () => {\n const pos = view.state.doc.line(this._line).from;\n view.dispatch({\n effects: EditorView.scrollIntoView(pos, { y: 'start' }),\n });\n };\n\n return el;\n }\n}\n\nconst getStartTime = (started?: Date, message?: Message.Message): Date | undefined => {\n if (started) {\n return started;\n }\n\n if (message?.blocks[0]?._tag === 'transcript' && message.blocks[0].started) {\n return new Date(message.blocks[0].started);\n }\n\n return undefined;\n};\n\nconst formatTimestamp = (timestamp: Date, relative?: Date) => {\n if (relative) {\n const pad = (n = 0) => String(n).padStart(2, '0');\n const { hours, minutes, seconds } = intervalToDuration({ start: relative, end: timestamp });\n return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;\n } else {\n return format(timestamp, 'HH:mm:ss');\n }\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["React", "Obj", "useMembers", "useQueue", "Layout", "useEffect", "useState", "scheduleTask", "Context", "log", "useAudioFile", "audioUrl", "constraints", "audio", "stream", "track", "setStream", "ctx", "response", "fetch", "blob", "objectUrl", "URL", "createObjectURL", "onDispose", "revokeObjectURL", "Audio", "src", "Promise", "resolve", "reject", "addEventListener", "err", "error", "once", "load", "audioCtx", "AudioContext", "state", "resume", "destination", "createMediaStreamDestination", "channelCount", "source", "createMediaElementSource", "connect", "getAudioTracks", "applyConstraints", "catch", "dispose", "useEffect", "useState", "useAudioTrack", "active", "constraints", "track", "setTrack", "useState", "useEffect", "stop", "undefined", "initAudio", "audio", "Audio", "srcObject", "navigator", "mediaDevices", "getUserMedia", "getAudioTracks", "useEffect", "useMemo", "useState", "Text", "Event", "invariant", "log", "DocumentAdapter", "_view", "lineCount", "state", "doc", "lines", "replaceLines", "from", "remove", "insert", "count", "numLines", "posFrom", "line", "posTo", "Math", "min", "text", "join", "length", "dispatch", "changes", "to", "SerializationModel", "_chunks", "_chunkLineCounts", "Map", "_lineToChunk", "_changes", "update", "_renderer", "initialChunks", "forEach", "chunk", "appendChunk", "toJSON", "chunks", "of", "flatMap", "index", "getChunkAtLine", "get", "reset", "clear", "emit", "push", "type", "updateChunk", "findIndex", "c", "id", "deleteBlock", "splice", "sync", "document", "change", "lastLine", "lineStart", "i", "previousLineCount", "newLines", "currentLine", "entries", "set", "chunkIds", "Set", "map", "keys", "has", "delete", "useQueueModelAdapter", "renderer", "queue", "initialChunks", "model", "useMemo", "SerializationModel", "loaded", "setLoaded", "useState", "useEffect", "update", "block", "objects", "appendChunk", "i", "isLoading", "setInterval", "clearInterval", "clearTimeout", "chunks", "length", "chunk", "at", "useEffect", "useMemo", "useCapabilities", "useTranscriber", "audioStreamTrack", "recorderConfig", "transcriberConfig", "onSegments", "getTranscriber", "useCapabilities", "TranscriptionCapabilities", "Transcriber", "transcriber", "useMemo", "undefined", "useEffect", "close", "useCallback", "useEffect", "useState", "scheduleMicroTask", "Context", "log", "useSoundEffect", "useVoiceInput", "active", "onUpdate", "soundStart", "useSoundEffect", "soundStop", "handleSegments", "useCallback", "segments", "text", "map", "str", "trim", "replace", "join", "recording", "setRecording", "useState", "track", "useAudioTrack", "transcriber", "useTranscriber", "audioStreamTrack", "onSegments", "useEffect", "ctx", "Context", "scheduleMicroTask", "open", "log", "info", "play", "startChunksRecording", "isOpen", "stopChunksRecording", "close", "dispose", "React", "useThemeContext", "useTextEditor", "autoScroll", "createBasicExtensions", "createMarkdownExtensions", "createThemeExtensions", "decorateMarkdown", "editorSlots", "preview", "mx", "isTruthy", "RangeSetBuilder", "EditorView", "GutterMarker", "ViewPlugin", "gutter", "format", "intervalToDuration", "addEventListener", "combine", "transcript", "model", "started", "gutter", "class", "lineMarkerChange", "update", "docChanged", "viewportChanged", "markers", "view", "start", "getStartTime", "chunks", "builder", "RangeSetBuilder", "from", "to", "visibleRanges", "line", "state", "doc", "lineAt", "block", "getChunkAtLine", "number", "blocks", "timestamp", "_tag", "add", "TimestampMarker", "Date", "length", "finish", "ViewPlugin", "fromClass", "_controls", "_cleanup", "_adapter", "_initialized", "DocumentAdapter", "scroller", "scrollDOM", "isAutoScrolling", "hasScrolled", "timeout", "scrollToBottom", "smooth", "style", "scrollBehavior", "classList", "clearTimeout", "setTimeout", "remove", "dispatch", "effects", "EditorView", "scrollIntoView", "y", "combine", "addEventListener", "on", "autoScroll", "scrollHeight", "scrollTop", "clientHeight", "sync", "_update", "destroy", "theme", "backgroundColor", "width", "paddingLeft", "paddingRight", "display", "textAlign", "padding", "GutterMarker", "_line", "_timestamp", "_started", "eq", "other", "toDOM", "el", "document", "createElement", "className", "textContent", "formatTimestamp", "onclick", "pos", "message", "undefined", "relative", "pad", "n", "String", "padStart", "hours", "minutes", "seconds", "intervalToDuration", "end", "format", "TranscriptView", "classNames", "transcript", "object", "model", "themeMode", "useThemeContext", "parentRef", "useTextEditor", "extensions", "createBasicExtensions", "readOnly", "lineWrapping", "search", "createMarkdownExtensions", "createThemeExtensions", "slots", "editorSlots", "decorateMarkdown", "preview", "started", "Date", "undefined", "autoScroll", "filter", "isTruthy", "div", "ref", "className", "mx", "data-popover-collision-boundary", "TranscriptionContainer", "role", "subject", "transcript", "attendableId", "Obj", "getDXN", "toString", "db", "getDatabase", "members", "useMembers", "spaceId", "map", "member", "identity", "queue", "useQueue", "dxn", "pollInterval", "model", "useQueueModelAdapter", "renderByline", "React", "Layout", "Main", "TranscriptView"]
|
|
7
|
+
}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
|
|
2
|
-
import "./chunk-X5BKN32O.mjs";
|
|
3
2
|
import {
|
|
4
3
|
renderByline
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-SWUVPFKR.mjs";
|
|
4
|
+
} from "./chunk-NVM2QUMX.mjs";
|
|
7
5
|
import {
|
|
8
|
-
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-YVNQN2J6.mjs";
|
|
6
|
+
__export
|
|
7
|
+
} from "./chunk-HSLMI22Q.mjs";
|
|
11
8
|
|
|
12
|
-
// src/
|
|
13
|
-
|
|
9
|
+
// src/blueprints/transcription-blueprint.ts
|
|
10
|
+
var transcription_blueprint_exports = {};
|
|
11
|
+
__export(transcription_blueprint_exports, {
|
|
12
|
+
Key: () => Key,
|
|
13
|
+
functions: () => functions,
|
|
14
|
+
make: () => make
|
|
15
|
+
});
|
|
14
16
|
import { Blueprint, Template } from "@dxos/blueprints";
|
|
15
17
|
import { trim as trim2 } from "@dxos/util";
|
|
16
18
|
|
|
@@ -19,8 +21,9 @@ import * as Effect from "effect/Effect";
|
|
|
19
21
|
import * as Schema from "effect/Schema";
|
|
20
22
|
import { ArtifactId } from "@dxos/assistant";
|
|
21
23
|
import { Obj } from "@dxos/echo";
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
+
import { Database } from "@dxos/echo";
|
|
25
|
+
import { QueueService, defineFunction } from "@dxos/functions";
|
|
26
|
+
import { Message, Transcript } from "@dxos/types";
|
|
24
27
|
var open_default = defineFunction({
|
|
25
28
|
key: "dxos.org/function/transcription/open",
|
|
26
29
|
name: "Open",
|
|
@@ -34,7 +37,7 @@ var open_default = defineFunction({
|
|
|
34
37
|
content: Schema.String
|
|
35
38
|
}),
|
|
36
39
|
handler: Effect.fn(function* ({ data: { id } }) {
|
|
37
|
-
const transcript = yield*
|
|
40
|
+
const transcript = yield* Database.Service.resolve(ArtifactId.toDXN(id), Transcript.Transcript);
|
|
38
41
|
const { dxn } = yield* Effect.promise(() => transcript.queue.load());
|
|
39
42
|
const queue = yield* QueueService.getQueue(dxn);
|
|
40
43
|
yield* Effect.promise(() => queue?.queryObjects());
|
|
@@ -123,29 +126,26 @@ var systemPrompt = trim`
|
|
|
123
126
|
If no actionable tasks are found, omit this tasks section.
|
|
124
127
|
`;
|
|
125
128
|
|
|
126
|
-
// src/
|
|
129
|
+
// src/blueprints/transcription-blueprint.ts
|
|
127
130
|
var functions = [
|
|
128
131
|
open_default,
|
|
129
132
|
summarize_default
|
|
130
133
|
];
|
|
131
|
-
var
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
`
|
|
144
|
-
})
|
|
145
|
-
}))
|
|
146
|
-
];
|
|
134
|
+
var Key = "dxos.org/blueprint/transcription";
|
|
135
|
+
var make = () => Blueprint.make({
|
|
136
|
+
key: Key,
|
|
137
|
+
name: "Transcription",
|
|
138
|
+
tools: Blueprint.toolDefinitions({
|
|
139
|
+
functions
|
|
140
|
+
}),
|
|
141
|
+
instructions: Template.make({
|
|
142
|
+
source: trim2`
|
|
143
|
+
You can open and summarize a meeting transcript.
|
|
144
|
+
`
|
|
145
|
+
})
|
|
147
146
|
});
|
|
147
|
+
|
|
148
148
|
export {
|
|
149
|
-
|
|
149
|
+
transcription_blueprint_exports
|
|
150
150
|
};
|
|
151
|
-
//# sourceMappingURL=
|
|
151
|
+
//# sourceMappingURL=chunk-CWP22IHV.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/blueprints/transcription-blueprint.ts", "../../../src/functions/open.ts", "../../../src/functions/summarize.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Blueprint, Template } from '@dxos/blueprints';\nimport { type FunctionDefinition } from '@dxos/functions';\nimport { trim } from '@dxos/util';\n\nimport { open, summarize } from '../functions';\n\nexport const functions: FunctionDefinition[] = [open, summarize];\n\nexport const Key = 'dxos.org/blueprint/transcription';\n\nexport const make = () =>\n Blueprint.make({\n key: Key,\n name: 'Transcription',\n tools: Blueprint.toolDefinitions({ functions }),\n instructions: Template.make({\n source: trim`\n You can open and summarize a meeting transcript.\n `,\n }),\n });\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Effect from 'effect/Effect';\nimport * as Schema from 'effect/Schema';\n\nimport { ArtifactId } from '@dxos/assistant';\nimport { Obj } from '@dxos/echo';\nimport { Database } from '@dxos/echo';\nimport { QueueService, defineFunction } from '@dxos/functions';\nimport { Message, Transcript } from '@dxos/types';\n\nimport { renderByline } from '../util';\n\nexport default defineFunction({\n key: 'dxos.org/function/transcription/open',\n name: 'Open',\n description: 'Opens and reads the contents of a transcription object.',\n inputSchema: Schema.Struct({\n id: ArtifactId.annotations({\n description: 'The ID of the transcription object.',\n }),\n }),\n outputSchema: Schema.Struct({\n content: Schema.String,\n }),\n handler: Effect.fn(function* ({ data: { id } }) {\n const transcript = yield* Database.Service.resolve(ArtifactId.toDXN(id), Transcript.Transcript);\n const { dxn } = yield* Effect.promise(() => transcript.queue.load());\n const queue = yield* QueueService.getQueue(dxn);\n yield* Effect.promise(() => queue?.queryObjects());\n const content = queue?.objects\n .filter((message) => Obj.instanceOf(Message.Message, message))\n .flatMap((message, index) => renderByline([])(message, index))\n .join('\\n\\n');\n return { content };\n }),\n});\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport * as Array from 'effect/Array';\nimport * as Effect from 'effect/Effect';\nimport * as Function from 'effect/Function';\nimport * as Layer from 'effect/Layer';\nimport * as Option from 'effect/Option';\nimport * as Schema from 'effect/Schema';\n\nimport { AiService, ConsolePrinter, ToolExecutionService, ToolResolverService } from '@dxos/ai';\nimport { AiSession, GenerationObserver } from '@dxos/assistant';\nimport { TracingService, defineFunction } from '@dxos/functions';\nimport { trim } from '@dxos/util';\n\n/**\n * Summarize a transcript of a meeting.\n */\nexport default defineFunction({\n key: 'dxos.org/function/transcription/summarize',\n name: 'Summarize',\n description: 'Summarize a transcript of a meeting.',\n inputSchema: Schema.Struct({\n transcript: Schema.String.annotations({\n description: 'The transcript of the meeting.',\n }),\n notes: Schema.optional(Schema.String).annotations({\n description: 'Additional notes from the participants.',\n }),\n }),\n outputSchema: Schema.Struct({\n summary: Schema.String.annotations({\n description: 'The summary of the transcript.',\n }),\n }),\n handler: Effect.fnUntraced(\n function* ({ data: { transcript, notes } }) {\n const result = yield* new AiSession().run({\n prompt: `Transcript: ${transcript}\\n\\nNotes: ${notes}`,\n history: [],\n system: systemPrompt,\n observer: GenerationObserver.fromPrinter(new ConsolePrinter({ tag: 'summarize' })),\n });\n\n const summary = Function.pipe(\n result,\n Array.findLast((msg) => msg.sender.role === 'assistant' && msg.blocks.some((block) => block._tag === 'text')),\n Option.flatMap((msg) =>\n Function.pipe(\n msg.blocks,\n Array.findLast((block) => block._tag === 'text'),\n Option.map((block) => block.text),\n ),\n ),\n Option.getOrThrowWith(() => new Error('No summary found')),\n );\n\n return { summary };\n },\n Effect.provide(\n Layer.mergeAll(\n AiService.model('@anthropic/claude-sonnet-4-0'),\n ToolResolverService.layerEmpty,\n ToolExecutionService.layerEmpty,\n TracingService.layerNoop,\n ),\n ),\n ),\n});\n\nconst systemPrompt = trim`\n You are a helpful assistant that summarizes transcripts of meetings.\n\n # Goal\n Create a markdown summary of the meeting transcript with text notes provided.\n Notes are very important so make sure to include them in the summary if they contain meaningful information.\n\n # Formatting\n - Format the summary as a markdown document without extra comments like \"Here is the summary of the transcript:\".\n - Use markdown formatting for headings and bullet points.\n - Format the summary as a list of key points and takeaways.\n - All names of people should be in bold.\n\n # Note Taking\n - Correlate items in the summary with the person of origin to build a coherent narrative.\n - Include short quotes verbatim where appropriate. Especially when concerned with design decisions and problem descriptions.\n\n # Tasks\n At the end of the summary include tasks.\n Extract only the tasks that are:\n - Directly actionable.\n - Clearly assigned to a person or team (or can easily be inferred).\n - Strongly implied by the conversation and/or user note (no speculative tasks).\n - Specific enough that someone reading them would know exactly what to do next.\n\n Format all tasks as markdown checkboxes using the syntax:\n - [ ] Task description.\n\n Additional information can be included (indented).\n\n If no actionable tasks are found, omit this tasks section.\n`;\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;AAAA;;;;;;AAIA,SAASA,WAAWC,gBAAgB;AAEpC,SAASC,QAAAA,aAAY;;;ACFrB,YAAYC,YAAY;AACxB,YAAYC,YAAY;AAExB,SAASC,kBAAkB;AAC3B,SAASC,WAAW;AACpB,SAASC,gBAAgB;AACzB,SAASC,cAAcC,sBAAsB;AAC7C,SAASC,SAASC,kBAAkB;AAIpC,IAAA,eAAeC,eAAe;EAC5BC,KAAK;EACLC,MAAM;EACNC,aAAa;EACbC,aAAoBC,cAAO;IACzBC,IAAIC,WAAWC,YAAY;MACzBL,aAAa;IACf,CAAA;EACF,CAAA;EACAM,cAAqBJ,cAAO;IAC1BK,SAAgBC;EAClB,CAAA;EACAC,SAAgBC,UAAG,WAAW,EAAEC,MAAM,EAAER,GAAE,EAAE,GAAE;AAC5C,UAAMS,aAAa,OAAOC,SAASC,QAAQC,QAAQX,WAAWY,MAAMb,EAAAA,GAAKc,WAAWA,UAAU;AAC9F,UAAM,EAAEC,IAAG,IAAK,OAAcC,eAAQ,MAAMP,WAAWQ,MAAMC,KAAI,CAAA;AACjE,UAAMD,QAAQ,OAAOE,aAAaC,SAASL,GAAAA;AAC3C,WAAcC,eAAQ,MAAMC,OAAOI,aAAAA,CAAAA;AACnC,UAAMjB,UAAUa,OAAOK,QACpBC,OAAO,CAACC,YAAYC,IAAIC,WAAWC,QAAQA,SAASH,OAAAA,CAAAA,EACpDI,QAAQ,CAACJ,SAASK,UAAUC,aAAa,CAAA,CAAE,EAAEN,SAASK,KAAAA,CAAAA,EACtDE,KAAK,MAAA;AACR,WAAO;MAAE3B;IAAQ;EACnB,CAAA;AACF,CAAA;;;AClCA,YAAY4B,WAAW;AACvB,YAAYC,aAAY;AACxB,YAAYC,cAAc;AAC1B,YAAYC,WAAW;AACvB,YAAYC,YAAY;AACxB,YAAYC,aAAY;AAExB,SAASC,WAAWC,gBAAgBC,sBAAsBC,2BAA2B;AACrF,SAASC,WAAWC,0BAA0B;AAC9C,SAASC,gBAAgBC,kBAAAA,uBAAsB;AAC/C,SAASC,YAAY;AAKrB,IAAA,oBAAeC,gBAAe;EAC5BC,KAAK;EACLC,MAAM;EACNC,aAAa;EACbC,aAAoBC,eAAO;IACzBC,YAAmBC,eAAOC,YAAY;MACpCL,aAAa;IACf,CAAA;IACAM,OAAcC,iBAAgBH,cAAM,EAAEC,YAAY;MAChDL,aAAa;IACf,CAAA;EACF,CAAA;EACAQ,cAAqBN,eAAO;IAC1BO,SAAgBL,eAAOC,YAAY;MACjCL,aAAa;IACf,CAAA;EACF,CAAA;EACAU,SAAgBC,mBACd,WAAW,EAAEC,MAAM,EAAET,YAAYG,MAAK,EAAE,GAAE;AACxC,UAAMO,SAAS,OAAO,IAAIC,UAAAA,EAAYC,IAAI;MACxCC,QAAQ,eAAeb,UAAAA;;SAAwBG,KAAAA;MAC/CW,SAAS,CAAA;MACTC,QAAQC;MACRC,UAAUC,mBAAmBC,YAAY,IAAIC,eAAe;QAAEC,KAAK;MAAY,CAAA,CAAA;IACjF,CAAA;AAEA,UAAMf,UAAmBgB,cACvBZ,QACMa,eAAS,CAACC,QAAQA,IAAIC,OAAOC,SAAS,eAAeF,IAAIG,OAAOC,KAAK,CAACC,UAAUA,MAAMC,SAAS,MAAA,CAAA,GAC9FC,eAAQ,CAACP,QACLF,cACPE,IAAIG,QACEJ,eAAS,CAACM,UAAUA,MAAMC,SAAS,MAAA,GAClCE,WAAI,CAACH,UAAUA,MAAMI,IAAI,CAAA,CAAA,GAG7BC,sBAAe,MAAM,IAAIC,MAAM,kBAAA,CAAA,CAAA;AAGxC,WAAO;MAAE7B;IAAQ;EACnB,GACO8B,gBACCC,eACJC,UAAUC,MAAM,8BAAA,GAChBC,oBAAoBC,YACpBC,qBAAqBD,YACrBE,eAAeC,SAAS,CAAA,CAAA;AAIhC,CAAA;AAEA,IAAM5B,eAAe6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AF7Dd,IAAMC,YAAkC;EAACC;EAAMC;;AAE/C,IAAMC,MAAM;AAEZ,IAAMC,OAAO,MAClBC,UAAUD,KAAK;EACbE,KAAKH;EACLI,MAAM;EACNC,OAAOH,UAAUI,gBAAgB;IAAET;EAAU,CAAA;EAC7CU,cAAcC,SAASP,KAAK;IAC1BQ,QAAQC;;;EAGV,CAAA;AACF,CAAA;",
|
|
6
|
+
"names": ["Blueprint", "Template", "trim", "Effect", "Schema", "ArtifactId", "Obj", "Database", "QueueService", "defineFunction", "Message", "Transcript", "defineFunction", "key", "name", "description", "inputSchema", "Struct", "id", "ArtifactId", "annotations", "outputSchema", "content", "String", "handler", "fn", "data", "transcript", "Database", "Service", "resolve", "toDXN", "Transcript", "dxn", "promise", "queue", "load", "QueueService", "getQueue", "queryObjects", "objects", "filter", "message", "Obj", "instanceOf", "Message", "flatMap", "index", "renderByline", "join", "Array", "Effect", "Function", "Layer", "Option", "Schema", "AiService", "ConsolePrinter", "ToolExecutionService", "ToolResolverService", "AiSession", "GenerationObserver", "TracingService", "defineFunction", "trim", "defineFunction", "key", "name", "description", "inputSchema", "Struct", "transcript", "String", "annotations", "notes", "optional", "outputSchema", "summary", "handler", "fnUntraced", "data", "result", "AiSession", "run", "prompt", "history", "system", "systemPrompt", "observer", "GenerationObserver", "fromPrinter", "ConsolePrinter", "tag", "pipe", "findLast", "msg", "sender", "role", "blocks", "some", "block", "_tag", "flatMap", "map", "text", "getOrThrowWith", "Error", "provide", "mergeAll", "AiService", "model", "ToolResolverService", "layerEmpty", "ToolExecutionService", "TracingService", "layerNoop", "trim", "functions", "open", "summarize", "Key", "make", "Blueprint", "key", "name", "tools", "toolDefinitions", "instructions", "Template", "source", "trim"]
|
|
7
|
+
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
mergeFloat64Arrays
|
|
4
|
+
} from "./chunk-NVM2QUMX.mjs";
|
|
2
5
|
import {
|
|
3
6
|
TRANSCRIPTION_URL
|
|
4
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-4BFY6P2D.mjs";
|
|
5
8
|
|
|
6
9
|
// src/transcriber/media-stream-recorder.ts
|
|
7
10
|
import { MediaRecorder, register } from "extendable-media-recorder";
|
|
@@ -131,19 +134,6 @@ import { DeferredTask, Trigger } from "@dxos/async";
|
|
|
131
134
|
import { LifecycleState, Resource } from "@dxos/context";
|
|
132
135
|
import { log as log2 } from "@dxos/log";
|
|
133
136
|
import { trace as trace2 } from "@dxos/tracing";
|
|
134
|
-
|
|
135
|
-
// src/util/array.ts
|
|
136
|
-
var mergeFloat64Arrays = (arrays) => {
|
|
137
|
-
const newArray = new Float64Array(arrays.reduce((acc, array) => array.length + acc, 0));
|
|
138
|
-
let offset = 0;
|
|
139
|
-
for (const array of arrays) {
|
|
140
|
-
newArray.set(array, offset);
|
|
141
|
-
offset += array.length;
|
|
142
|
-
}
|
|
143
|
-
return newArray;
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
// src/transcriber/transcriber.ts
|
|
147
137
|
function _ts_decorate2(decorators, target, key, desc) {
|
|
148
138
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
149
139
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -329,7 +319,7 @@ _ts_decorate2([
|
|
|
329
319
|
], Transcriber.prototype, "_fetchTranscription", null);
|
|
330
320
|
|
|
331
321
|
// src/transcriber/transcription-manager.ts
|
|
332
|
-
import {
|
|
322
|
+
import { Atom } from "@effect-atom/atom-react";
|
|
333
323
|
import { synchronized as synchronized2 } from "@dxos/async";
|
|
334
324
|
import { Resource as Resource2 } from "@dxos/context";
|
|
335
325
|
import { Obj } from "@dxos/echo";
|
|
@@ -346,20 +336,24 @@ var TRANSCRIBE_AFTER_CHUNKS_AMOUNT = 50;
|
|
|
346
336
|
var TranscriptionManager = class extends Resource2 {
|
|
347
337
|
_edgeClient;
|
|
348
338
|
_messageEnricher;
|
|
339
|
+
_registry;
|
|
349
340
|
_audioStreamTrack = void 0;
|
|
350
341
|
_identityDid = void 0;
|
|
351
342
|
_mediaRecorder = void 0;
|
|
352
343
|
_transcriber = void 0;
|
|
353
344
|
_queue = void 0;
|
|
354
|
-
|
|
345
|
+
_enabledAtom = Atom.make(false);
|
|
355
346
|
constructor(options) {
|
|
356
347
|
super();
|
|
357
348
|
this._edgeClient = options.edgeClient;
|
|
358
349
|
this._messageEnricher = options.messageEnricher;
|
|
350
|
+
this._registry = options.registry;
|
|
359
351
|
}
|
|
360
|
-
/** @reactive */
|
|
361
352
|
get enabled() {
|
|
362
|
-
return this.
|
|
353
|
+
return this._enabledAtom;
|
|
354
|
+
}
|
|
355
|
+
getEnabled() {
|
|
356
|
+
return this._registry.get(this._enabledAtom);
|
|
363
357
|
}
|
|
364
358
|
setQueue(queue) {
|
|
365
359
|
this._queue = queue;
|
|
@@ -372,7 +366,7 @@ var TranscriptionManager = class extends Resource2 {
|
|
|
372
366
|
return this;
|
|
373
367
|
}
|
|
374
368
|
setRecording(recording) {
|
|
375
|
-
if (!this.isOpen || !this.
|
|
369
|
+
if (!this.isOpen || !this.getEnabled()) {
|
|
376
370
|
return this;
|
|
377
371
|
}
|
|
378
372
|
if (recording) {
|
|
@@ -383,10 +377,10 @@ var TranscriptionManager = class extends Resource2 {
|
|
|
383
377
|
return this;
|
|
384
378
|
}
|
|
385
379
|
async setEnabled(enabled) {
|
|
386
|
-
if (this.
|
|
380
|
+
if (this.getEnabled() === enabled) {
|
|
387
381
|
return;
|
|
388
382
|
}
|
|
389
|
-
this.
|
|
383
|
+
this._registry.set(this._enabledAtom, enabled ?? false);
|
|
390
384
|
if (enabled) {
|
|
391
385
|
await this._maybeRestartTranscriber();
|
|
392
386
|
} else {
|
|
@@ -407,7 +401,7 @@ var TranscriptionManager = class extends Resource2 {
|
|
|
407
401
|
await this._stopTranscriber();
|
|
408
402
|
}
|
|
409
403
|
async _maybeRestartTranscriber() {
|
|
410
|
-
if (!this._audioStreamTrack || !this.
|
|
404
|
+
if (!this._audioStreamTrack || !this.getEnabled() || !this.isOpen) {
|
|
411
405
|
return;
|
|
412
406
|
}
|
|
413
407
|
let needReinit = false;
|
|
@@ -464,4 +458,4 @@ export {
|
|
|
464
458
|
Transcriber,
|
|
465
459
|
TranscriptionManager
|
|
466
460
|
};
|
|
467
|
-
//# sourceMappingURL=chunk-
|
|
461
|
+
//# sourceMappingURL=chunk-EPC27WWV.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/transcriber/media-stream-recorder.ts", "../../../src/transcriber/transcriber.ts", "../../../src/transcriber/transcription-manager.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { type IBlobEvent, type IMediaRecorder, MediaRecorder, register } from 'extendable-media-recorder';\nimport { WaveFile } from 'wavefile';\n\nimport { synchronized } from '@dxos/async';\nimport { invariant } from '@dxos/invariant';\nimport { log } from '@dxos/log';\nimport { trace } from '@dxos/tracing';\n\nimport { type AudioChunk, type AudioRecorder, type WavConfig } from './audio-recorder';\n\nlet initializingPromise: Promise<void> | undefined;\n\nconst initializeExtendableMediaRecorder = async () => {\n const { connect } = await import('extendable-media-recorder-wav-encoder');\n await register(await connect());\n};\n\nexport type MediaStreamRecorderProps = {\n mediaStreamTrack: MediaStreamTrack;\n config: {\n interval: number;\n };\n};\n\n/**\n * Recorder that uses the MediaContext API and AudioNode API to record audio.\n *\n * It records MediaStream using https://www.npmjs.com/package/extendable-media-recorder.\n */\n@trace.resource()\nexport class MediaStreamRecorder implements AudioRecorder {\n private readonly _mediaStreamTrack: MediaStreamTrack;\n /**\n * Default MediaRecorder implementation do not support wav encoding.\n */\n private readonly _config: MediaStreamRecorderProps['config'];\n private _mediaRecorder?: IMediaRecorder = undefined;\n private _header?: Uint8Array = undefined;\n private _onChunk?: (chunk: AudioChunk) => void;\n\n constructor({ mediaStreamTrack, config }: MediaStreamRecorderProps) {\n this._mediaStreamTrack = mediaStreamTrack;\n this._config = config;\n }\n\n get wavConfig(): WavConfig {\n const settings = this._mediaStreamTrack.getSettings();\n return {\n channels: settings.channelCount ?? 1,\n sampleRate: settings.sampleRate ?? 16000,\n bitDepthCode: settings.sampleSize ? String(settings.sampleSize) : '16',\n };\n }\n\n get mediaStreamTrack() {\n return this._mediaStreamTrack;\n }\n\n setOnChunk(onChunk: (chunk: AudioChunk) => void): void {\n this._onChunk = onChunk;\n }\n\n async start(): Promise<void> {\n await (initializingPromise ??= initializeExtendableMediaRecorder()).catch((err) =>\n log.info('initializeExtendableMediaRecorder', { err }),\n );\n\n if (!this._mediaRecorder) {\n const stream = new MediaStream([this._mediaStreamTrack]);\n this._mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/wav' });\n }\n\n if (this._mediaRecorder.state === 'recording') {\n return;\n }\n invariant(this._onChunk, 'MediaStreamRecorder: onChunk is not set');\n this._mediaRecorder.ondataavailable = (event) => this._ondataavailable(event);\n this._mediaRecorder.start(this._config.interval);\n }\n\n async stop(): Promise<void> {\n if (this._mediaRecorder?.state !== 'recording') {\n return;\n }\n this._mediaRecorder.stop();\n }\n\n @synchronized\n private async _ondataavailable(event: IBlobEvent): Promise<void> {\n const blob = event.data;\n const uint8Array = new Uint8Array(await blob.arrayBuffer());\n\n // First chunk from the MediaRecorder has a header.\n const isHeader =\n uint8Array[0] === 0x52 && // R\n uint8Array[1] === 0x49 && // I\n uint8Array[2] === 0x46 && // F\n uint8Array[3] === 0x46; // F\n let wav: WaveFile;\n\n if (isHeader) {\n wav = new WaveFile(uint8Array);\n this._header = uint8Array.slice(0, 44);\n } else if (this._header) {\n wav = new WaveFile(new Uint8Array([...this._header, ...uint8Array]));\n } else {\n log.warn('MediaStreamRecorder: no header');\n return;\n }\n\n this._onChunk!({\n timestamp: Date.now(),\n data: wav.getSamples(),\n });\n }\n}\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { WaveFile } from 'wavefile';\n\nimport { DeferredTask, Trigger } from '@dxos/async';\nimport { type Context, LifecycleState, Resource } from '@dxos/context';\nimport { log } from '@dxos/log';\nimport { trace } from '@dxos/tracing';\nimport { type ContentBlock } from '@dxos/types';\n\nimport { TRANSCRIPTION_URL } from '../types';\nimport { mergeFloat64Arrays } from '../util';\n\nimport { type AudioChunk, type AudioRecorder } from './audio-recorder';\n\ntype WhisperWord = {\n word: string;\n\n /**\n * Time in seconds from the start of the audio.\n */\n start: number;\n\n /**\n * Time in seconds from the start of the audio.\n */\n end: number;\n};\n\ntype WhisperSegment = {\n text: string;\n\n /**\n * Time in seconds from the start of the audio.\n */\n start: number;\n\n /**\n * Time in seconds from the start of the audio.\n */\n end: number;\n\n /**\n * Probability of no speech in the segment.\n */\n no_speech_prob: number;\n\n words: WhisperWord[];\n};\n\nexport type TranscribeConfig = {\n /**\n * Number of chunks to transcribe automatically after.\n */\n transcribeAfterChunksAmount: number;\n\n /**\n * Number of chunks to save before the user starts speaking.\n * This is needed to catch the beginning of the user's speech.\n */\n prefixBufferChunksAmount: number;\n};\n\nexport type TranscriberProps = {\n config: TranscribeConfig;\n recorder: AudioRecorder;\n /**\n * Callback to handle the transcribed segments, after all segment transformers are applied.\n * @param segments - The transcribed segments.\n */\n onSegments: (segments: ContentBlock.Transcript[]) => Promise<void>;\n};\n\n/**\n * Handles transcription of audio chunks.\n * If user is not speaking, the last `minChunksAmount` chunks are saved and transcribed.\n * If user is speaking, the chunks are added to the buffer until the user is done talking.\n */\nexport class Transcriber extends Resource {\n private _audioChunks: AudioChunk[] = [];\n private _lastUsedTimestamp = 0;\n\n private readonly _openTrigger = new Trigger({ autoReset: true });\n\n private readonly _config: TranscribeConfig;\n private readonly _recorder: AudioRecorder;\n private readonly _onSegments: TranscriberProps['onSegments'];\n\n private _recording = false;\n private _transcribeTask?: DeferredTask = undefined;\n\n constructor({ config, recorder, onSegments }: TranscriberProps) {\n super();\n this._config = config;\n this._recorder = recorder;\n this._onSegments = onSegments;\n }\n\n protected override async _open(ctx: Context): Promise<void> {\n log.info('opening');\n this._recorder.setOnChunk((chunk) => this._saveAudioChunk(chunk));\n await this._recorder.start();\n this._transcribeTask = new DeferredTask(ctx, async () => this._transcribe());\n this._openTrigger.wake();\n }\n\n protected override async _close(): Promise<void> {\n log.info('closing');\n this._recording = false;\n this._transcribeTask = undefined;\n await this._recorder.stop();\n }\n\n startChunksRecording(): void {\n log.info('starting');\n if (this._lifecycleState !== LifecycleState.OPEN) {\n return;\n }\n\n this._recording = true;\n }\n\n stopChunksRecording(): void {\n if (this._lifecycleState !== LifecycleState.OPEN || !this._recording) {\n return;\n }\n\n this._recording = false;\n this._transcribeTask?.schedule();\n log.info('stopped');\n }\n\n private _saveAudioChunk(chunk: AudioChunk): void {\n log('saving audio chunk', { chunk });\n this._audioChunks.push(chunk);\n\n // Clean the buffer if the user is not speaking and the transcription task is not scheduled.\n if (\n !this._recording &&\n (!this._transcribeTask || !this._transcribeTask.scheduled) &&\n this._audioChunks.length >= this._config.prefixBufferChunksAmount\n ) {\n this._audioChunks = this._dropOldChunks();\n } else if (this._audioChunks.length >= this._config.transcribeAfterChunksAmount && this._recording) {\n this._transcribeTask?.schedule();\n }\n }\n\n private async _transcribe(): Promise<void> {\n log('transcribing', { chunks: this._audioChunks.length });\n const chunks = this._audioChunks;\n this._audioChunks = this._dropOldChunks();\n if (chunks.length === 0) {\n return;\n }\n\n const audio = await this._mergeAudioChunks(chunks);\n const segments = await this._fetchTranscription(audio);\n if (!Array.isArray(segments) || segments.length === 0) {\n return;\n }\n\n const alignedSegments = this._alignSegments(segments, chunks);\n if (alignedSegments.length > 0) {\n await this._onSegments(alignedSegments);\n }\n }\n\n private _dropOldChunks(): AudioChunk[] {\n return this._config.prefixBufferChunksAmount > 0\n ? this._audioChunks.slice(-this._config.prefixBufferChunksAmount)\n : [];\n }\n\n @trace.span({ showInBrowserTimeline: true })\n private async _mergeAudioChunks(chunks: AudioChunk[]): Promise<string> {\n const file = new WaveFile();\n const wavConfig = this._recorder.wavConfig;\n\n file.fromScratch(\n wavConfig.channels,\n wavConfig.sampleRate,\n wavConfig.bitDepthCode,\n mergeFloat64Arrays(chunks.map(({ data }) => data)),\n );\n\n return file.toBase64();\n }\n\n @trace.span({ showInBrowserTimeline: true })\n private async _fetchTranscription(audio: string): Promise<WhisperSegment[]> {\n if (audio.length === 0) {\n this._audioChunks = [];\n throw new Error('No audio to send for transcribing');\n }\n\n const response = await fetch(`${TRANSCRIPTION_URL}/transcribe`, {\n method: 'POST',\n body: JSON.stringify({ audio }),\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n this._audioChunks = [];\n throw new Error(`Transcription failed: ${response.statusText}`);\n }\n\n const { segments } = (await response.json()) as {\n segments: WhisperSegment[];\n };\n\n log.info('transcription response', {\n segments: segments.length,\n string: segments.map((segments) => segments.text).join(' '),\n });\n\n return segments;\n }\n\n private _alignSegments(segments: WhisperSegment[], originalChunks: AudioChunk[]): ContentBlock.Transcript[] {\n // Absolute zero for all relative timestamps in the segments.\n const zeroTimestamp = originalChunks.at(0)!.timestamp;\n\n const filteredSegments = segments\n // Use segments that end after the last used timestamp.\n // Segments could overlap, so we need to filter words that starts after the last used timestamp.\n .filter((segment) => zeroTimestamp + segment.end * 1_000 >= this._lastUsedTimestamp)\n // Use words that starts after the last used timestamp.\n .map((segment) => {\n const words = segment.words.filter((word) => zeroTimestamp + word.start * 1_000 >= this._lastUsedTimestamp);\n return {\n ...segment,\n words,\n text: words.map((word) => word.word).join(''),\n start: words.at(0)?.start ?? segment.end,\n };\n })\n .filter((segment) => segment.words.length > 0);\n\n if (filteredSegments.length === 0) {\n return [];\n }\n\n // Update last timestamp.\n this._lastUsedTimestamp = zeroTimestamp + filteredSegments.at(-1)!.end * 1_000;\n\n // Add absolute timestamp to each segment.\n return filteredSegments.map((segment) => ({\n _tag: 'transcript',\n started: new Date(zeroTimestamp + segment.start * 1_000).toISOString(),\n text: segment.text.trim(),\n }));\n }\n}\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { Atom, type Registry } from '@effect-atom/atom-react';\n\nimport { synchronized } from '@dxos/async';\nimport { Resource } from '@dxos/context';\nimport { Obj } from '@dxos/echo';\nimport { type Queue } from '@dxos/echo-db';\nimport { type EdgeHttpClient } from '@dxos/react-edge-client';\nimport { type ContentBlock, Message } from '@dxos/types';\n\nimport { MediaStreamRecorder } from './media-stream-recorder';\nimport { Transcriber } from './transcriber';\n\n/**\n * Length of the chunk in ms.\n */\nconst RECORD_INTERVAL = 200;\n\n/**\n * Number of chunks to save before the user starts speaking.\n */\nconst PREFIXED_CHUNKS_AMOUNT = 10;\n\n/**\n * Number of chunks to transcribe automatically after.\n * Combined should be mess than 25MB or whisper would fail.\n */\nconst TRANSCRIBE_AFTER_CHUNKS_AMOUNT = 50;\n\nexport type TranscriptMessageEnricher = (message: Message.Message) => Promise<Message.Message>;\n\nexport type TranscriptionManagerOptions = {\n edgeClient: EdgeHttpClient;\n registry: Registry.Registry;\n\n /**\n * Enrich the message before it is written to the transcription queue.\n */\n messageEnricher?: TranscriptMessageEnricher;\n};\n\n/**\n * Manages transcription state for a meeting.\n */\nexport class TranscriptionManager extends Resource {\n private readonly _edgeClient: EdgeHttpClient;\n private readonly _messageEnricher?: TranscriptMessageEnricher;\n private readonly _registry: Registry.Registry;\n private _audioStreamTrack?: MediaStreamTrack = undefined;\n private _identityDid?: string = undefined;\n private _mediaRecorder?: MediaStreamRecorder = undefined;\n private _transcriber?: Transcriber = undefined;\n private _queue?: Queue<Message.Message> = undefined;\n private _enabledAtom = Atom.make(false);\n\n constructor(options: TranscriptionManagerOptions) {\n super();\n this._edgeClient = options.edgeClient;\n this._messageEnricher = options.messageEnricher;\n this._registry = options.registry;\n }\n\n get enabled(): Atom.Atom<boolean> {\n return this._enabledAtom;\n }\n\n getEnabled(): boolean {\n return this._registry.get(this._enabledAtom);\n }\n\n setQueue(queue: Queue<Message.Message>): this {\n this._queue = queue;\n return this;\n }\n\n setIdentityDid(did: string): this {\n if (this._identityDid !== did) {\n this._identityDid = did;\n }\n return this;\n }\n\n setRecording(recording?: boolean): this {\n if (!this.isOpen || !this.getEnabled()) {\n return this;\n }\n\n if (recording) {\n this._transcriber?.startChunksRecording();\n } else {\n this._transcriber?.stopChunksRecording();\n }\n return this;\n }\n\n async setEnabled(enabled: boolean): Promise<void> {\n if (this.getEnabled() === enabled) {\n return;\n }\n\n this._registry.set(this._enabledAtom, enabled ?? false);\n if (enabled) {\n await this._maybeRestartTranscriber();\n } else {\n await this._stopTranscriber();\n }\n }\n\n @synchronized\n async setAudioTrack(track?: MediaStreamTrack): Promise<void> {\n if (this._audioStreamTrack === track) {\n return;\n }\n\n this._audioStreamTrack = track;\n await this._maybeRestartTranscriber();\n }\n\n protected override async _open(): Promise<void> {\n await this._maybeRestartTranscriber();\n }\n\n protected override async _close(): Promise<void> {\n await this._stopTranscriber();\n }\n\n private async _maybeRestartTranscriber(): Promise<void> {\n if (!this._audioStreamTrack || !this.getEnabled() || !this.isOpen) {\n return;\n }\n\n // Reinitialize transcriber if queue or media stream track has changed.\n let needReinit = false;\n if (this._audioStreamTrack !== this._mediaRecorder?.mediaStreamTrack) {\n this._mediaRecorder = new MediaStreamRecorder({\n mediaStreamTrack: this._audioStreamTrack,\n config: { interval: RECORD_INTERVAL },\n });\n needReinit = true;\n }\n if (needReinit) {\n await this._transcriber?.close();\n this._transcriber = new Transcriber({\n config: {\n transcribeAfterChunksAmount: TRANSCRIBE_AFTER_CHUNKS_AMOUNT,\n prefixBufferChunksAmount: PREFIXED_CHUNKS_AMOUNT,\n },\n recorder: this._mediaRecorder,\n onSegments: (segments) => this._onSegments(segments),\n });\n\n await this._transcriber?.open();\n }\n }\n\n private async _stopTranscriber(): Promise<void> {\n await this._transcriber?.close();\n }\n\n private async _onSegments(segments: ContentBlock.Transcript[]): Promise<void> {\n if (!this.isOpen || !this._queue) {\n return;\n }\n\n let block = Obj.make(Message.Message, {\n created: new Date().toISOString(),\n blocks: segments,\n sender: { identityDid: this._identityDid },\n });\n\n if (this._messageEnricher) {\n block = await this._messageEnricher(block);\n }\n\n await this._queue.append([block]);\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["MediaRecorder", "register", "WaveFile", "synchronized", "invariant", "log", "trace", "initializingPromise", "initializeExtendableMediaRecorder", "connect", "MediaStreamRecorder", "_mediaStreamTrack", "_config", "_mediaRecorder", "undefined", "_header", "_onChunk", "mediaStreamTrack", "config", "wavConfig", "settings", "getSettings", "channels", "channelCount", "sampleRate", "bitDepthCode", "sampleSize", "String", "setOnChunk", "onChunk", "start", "catch", "err", "info", "stream", "MediaStream", "mimeType", "state", "ondataavailable", "event", "_ondataavailable", "interval", "stop", "blob", "data", "uint8Array", "Uint8Array", "arrayBuffer", "isHeader", "wav", "slice", "warn", "timestamp", "Date", "now", "getSamples", "resource", "WaveFile", "DeferredTask", "Trigger", "LifecycleState", "Resource", "log", "trace", "Transcriber", "Resource", "_audioChunks", "_lastUsedTimestamp", "_openTrigger", "Trigger", "autoReset", "_config", "_recorder", "_onSegments", "_recording", "_transcribeTask", "undefined", "config", "recorder", "onSegments", "_open", "ctx", "log", "info", "setOnChunk", "chunk", "_saveAudioChunk", "start", "DeferredTask", "_transcribe", "wake", "_close", "stop", "startChunksRecording", "_lifecycleState", "LifecycleState", "OPEN", "stopChunksRecording", "schedule", "push", "scheduled", "length", "prefixBufferChunksAmount", "_dropOldChunks", "transcribeAfterChunksAmount", "chunks", "audio", "_mergeAudioChunks", "segments", "_fetchTranscription", "Array", "isArray", "alignedSegments", "_alignSegments", "slice", "file", "WaveFile", "wavConfig", "fromScratch", "channels", "sampleRate", "bitDepthCode", "mergeFloat64Arrays", "map", "data", "toBase64", "Error", "response", "fetch", "TRANSCRIPTION_URL", "method", "body", "JSON", "stringify", "headers", "ok", "statusText", "json", "string", "text", "join", "originalChunks", "zeroTimestamp", "at", "timestamp", "filteredSegments", "filter", "segment", "end", "words", "word", "_tag", "started", "Date", "toISOString", "trim", "span", "showInBrowserTimeline", "Atom", "synchronized", "Resource", "Obj", "Message", "RECORD_INTERVAL", "PREFIXED_CHUNKS_AMOUNT", "TRANSCRIBE_AFTER_CHUNKS_AMOUNT", "TranscriptionManager", "Resource", "_edgeClient", "_messageEnricher", "_registry", "_audioStreamTrack", "undefined", "_identityDid", "_mediaRecorder", "_transcriber", "_queue", "_enabledAtom", "Atom", "make", "options", "edgeClient", "messageEnricher", "registry", "enabled", "getEnabled", "get", "setQueue", "queue", "setIdentityDid", "did", "setRecording", "recording", "isOpen", "startChunksRecording", "stopChunksRecording", "setEnabled", "set", "_maybeRestartTranscriber", "_stopTranscriber", "setAudioTrack", "track", "_open", "_close", "needReinit", "mediaStreamTrack", "MediaStreamRecorder", "config", "interval", "close", "Transcriber", "transcribeAfterChunksAmount", "prefixBufferChunksAmount", "recorder", "onSegments", "segments", "_onSegments", "open", "block", "Obj", "Message", "created", "Date", "toISOString", "blocks", "sender", "identityDid", "append"]
|
|
7
|
+
}
|