@dxos/plugin-transcription 0.8.4-main.7ace549 → 0.8.4-main.8baae0fced
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/LICENSE +102 -5
- package/README.md +1 -1
- package/dist/lib/neutral/TranscriptionArticle-L6XANBH5.mjs +54 -0
- package/dist/lib/neutral/TranscriptionArticle-L6XANBH5.mjs.map +7 -0
- package/dist/lib/neutral/TranscriptionPlugin.mjs +34 -0
- package/dist/lib/neutral/TranscriptionPlugin.mjs.map +7 -0
- package/dist/lib/neutral/TranscriptionPlugin.node.mjs +25 -0
- package/dist/lib/neutral/TranscriptionPlugin.node.mjs.map +7 -0
- package/dist/lib/neutral/TranscriptionPlugin.workerd.mjs +21 -0
- package/dist/lib/neutral/TranscriptionPlugin.workerd.mjs.map +7 -0
- package/dist/lib/neutral/blueprint-definition-HOXDG5QP.mjs +15 -0
- package/dist/lib/neutral/blueprint-definition-HOXDG5QP.mjs.map +7 -0
- package/dist/lib/neutral/blueprints/index.mjs +8 -0
- package/dist/lib/neutral/capabilities/index.mjs +17 -0
- package/dist/lib/neutral/capabilities/index.mjs.map +7 -0
- package/dist/lib/neutral/chunk-2O3ONPRZ.mjs +298 -0
- package/dist/lib/neutral/chunk-2O3ONPRZ.mjs.map +7 -0
- package/dist/lib/neutral/chunk-5FXU36PN.mjs +120 -0
- package/dist/lib/neutral/chunk-5FXU36PN.mjs.map +7 -0
- package/dist/lib/{browser/chunk-7GNN7E3U.mjs → neutral/chunk-ILSA3DU7.mjs} +100 -131
- package/dist/lib/neutral/chunk-ILSA3DU7.mjs.map +7 -0
- package/dist/lib/neutral/chunk-J5LGTIGS.mjs +10 -0
- package/dist/lib/neutral/chunk-KAEXRX3Y.mjs +35 -0
- package/dist/lib/neutral/chunk-KAEXRX3Y.mjs.map +7 -0
- package/dist/lib/neutral/chunk-MLRJWAQH.mjs +179 -0
- package/dist/lib/neutral/chunk-MLRJWAQH.mjs.map +7 -0
- package/dist/lib/neutral/chunk-Y5EQAFFR.mjs +8 -0
- package/dist/lib/neutral/chunk-Y5EQAFFR.mjs.map +7 -0
- package/dist/lib/neutral/chunk-ZR4BH4QQ.mjs +30 -0
- package/dist/lib/neutral/chunk-ZR4BH4QQ.mjs.map +7 -0
- package/dist/lib/{browser/chunk-VBUIO677.mjs → neutral/chunk-ZWOWQAFX.mjs} +3 -9
- package/dist/lib/neutral/chunk-ZWOWQAFX.mjs.map +7 -0
- package/dist/lib/neutral/components/index.mjs +272 -0
- package/dist/lib/neutral/components/index.mjs.map +7 -0
- package/dist/lib/neutral/containers/index.mjs +9 -0
- package/dist/lib/neutral/containers/index.mjs.map +7 -0
- package/dist/lib/neutral/create-RRWRIUSR.mjs +21 -0
- package/dist/lib/neutral/create-RRWRIUSR.mjs.map +7 -0
- package/dist/lib/neutral/hooks/index.mjs +19 -0
- package/dist/lib/neutral/index.mjs +44 -0
- package/dist/lib/neutral/meta.json +1 -0
- package/dist/lib/neutral/meta.mjs +8 -0
- package/dist/lib/neutral/meta.mjs.map +7 -0
- package/dist/lib/neutral/open-CVMX5KXZ.mjs +27 -0
- package/dist/lib/neutral/open-CVMX5KXZ.mjs.map +7 -0
- package/dist/lib/neutral/operation-handler-NXMOAXFP.mjs +13 -0
- package/dist/lib/neutral/operation-handler-NXMOAXFP.mjs.map +7 -0
- package/dist/lib/neutral/operations/index.mjs +8 -0
- package/dist/lib/neutral/operations/index.mjs.map +7 -0
- package/dist/lib/neutral/plugin.mjs +16 -0
- package/dist/lib/neutral/plugin.mjs.map +7 -0
- package/dist/lib/neutral/react-surface-YMZRO242.mjs +26 -0
- package/dist/lib/neutral/react-surface-YMZRO242.mjs.map +7 -0
- package/dist/lib/neutral/summarize-LA7TRW7A.mjs +78 -0
- package/dist/lib/neutral/summarize-LA7TRW7A.mjs.map +7 -0
- package/dist/lib/neutral/text-content-F4ASMITB.mjs +30 -0
- package/dist/lib/neutral/text-content-F4ASMITB.mjs.map +7 -0
- package/dist/lib/{node-esm/transcriber-CPD3FZ7M.mjs → neutral/transcriber-ABHATBVH.mjs} +20 -18
- package/dist/lib/neutral/transcriber-ABHATBVH.mjs.map +7 -0
- package/dist/lib/neutral/translations.mjs +24 -0
- package/dist/lib/neutral/translations.mjs.map +7 -0
- package/dist/lib/neutral/types/index.mjs +10 -0
- package/dist/lib/neutral/types/index.mjs.map +7 -0
- package/dist/types/src/TranscriptionPlugin.d.ts +3 -1
- package/dist/types/src/TranscriptionPlugin.d.ts.map +1 -1
- package/dist/types/src/TranscriptionPlugin.node.d.ts +4 -0
- package/dist/types/src/TranscriptionPlugin.node.d.ts.map +1 -0
- package/dist/types/src/TranscriptionPlugin.test.d.ts +2 -0
- package/dist/types/src/TranscriptionPlugin.test.d.ts.map +1 -0
- package/dist/types/src/TranscriptionPlugin.workerd.d.ts +4 -0
- package/dist/types/src/TranscriptionPlugin.workerd.d.ts.map +1 -0
- 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 +4 -0
- package/dist/types/src/blueprints/transcription-blueprint.d.ts.map +1 -0
- package/dist/types/src/capabilities/blueprint-definition.d.ts +5 -4
- package/dist/types/src/capabilities/blueprint-definition.d.ts.map +1 -1
- package/dist/types/src/capabilities/index.d.ts +10 -5
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/operation-handler.d.ts +6 -0
- package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface.d.ts +3 -2
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/capabilities/text-content.d.ts +8 -0
- package/dist/types/src/capabilities/text-content.d.ts.map +1 -0
- package/dist/types/src/capabilities/transcriber.d.ts +4 -3
- package/dist/types/src/capabilities/transcriber.d.ts.map +1 -1
- package/dist/types/src/components/Oracle/Oracle.d.ts +24 -0
- package/dist/types/src/components/Oracle/Oracle.d.ts.map +1 -0
- package/dist/types/src/components/Oracle/Oracle.stories.d.ts +32 -0
- package/dist/types/src/components/Oracle/Oracle.stories.d.ts.map +1 -0
- package/dist/types/src/components/Oracle/index.d.ts +2 -0
- package/dist/types/src/components/Oracle/index.d.ts.map +1 -0
- package/dist/types/src/components/Transcription/Transcription.d.ts +13 -0
- package/dist/types/src/components/Transcription/Transcription.d.ts.map +1 -0
- package/dist/types/src/components/Transcription/Transcription.stories.d.ts +37 -0
- package/dist/types/src/components/Transcription/Transcription.stories.d.ts.map +1 -0
- package/dist/types/src/components/Transcription/index.d.ts +2 -0
- package/dist/types/src/components/Transcription/index.d.ts.map +1 -0
- package/dist/types/src/components/{Transcript/transcript-extension.d.ts → Transcription/transcription-extension.d.ts} +3 -3
- package/dist/types/src/components/Transcription/transcription-extension.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +2 -3
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/containers/TranscriptionArticle/TranscriptionArticle.d.ts +6 -0
- package/dist/types/src/containers/TranscriptionArticle/TranscriptionArticle.d.ts.map +1 -0
- package/dist/types/src/containers/TranscriptionArticle/TranscriptionArticle.stories.d.ts +28 -0
- package/dist/types/src/containers/TranscriptionArticle/TranscriptionArticle.stories.d.ts.map +1 -0
- package/dist/types/src/containers/TranscriptionArticle/index.d.ts +2 -0
- package/dist/types/src/containers/TranscriptionArticle/index.d.ts.map +1 -0
- package/dist/types/src/containers/index.d.ts +3 -0
- package/dist/types/src/containers/index.d.ts.map +1 -0
- package/dist/types/src/enrichment/conversation.test.d.ts +2 -0
- package/dist/types/src/enrichment/conversation.test.d.ts.map +1 -0
- package/dist/types/src/enrichment/operations.d.ts +200 -0
- package/dist/types/src/enrichment/operations.d.ts.map +1 -0
- package/dist/types/src/enrichment/parser.d.ts +26 -0
- package/dist/types/src/enrichment/parser.d.ts.map +1 -0
- package/dist/types/src/enrichment/stream-simulator.d.ts +38 -0
- package/dist/types/src/enrichment/stream-simulator.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +2 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useAudioFile.d.ts.map +1 -1
- package/dist/types/src/hooks/useAudioTrack.d.ts.map +1 -1
- package/dist/types/src/hooks/useFeedModelAdapter.d.ts +12 -0
- package/dist/types/src/hooks/useFeedModelAdapter.d.ts.map +1 -0
- package/dist/types/src/hooks/useTranscriber.d.ts +2 -2
- package/dist/types/src/hooks/useTranscriber.d.ts.map +1 -1
- package/dist/types/src/hooks/useTranscriptionRecording.d.ts +12 -0
- package/dist/types/src/hooks/useTranscriptionRecording.d.ts.map +1 -0
- package/dist/types/src/hooks/useVoiceInput.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +2 -3
- 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/model/model.d.ts +2 -2
- package/dist/types/src/model/model.d.ts.map +1 -1
- package/dist/types/src/{segments-normalization → normalization}/index.d.ts +1 -1
- package/dist/types/src/normalization/index.d.ts.map +1 -0
- package/dist/types/src/{segments-normalization → normalization}/message-normalizer.d.ts +8 -6
- package/dist/types/src/normalization/message-normalizer.d.ts.map +1 -0
- package/dist/types/src/normalization/normalization.d.ts +549 -0
- package/dist/types/src/normalization/normalization.d.ts.map +1 -0
- package/dist/types/src/normalization/normalization.test.d.ts.map +1 -0
- package/dist/types/src/normalization/utils.d.ts.map +1 -0
- package/dist/types/src/operations/create.d.ts +5 -0
- package/dist/types/src/operations/create.d.ts.map +1 -0
- package/dist/types/src/operations/index.d.ts +3 -0
- package/dist/types/src/operations/index.d.ts.map +1 -0
- package/dist/types/src/operations/open.d.ts +5 -0
- package/dist/types/src/operations/open.d.ts.map +1 -0
- package/dist/types/src/operations/summarize.d.ts +8 -0
- package/dist/types/src/operations/summarize.d.ts.map +1 -0
- package/dist/types/src/plugin.d.ts +4 -0
- package/dist/types/src/plugin.d.ts.map +1 -0
- package/dist/types/src/stories/FileTranscription.stories.d.ts +20 -0
- package/dist/types/src/stories/FileTranscription.stories.d.ts.map +1 -0
- package/dist/types/src/{components/stories → stories}/KeyWordRecognition.stories.d.ts +2 -2
- package/dist/types/src/stories/KeyWordRecognition.stories.d.ts.map +1 -0
- package/dist/types/src/{components/stories/MicrophoneTranscription.stories.d.ts → stories/LiveTranscription.stories.d.ts} +7 -7
- package/dist/types/src/stories/LiveTranscription.stories.d.ts.map +1 -0
- package/dist/types/src/stories/TranscriptionStory.d.ts +21 -0
- package/dist/types/src/stories/TranscriptionStory.d.ts.map +1 -0
- package/dist/types/src/stories/common.d.ts +46 -0
- package/dist/types/src/stories/common.d.ts.map +1 -0
- package/dist/types/src/testing/testing.d.ts +9 -10
- 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 +2 -2
- package/dist/types/src/transcriber/media-stream-recorder.d.ts.map +1 -1
- package/dist/types/src/transcriber/transcriber.d.ts +59 -4
- package/dist/types/src/transcriber/transcriber.d.ts.map +1 -1
- package/dist/types/src/transcriber/transcriber.test.d.ts +2 -0
- package/dist/types/src/transcriber/transcriber.test.d.ts.map +1 -0
- package/dist/types/src/transcriber/transcription-manager.d.ts +12 -7
- package/dist/types/src/transcriber/transcription-manager.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +9 -8
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/TranscriptOperation.d.ts +927 -0
- package/dist/types/src/types/TranscriptOperation.d.ts.map +1 -0
- package/dist/types/src/types/TranscriptionCapabilities.d.ts +17 -0
- package/dist/types/src/types/TranscriptionCapabilities.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +2 -2
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/util/array.d.ts.map +1 -1
- package/dist/types/src/util/get-time-str.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/monitor-audio-level.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 +157 -84
- package/src/TranscriptionPlugin.node.ts +20 -0
- package/src/TranscriptionPlugin.test.ts +31 -0
- package/src/TranscriptionPlugin.tsx +20 -63
- package/src/TranscriptionPlugin.workerd.ts +18 -0
- package/src/blueprints/index.ts +5 -0
- package/src/blueprints/transcription-blueprint.ts +29 -0
- package/src/capabilities/blueprint-definition.ts +12 -24
- package/src/capabilities/index.ts +11 -7
- package/src/capabilities/operation-handler.ts +16 -0
- package/src/capabilities/react-surface.tsx +22 -13
- package/src/capabilities/text-content.ts +33 -0
- package/src/capabilities/transcriber.ts +53 -42
- package/src/components/Oracle/Oracle.stories.tsx +147 -0
- package/src/components/Oracle/Oracle.tsx +141 -0
- package/src/components/Oracle/index.ts +5 -0
- package/src/components/Transcription/Transcription.stories.tsx +213 -0
- package/src/components/Transcription/Transcription.tsx +58 -0
- package/src/components/{Transcript → Transcription}/index.ts +1 -1
- package/src/components/{Transcript/transcript-extension.ts → Transcription/transcription-extension.ts} +4 -4
- package/src/components/index.ts +2 -6
- package/src/containers/TranscriptionArticle/TranscriptionArticle.stories.tsx +61 -0
- package/src/containers/TranscriptionArticle/TranscriptionArticle.tsx +62 -0
- package/src/containers/TranscriptionArticle/index.ts +5 -0
- package/src/containers/index.ts +7 -0
- package/src/enrichment/conversation.test.ts +162 -0
- package/src/enrichment/conversation.txt +23 -0
- package/src/enrichment/operations.ts +268 -0
- package/src/enrichment/parser.ts +101 -0
- package/src/enrichment/stream-simulator.ts +125 -0
- package/src/hooks/index.ts +2 -1
- package/src/hooks/useFeedModelAdapter.ts +46 -0
- package/src/hooks/useTranscriber.ts +6 -3
- package/src/hooks/useTranscriptionRecording.ts +87 -0
- package/src/hooks/useVoiceInput.ts +2 -3
- package/src/index.ts +4 -5
- package/src/meta.ts +4 -3
- package/src/model/model.test.ts +9 -3
- package/src/model/model.ts +3 -3
- package/src/{segments-normalization → normalization}/message-normalizer.ts +34 -21
- package/src/{segments-normalization → normalization}/normalization.test.ts +4 -43
- package/src/normalization/normalization.ts +76 -0
- package/src/operations/create.ts +24 -0
- package/src/operations/index.ts +11 -0
- package/src/operations/open.ts +28 -0
- package/src/operations/summarize.ts +101 -0
- package/src/plugin.ts +11 -0
- package/src/stories/FileTranscription.stories.tsx +143 -0
- package/src/{components/stories → stories}/KeyWordRecognition.stories.tsx +40 -40
- package/src/stories/LiveTranscription.stories.tsx +153 -0
- package/src/stories/TranscriptionStory.tsx +101 -0
- package/src/stories/common.ts +233 -0
- package/src/testing/testing.ts +35 -47
- package/src/transcriber/index.ts +1 -1
- package/src/transcriber/media-stream-recorder.ts +3 -3
- package/src/transcriber/transcriber.browser.test.ts +1 -2
- package/src/transcriber/transcriber.test.ts +104 -0
- package/src/transcriber/transcriber.ts +102 -57
- package/src/transcriber/transcription-manager.ts +29 -18
- package/src/translations.ts +10 -7
- package/src/types/TranscriptOperation.ts +103 -0
- package/src/types/TranscriptionCapabilities.ts +39 -0
- package/src/types/index.ts +2 -2
- package/src/util/index.ts +1 -0
- package/src/util/render-byline.ts +33 -0
- package/dist/lib/browser/TranscriptContainer-OQFBAGSP.mjs +0 -11
- package/dist/lib/browser/blueprint-definition-GZ7NOODS.mjs +0 -147
- package/dist/lib/browser/blueprint-definition-GZ7NOODS.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-7GNN7E3U.mjs.map +0 -7
- package/dist/lib/browser/chunk-C5YV3JZF.mjs +0 -738
- package/dist/lib/browser/chunk-C5YV3JZF.mjs.map +0 -7
- package/dist/lib/browser/chunk-O33THH53.mjs +0 -8
- package/dist/lib/browser/chunk-O33THH53.mjs.map +0 -7
- package/dist/lib/browser/chunk-QOSZIUE2.mjs +0 -32
- package/dist/lib/browser/chunk-QOSZIUE2.mjs.map +0 -7
- package/dist/lib/browser/chunk-VBUIO677.mjs.map +0 -7
- package/dist/lib/browser/index.mjs +0 -128
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-5CGCLOXB.mjs +0 -25
- package/dist/lib/browser/intent-resolver-5CGCLOXB.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/browser/react-surface-OK55WK7J.mjs +0 -32
- package/dist/lib/browser/react-surface-OK55WK7J.mjs.map +0 -7
- package/dist/lib/browser/transcriber-6YDM5ZDT.mjs +0 -56
- package/dist/lib/browser/transcriber-6YDM5ZDT.mjs.map +0 -7
- package/dist/lib/browser/types/index.mjs +0 -10
- package/dist/lib/node-esm/TranscriptContainer-GM47P6WH.mjs +0 -12
- package/dist/lib/node-esm/blueprint-definition-GAHQBYTF.mjs +0 -148
- package/dist/lib/node-esm/blueprint-definition-GAHQBYTF.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-5JN2MHYA.mjs +0 -467
- package/dist/lib/node-esm/chunk-5JN2MHYA.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-IKGUNN3Z.mjs +0 -739
- package/dist/lib/node-esm/chunk-IKGUNN3Z.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-SSYFSLB7.mjs +0 -10
- package/dist/lib/node-esm/chunk-SSYFSLB7.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-U4YPUD2F.mjs +0 -33
- package/dist/lib/node-esm/chunk-U4YPUD2F.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/index.mjs +0 -129
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/intent-resolver-4H4CXIAL.mjs +0 -26
- package/dist/lib/node-esm/intent-resolver-4H4CXIAL.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/react-surface-EK6K2MMD.mjs +0 -33
- package/dist/lib/node-esm/react-surface-EK6K2MMD.mjs.map +0 -7
- package/dist/lib/node-esm/transcriber-CPD3FZ7M.mjs.map +0 -7
- package/dist/lib/node-esm/types/index.mjs +0 -11
- 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/components/Transcript/Transcript.d.ts +0 -19
- package/dist/types/src/components/Transcript/Transcript.d.ts.map +0 -1
- package/dist/types/src/components/Transcript/Transcript.stories.d.ts +0 -39
- package/dist/types/src/components/Transcript/Transcript.stories.d.ts.map +0 -1
- package/dist/types/src/components/Transcript/deprecated/OldTranscript.d.ts +0 -28
- package/dist/types/src/components/Transcript/deprecated/OldTranscript.d.ts.map +0 -1
- package/dist/types/src/components/Transcript/index.d.ts +0 -2
- package/dist/types/src/components/Transcript/index.d.ts.map +0 -1
- package/dist/types/src/components/Transcript/transcript-extension.d.ts.map +0 -1
- package/dist/types/src/components/TranscriptContainer.d.ts +0 -9
- package/dist/types/src/components/TranscriptContainer.d.ts.map +0 -1
- package/dist/types/src/components/stories/FileTranscription.stories.d.ts +0 -18
- package/dist/types/src/components/stories/FileTranscription.stories.d.ts.map +0 -1
- package/dist/types/src/components/stories/KeyWordRecognition.stories.d.ts.map +0 -1
- package/dist/types/src/components/stories/MicrophoneTranscription.stories.d.ts.map +0 -1
- package/dist/types/src/components/stories/TranscriptionStory.d.ts +0 -12
- package/dist/types/src/components/stories/TranscriptionStory.d.ts.map +0 -1
- package/dist/types/src/components/stories/useIsSpeaking.d.ts +0 -3
- package/dist/types/src/components/stories/useIsSpeaking.d.ts.map +0 -1
- package/dist/types/src/functions/index.d.ts +0 -3
- package/dist/types/src/functions/index.d.ts.map +0 -1
- package/dist/types/src/functions/open.d.ts +0 -7
- package/dist/types/src/functions/open.d.ts.map +0 -1
- package/dist/types/src/functions/summarize.d.ts +0 -11
- package/dist/types/src/functions/summarize.d.ts.map +0 -1
- package/dist/types/src/hooks/useQueueModelAdapter.d.ts +0 -8
- package/dist/types/src/hooks/useQueueModelAdapter.d.ts.map +0 -1
- package/dist/types/src/segments-normalization/index.d.ts.map +0 -1
- package/dist/types/src/segments-normalization/message-normalizer.d.ts.map +0 -1
- package/dist/types/src/segments-normalization/normalization.d.ts +0 -461
- package/dist/types/src/segments-normalization/normalization.d.ts.map +0 -1
- package/dist/types/src/segments-normalization/normalization.test.d.ts.map +0 -1
- package/dist/types/src/segments-normalization/utils.d.ts.map +0 -1
- package/dist/types/src/types/TranscriptAction.d.ts +0 -23
- package/dist/types/src/types/TranscriptAction.d.ts.map +0 -1
- package/dist/types/src/types/types.d.ts +0 -5
- package/dist/types/src/types/types.d.ts.map +0 -1
- package/src/capabilities/capabilities.ts +0 -33
- package/src/capabilities/intent-resolver.ts +0 -19
- package/src/components/Transcript/Transcript.stories.tsx +0 -245
- package/src/components/Transcript/Transcript.tsx +0 -93
- package/src/components/Transcript/deprecated/OldTranscript.tsx +0 -260
- package/src/components/TranscriptContainer.tsx +0 -36
- package/src/components/stories/FileTranscription.stories.tsx +0 -257
- package/src/components/stories/MicrophoneTranscription.stories.tsx +0 -288
- package/src/components/stories/TranscriptionStory.tsx +0 -44
- package/src/components/stories/useIsSpeaking.tsx +0 -40
- package/src/functions/index.ts +0 -6
- package/src/functions/open.ts +0 -38
- package/src/functions/summarize.ts +0 -103
- package/src/hooks/useQueueModelAdapter.ts +0 -66
- package/src/segments-normalization/normalization.ts +0 -115
- package/src/types/TranscriptAction.ts +0 -23
- package/src/types/types.ts +0 -9
- package/dist/lib/{browser/types → neutral/blueprints}/index.mjs.map +0 -0
- package/dist/lib/{browser/TranscriptContainer-OQFBAGSP.mjs.map → neutral/chunk-J5LGTIGS.mjs.map} +0 -0
- package/dist/lib/{node-esm/types → neutral/hooks}/index.mjs.map +0 -0
- package/dist/lib/{node-esm/TranscriptContainer-GM47P6WH.mjs.map → neutral/index.mjs.map} +0 -0
- package/dist/types/src/{segments-normalization → normalization}/normalization.test.d.ts +0 -0
- package/dist/types/src/{segments-normalization → normalization}/utils.d.ts +0 -0
- package/src/{segments-normalization → normalization}/index.ts +1 -1
- /package/src/{segments-normalization → normalization}/utils.ts +0 -0
|
@@ -19,7 +19,7 @@ const initializeExtendableMediaRecorder = async () => {
|
|
|
19
19
|
await register(await connect());
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
export type
|
|
22
|
+
export type MediaStreamRecorderProps = {
|
|
23
23
|
mediaStreamTrack: MediaStreamTrack;
|
|
24
24
|
config: {
|
|
25
25
|
interval: number;
|
|
@@ -37,12 +37,12 @@ export class MediaStreamRecorder implements AudioRecorder {
|
|
|
37
37
|
/**
|
|
38
38
|
* Default MediaRecorder implementation do not support wav encoding.
|
|
39
39
|
*/
|
|
40
|
-
private readonly _config:
|
|
40
|
+
private readonly _config: MediaStreamRecorderProps['config'];
|
|
41
41
|
private _mediaRecorder?: IMediaRecorder = undefined;
|
|
42
42
|
private _header?: Uint8Array = undefined;
|
|
43
43
|
private _onChunk?: (chunk: AudioChunk) => void;
|
|
44
44
|
|
|
45
|
-
constructor({ mediaStreamTrack, config }:
|
|
45
|
+
constructor({ mediaStreamTrack, config }: MediaStreamRecorderProps) {
|
|
46
46
|
this._mediaStreamTrack = mediaStreamTrack;
|
|
47
47
|
this._config = config;
|
|
48
48
|
}
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
import fs from 'node:fs';
|
|
6
6
|
import path from 'node:path';
|
|
7
|
-
|
|
8
7
|
import { describe, expect, test } from 'vitest';
|
|
9
8
|
import { WaveFile } from 'wavefile';
|
|
10
9
|
|
|
@@ -213,7 +212,7 @@ class MockAudioRecorder implements AudioRecorder {
|
|
|
213
212
|
|
|
214
213
|
@trace.span()
|
|
215
214
|
async start(): Promise<void> {
|
|
216
|
-
log.info('start mock audio recorder', {
|
|
215
|
+
log.info('start mock audio recorder', { wavProps: this.wav.fmt });
|
|
217
216
|
const now = Date.now();
|
|
218
217
|
const samples = this.wav.getSamples();
|
|
219
218
|
const sampleRate = this.wavConfig.sampleRate;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, test } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import { type AudioChunk } from './audio-recorder';
|
|
8
|
+
import { alignWhisperSegments, type WhisperSegment } from './transcriber';
|
|
9
|
+
|
|
10
|
+
const T0 = Date.parse('2026-01-01T00:00:00.000Z');
|
|
11
|
+
|
|
12
|
+
const chunk = (offsetMs = 0, samples = 16): AudioChunk => ({
|
|
13
|
+
timestamp: T0 + offsetMs,
|
|
14
|
+
data: new Float64Array(samples),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const segment = (overrides: Partial<WhisperSegment>): WhisperSegment => ({
|
|
18
|
+
text: '',
|
|
19
|
+
start: 0,
|
|
20
|
+
end: 0,
|
|
21
|
+
no_speech_prob: 0,
|
|
22
|
+
words: [],
|
|
23
|
+
...overrides,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe('alignWhisperSegments', () => {
|
|
27
|
+
test('returns empty when no chunks were transcribed', ({ expect }) => {
|
|
28
|
+
const result = alignWhisperSegments(
|
|
29
|
+
[segment({ text: 'x', end: 1, words: [{ word: 'x', start: 0, end: 1 }] })],
|
|
30
|
+
[],
|
|
31
|
+
0,
|
|
32
|
+
);
|
|
33
|
+
expect(result.transcripts).toEqual([]);
|
|
34
|
+
expect(result.lastTimestamp).toBeUndefined();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('absolute-timestamps and deduplicates segments against lastTimestamp', ({ expect }) => {
|
|
38
|
+
const segments: WhisperSegment[] = [
|
|
39
|
+
segment({
|
|
40
|
+
text: 'hello world',
|
|
41
|
+
start: 0,
|
|
42
|
+
end: 1,
|
|
43
|
+
words: [
|
|
44
|
+
{ word: 'hello ', start: 0, end: 0.5 },
|
|
45
|
+
{ word: 'world', start: 0.5, end: 1 },
|
|
46
|
+
],
|
|
47
|
+
}),
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
const first = alignWhisperSegments(segments, [chunk(0)], 0);
|
|
51
|
+
expect(first.transcripts).toHaveLength(1);
|
|
52
|
+
expect(first.transcripts[0]._tag).toBe('transcript');
|
|
53
|
+
expect(first.transcripts[0].text).toBe('hello world');
|
|
54
|
+
expect(new Date(first.transcripts[0].started).getTime()).toBe(T0);
|
|
55
|
+
expect(first.lastTimestamp).toBe(T0 + 1_000);
|
|
56
|
+
|
|
57
|
+
// Same segments, same chunk start: every word's absolute start is < lastTimestamp -> filtered out.
|
|
58
|
+
const second = alignWhisperSegments(segments, [chunk(0)], first.lastTimestamp!);
|
|
59
|
+
expect(second.transcripts).toEqual([]);
|
|
60
|
+
expect(second.lastTimestamp).toBeUndefined();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test('keeps later words when earlier words fall before lastTimestamp', ({ expect }) => {
|
|
64
|
+
const segments: WhisperSegment[] = [
|
|
65
|
+
segment({
|
|
66
|
+
text: 'old new',
|
|
67
|
+
start: 0,
|
|
68
|
+
end: 2,
|
|
69
|
+
words: [
|
|
70
|
+
{ word: 'old ', start: 0, end: 1 },
|
|
71
|
+
{ word: 'new', start: 1.5, end: 2 },
|
|
72
|
+
],
|
|
73
|
+
}),
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
// First word starts at T0, second at T0+1500 — only the second survives a cursor at T0+1000.
|
|
77
|
+
const result = alignWhisperSegments(segments, [chunk(0)], T0 + 1_000);
|
|
78
|
+
expect(result.transcripts).toHaveLength(1);
|
|
79
|
+
expect(result.transcripts[0].text).toBe('new');
|
|
80
|
+
expect(new Date(result.transcripts[0].started).getTime()).toBe(T0 + 1_500);
|
|
81
|
+
expect(result.lastTimestamp).toBe(T0 + 2_000);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('drops segments that end before lastTimestamp', ({ expect }) => {
|
|
85
|
+
const segments: WhisperSegment[] = [
|
|
86
|
+
segment({
|
|
87
|
+
text: 'stale',
|
|
88
|
+
start: 0,
|
|
89
|
+
end: 0.5,
|
|
90
|
+
words: [{ word: 'stale', start: 0, end: 0.5 }],
|
|
91
|
+
}),
|
|
92
|
+
segment({
|
|
93
|
+
text: 'fresh',
|
|
94
|
+
start: 1,
|
|
95
|
+
end: 2,
|
|
96
|
+
words: [{ word: 'fresh', start: 1.5, end: 2 }],
|
|
97
|
+
}),
|
|
98
|
+
];
|
|
99
|
+
|
|
100
|
+
const result = alignWhisperSegments(segments, [chunk(0)], T0 + 1_000);
|
|
101
|
+
expect(result.transcripts).toHaveLength(1);
|
|
102
|
+
expect(result.transcripts[0].text).toBe('fresh');
|
|
103
|
+
});
|
|
104
|
+
});
|
|
@@ -10,12 +10,15 @@ import { log } from '@dxos/log';
|
|
|
10
10
|
import { trace } from '@dxos/tracing';
|
|
11
11
|
import { type ContentBlock } from '@dxos/types';
|
|
12
12
|
|
|
13
|
-
import { TRANSCRIPTION_URL } from '../types';
|
|
14
13
|
import { mergeFloat64Arrays } from '../util';
|
|
15
|
-
|
|
16
14
|
import { type AudioChunk, type AudioRecorder } from './audio-recorder';
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Endpoint to the calls service.
|
|
18
|
+
*/
|
|
19
|
+
const DEFAULT_TRANSCRIPTION_URL = 'https://calls-service.dxos.workers.dev';
|
|
20
|
+
|
|
21
|
+
export type WhisperWord = {
|
|
19
22
|
word: string;
|
|
20
23
|
|
|
21
24
|
/**
|
|
@@ -29,7 +32,7 @@ type WhisperWord = {
|
|
|
29
32
|
end: number;
|
|
30
33
|
};
|
|
31
34
|
|
|
32
|
-
type WhisperSegment = {
|
|
35
|
+
export type WhisperSegment = {
|
|
33
36
|
text: string;
|
|
34
37
|
|
|
35
38
|
/**
|
|
@@ -61,9 +64,21 @@ export type TranscribeConfig = {
|
|
|
61
64
|
* This is needed to catch the beginning of the user's speech.
|
|
62
65
|
*/
|
|
63
66
|
prefixBufferChunksAmount: number;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Override the transcription endpoint base URL.
|
|
70
|
+
* Defaults to the DXOS calls service.
|
|
71
|
+
*/
|
|
72
|
+
endpoint?: string;
|
|
64
73
|
};
|
|
65
74
|
|
|
66
|
-
|
|
75
|
+
/**
|
|
76
|
+
* Function that converts a base64-encoded WAV payload into Whisper segments.
|
|
77
|
+
* Allows callers to swap in alternative providers or mock the transport.
|
|
78
|
+
*/
|
|
79
|
+
export type TranscribeFn = (audio: string) => Promise<WhisperSegment[]>;
|
|
80
|
+
|
|
81
|
+
export type TranscriberProps = {
|
|
67
82
|
config: TranscribeConfig;
|
|
68
83
|
recorder: AudioRecorder;
|
|
69
84
|
/**
|
|
@@ -71,6 +86,10 @@ export type TranscriberParams = {
|
|
|
71
86
|
* @param segments - The transcribed segments.
|
|
72
87
|
*/
|
|
73
88
|
onSegments: (segments: ContentBlock.Transcript[]) => Promise<void>;
|
|
89
|
+
/**
|
|
90
|
+
* Optional override of the transcription transport. When provided, supersedes `config.endpoint`.
|
|
91
|
+
*/
|
|
92
|
+
transcribe?: TranscribeFn;
|
|
74
93
|
};
|
|
75
94
|
|
|
76
95
|
/**
|
|
@@ -80,22 +99,24 @@ export type TranscriberParams = {
|
|
|
80
99
|
*/
|
|
81
100
|
export class Transcriber extends Resource {
|
|
82
101
|
private _audioChunks: AudioChunk[] = [];
|
|
83
|
-
private
|
|
102
|
+
private _lastTimestamp = 0;
|
|
84
103
|
|
|
85
104
|
private readonly _openTrigger = new Trigger({ autoReset: true });
|
|
86
105
|
|
|
87
106
|
private readonly _config: TranscribeConfig;
|
|
88
107
|
private readonly _recorder: AudioRecorder;
|
|
89
|
-
private readonly _onSegments:
|
|
108
|
+
private readonly _onSegments: TranscriberProps['onSegments'];
|
|
109
|
+
private readonly _transcribeFn?: TranscribeFn;
|
|
90
110
|
|
|
91
111
|
private _recording = false;
|
|
92
112
|
private _transcribeTask?: DeferredTask = undefined;
|
|
93
113
|
|
|
94
|
-
constructor({ config, recorder, onSegments }:
|
|
114
|
+
constructor({ config, recorder, onSegments, transcribe }: TranscriberProps) {
|
|
95
115
|
super();
|
|
96
116
|
this._config = config;
|
|
97
117
|
this._recorder = recorder;
|
|
98
118
|
this._onSegments = onSegments;
|
|
119
|
+
this._transcribeFn = transcribe;
|
|
99
120
|
}
|
|
100
121
|
|
|
101
122
|
protected override async _open(ctx: Context): Promise<void> {
|
|
@@ -192,67 +213,91 @@ export class Transcriber extends Resource {
|
|
|
192
213
|
@trace.span({ showInBrowserTimeline: true })
|
|
193
214
|
private async _fetchTranscription(audio: string): Promise<WhisperSegment[]> {
|
|
194
215
|
if (audio.length === 0) {
|
|
195
|
-
this._audioChunks = [];
|
|
196
216
|
throw new Error('No audio to send for transcribing');
|
|
197
217
|
}
|
|
198
218
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
219
|
+
let segments: unknown;
|
|
220
|
+
if (this._transcribeFn) {
|
|
221
|
+
segments = await this._transcribeFn(audio);
|
|
222
|
+
} else {
|
|
223
|
+
// TODO(burdon): Create separate endpoint?
|
|
224
|
+
const endpoint = this._config.endpoint ?? DEFAULT_TRANSCRIPTION_URL;
|
|
225
|
+
const response = await fetch(`${endpoint}/transcribe`, {
|
|
226
|
+
method: 'POST',
|
|
227
|
+
body: JSON.stringify({ audio }),
|
|
228
|
+
headers: {
|
|
229
|
+
'Content-Type': 'application/json',
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
if (!response.ok) {
|
|
234
|
+
throw new Error(`Transcription failed: ${response.statusText}`);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
({ segments } = (await response.json()) as { segments?: unknown });
|
|
210
238
|
}
|
|
211
239
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
log.info('transcription response', {
|
|
217
|
-
segments: segments.length,
|
|
218
|
-
string: segments.map((segments) => segments.text).join(' '),
|
|
219
|
-
});
|
|
240
|
+
if (!Array.isArray(segments)) {
|
|
241
|
+
throw new Error('Transcription response payload is invalid');
|
|
242
|
+
}
|
|
220
243
|
|
|
221
|
-
|
|
244
|
+
log.info('transcription response', { segments: segments.length });
|
|
245
|
+
return segments as WhisperSegment[];
|
|
222
246
|
}
|
|
223
247
|
|
|
224
248
|
private _alignSegments(segments: WhisperSegment[], originalChunks: AudioChunk[]): ContentBlock.Transcript[] {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const filteredSegments = segments
|
|
229
|
-
// Use segments that end after the last used timestamp.
|
|
230
|
-
// Segments could overlap, so we need to filter words that starts after the last used timestamp.
|
|
231
|
-
.filter((segment) => zeroTimestamp + segment.end * 1_000 >= this._lastUsedTimestamp)
|
|
232
|
-
// Use words that starts after the last used timestamp.
|
|
233
|
-
.map((segment) => {
|
|
234
|
-
const words = segment.words.filter((word) => zeroTimestamp + word.start * 1_000 >= this._lastUsedTimestamp);
|
|
235
|
-
return {
|
|
236
|
-
...segment,
|
|
237
|
-
words,
|
|
238
|
-
text: words.map((word) => word.word).join(''),
|
|
239
|
-
start: words.at(0)?.start ?? segment.end,
|
|
240
|
-
};
|
|
241
|
-
})
|
|
242
|
-
.filter((segment) => segment.words.length > 0);
|
|
243
|
-
|
|
244
|
-
if (filteredSegments.length === 0) {
|
|
245
|
-
return [];
|
|
249
|
+
const result = alignWhisperSegments(segments, originalChunks, this._lastTimestamp);
|
|
250
|
+
if (result.lastTimestamp !== undefined) {
|
|
251
|
+
this._lastTimestamp = result.lastTimestamp;
|
|
246
252
|
}
|
|
247
253
|
|
|
248
|
-
|
|
249
|
-
|
|
254
|
+
return result.transcripts;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Pure helper that filters and absolute-timestamps Whisper segments against a chunk timeline.
|
|
260
|
+
* Exported for testing.
|
|
261
|
+
*
|
|
262
|
+
* @param segments - Raw segments returned by the Whisper service for `originalChunks`.
|
|
263
|
+
* @param originalChunks - Chunks fed into the transcription request (used for the zero timestamp).
|
|
264
|
+
* @param lastTimestamp - Most recent absolute timestamp already emitted; segments whose end
|
|
265
|
+
* falls strictly before this point are deduped out, as are individual words whose start does.
|
|
266
|
+
*/
|
|
267
|
+
export const alignWhisperSegments = (
|
|
268
|
+
segments: WhisperSegment[],
|
|
269
|
+
originalChunks: AudioChunk[],
|
|
270
|
+
lastTimestamp: number,
|
|
271
|
+
): { transcripts: ContentBlock.Transcript[]; lastTimestamp?: number } => {
|
|
272
|
+
if (originalChunks.length === 0) {
|
|
273
|
+
return { transcripts: [] };
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const zeroTimestamp = originalChunks[0].timestamp;
|
|
277
|
+
|
|
278
|
+
const filteredSegments = segments
|
|
279
|
+
.filter((segment) => zeroTimestamp + segment.end * 1_000 >= lastTimestamp)
|
|
280
|
+
.map((segment) => {
|
|
281
|
+
const words = segment.words.filter((word) => zeroTimestamp + word.start * 1_000 >= lastTimestamp);
|
|
282
|
+
return {
|
|
283
|
+
...segment,
|
|
284
|
+
words,
|
|
285
|
+
text: words.map((word) => word.word).join(''),
|
|
286
|
+
start: words.at(0)?.start ?? segment.end,
|
|
287
|
+
};
|
|
288
|
+
})
|
|
289
|
+
.filter((segment) => segment.words.length > 0);
|
|
290
|
+
|
|
291
|
+
if (filteredSegments.length === 0) {
|
|
292
|
+
return { transcripts: [] };
|
|
293
|
+
}
|
|
250
294
|
|
|
251
|
-
|
|
252
|
-
|
|
295
|
+
return {
|
|
296
|
+
lastTimestamp: zeroTimestamp + filteredSegments.at(-1)!.end * 1_000,
|
|
297
|
+
transcripts: filteredSegments.map((segment) => ({
|
|
253
298
|
_tag: 'transcript',
|
|
254
299
|
started: new Date(zeroTimestamp + segment.start * 1_000).toISOString(),
|
|
255
300
|
text: segment.text.trim(),
|
|
256
|
-
}))
|
|
257
|
-
}
|
|
258
|
-
}
|
|
301
|
+
})),
|
|
302
|
+
};
|
|
303
|
+
};
|
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { Atom, type Registry } from '@effect-atom/atom-react';
|
|
6
|
+
import * as Effect from 'effect/Effect';
|
|
7
|
+
import * as Layer from 'effect/Layer';
|
|
6
8
|
|
|
7
9
|
import { synchronized } from '@dxos/async';
|
|
10
|
+
import { createFeedServiceLayer, type Space } from '@dxos/client/echo';
|
|
8
11
|
import { Resource } from '@dxos/context';
|
|
9
|
-
import { Obj } from '@dxos/echo';
|
|
10
|
-
import {
|
|
12
|
+
import { Feed, Obj } from '@dxos/echo';
|
|
13
|
+
import { runAndForwardErrors } from '@dxos/effect';
|
|
11
14
|
import { type EdgeHttpClient } from '@dxos/react-edge-client';
|
|
12
15
|
import { type ContentBlock, Message } from '@dxos/types';
|
|
13
16
|
|
|
@@ -34,9 +37,10 @@ export type TranscriptMessageEnricher = (message: Message.Message) => Promise<Me
|
|
|
34
37
|
|
|
35
38
|
export type TranscriptionManagerOptions = {
|
|
36
39
|
edgeClient: EdgeHttpClient;
|
|
40
|
+
registry: Registry.Registry;
|
|
37
41
|
|
|
38
42
|
/**
|
|
39
|
-
* Enrich the message before it is written to the transcription
|
|
43
|
+
* Enrich the message before it is written to the transcription feed.
|
|
40
44
|
*/
|
|
41
45
|
messageEnricher?: TranscriptMessageEnricher;
|
|
42
46
|
};
|
|
@@ -47,26 +51,33 @@ export type TranscriptionManagerOptions = {
|
|
|
47
51
|
export class TranscriptionManager extends Resource {
|
|
48
52
|
private readonly _edgeClient: EdgeHttpClient;
|
|
49
53
|
private readonly _messageEnricher?: TranscriptMessageEnricher;
|
|
54
|
+
private readonly _registry: Registry.Registry;
|
|
50
55
|
private _audioStreamTrack?: MediaStreamTrack = undefined;
|
|
51
56
|
private _identityDid?: string = undefined;
|
|
52
57
|
private _mediaRecorder?: MediaStreamRecorder = undefined;
|
|
53
58
|
private _transcriber?: Transcriber = undefined;
|
|
54
|
-
private
|
|
55
|
-
private
|
|
59
|
+
private _feed?: Feed.Feed = undefined;
|
|
60
|
+
private _feedServiceLayer?: Layer.Layer<Feed.FeedService> = undefined;
|
|
61
|
+
private _enabledAtom = Atom.make(false);
|
|
56
62
|
|
|
57
63
|
constructor(options: TranscriptionManagerOptions) {
|
|
58
64
|
super();
|
|
59
65
|
this._edgeClient = options.edgeClient;
|
|
60
66
|
this._messageEnricher = options.messageEnricher;
|
|
67
|
+
this._registry = options.registry;
|
|
61
68
|
}
|
|
62
69
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return this._enabled.value;
|
|
70
|
+
get enabled(): Atom.Atom<boolean> {
|
|
71
|
+
return this._enabledAtom;
|
|
66
72
|
}
|
|
67
73
|
|
|
68
|
-
|
|
69
|
-
this.
|
|
74
|
+
getEnabled(): boolean {
|
|
75
|
+
return this._registry.get(this._enabledAtom);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
setFeed(space: Space, feed: Feed.Feed): this {
|
|
79
|
+
this._feed = feed;
|
|
80
|
+
this._feedServiceLayer = createFeedServiceLayer(space.queues);
|
|
70
81
|
return this;
|
|
71
82
|
}
|
|
72
83
|
|
|
@@ -78,7 +89,7 @@ export class TranscriptionManager extends Resource {
|
|
|
78
89
|
}
|
|
79
90
|
|
|
80
91
|
setRecording(recording?: boolean): this {
|
|
81
|
-
if (!this.isOpen || !this.
|
|
92
|
+
if (!this.isOpen || !this.getEnabled()) {
|
|
82
93
|
return this;
|
|
83
94
|
}
|
|
84
95
|
|
|
@@ -91,11 +102,11 @@ export class TranscriptionManager extends Resource {
|
|
|
91
102
|
}
|
|
92
103
|
|
|
93
104
|
async setEnabled(enabled: boolean): Promise<void> {
|
|
94
|
-
if (this.
|
|
105
|
+
if (this.getEnabled() === enabled) {
|
|
95
106
|
return;
|
|
96
107
|
}
|
|
97
108
|
|
|
98
|
-
this.
|
|
109
|
+
this._registry.set(this._enabledAtom, enabled ?? false);
|
|
99
110
|
if (enabled) {
|
|
100
111
|
await this._maybeRestartTranscriber();
|
|
101
112
|
} else {
|
|
@@ -122,11 +133,11 @@ export class TranscriptionManager extends Resource {
|
|
|
122
133
|
}
|
|
123
134
|
|
|
124
135
|
private async _maybeRestartTranscriber(): Promise<void> {
|
|
125
|
-
if (!this._audioStreamTrack || !this.
|
|
136
|
+
if (!this._audioStreamTrack || !this.getEnabled() || !this.isOpen) {
|
|
126
137
|
return;
|
|
127
138
|
}
|
|
128
139
|
|
|
129
|
-
// Reinitialize transcriber if
|
|
140
|
+
// Reinitialize transcriber if feed or media stream track has changed.
|
|
130
141
|
let needReinit = false;
|
|
131
142
|
if (this._audioStreamTrack !== this._mediaRecorder?.mediaStreamTrack) {
|
|
132
143
|
this._mediaRecorder = new MediaStreamRecorder({
|
|
@@ -155,7 +166,7 @@ export class TranscriptionManager extends Resource {
|
|
|
155
166
|
}
|
|
156
167
|
|
|
157
168
|
private async _onSegments(segments: ContentBlock.Transcript[]): Promise<void> {
|
|
158
|
-
if (!this.isOpen || !this.
|
|
169
|
+
if (!this.isOpen || !this._feed || !this._feedServiceLayer) {
|
|
159
170
|
return;
|
|
160
171
|
}
|
|
161
172
|
|
|
@@ -169,6 +180,6 @@ export class TranscriptionManager extends Resource {
|
|
|
169
180
|
block = await this._messageEnricher(block);
|
|
170
181
|
}
|
|
171
182
|
|
|
172
|
-
await
|
|
183
|
+
await Feed.append(this._feed, [block]).pipe(Effect.provide(this._feedServiceLayer), runAndForwardErrors);
|
|
173
184
|
}
|
|
174
185
|
}
|
package/src/translations.ts
CHANGED
|
@@ -4,20 +4,23 @@
|
|
|
4
4
|
|
|
5
5
|
import { type Resource } from '@dxos/react-ui';
|
|
6
6
|
|
|
7
|
-
import { meta } from '
|
|
7
|
+
import { meta } from '#meta';
|
|
8
8
|
|
|
9
9
|
export const translations = [
|
|
10
10
|
{
|
|
11
11
|
'en-US': {
|
|
12
12
|
[meta.id]: {
|
|
13
|
-
'plugin
|
|
14
|
-
'transcript
|
|
13
|
+
'plugin.name': 'Transcription',
|
|
14
|
+
'transcript-companion.label': 'Transcript',
|
|
15
15
|
|
|
16
|
-
'delete
|
|
17
|
-
'bookmark
|
|
18
|
-
'scroll
|
|
16
|
+
'delete.button': 'Delete',
|
|
17
|
+
'bookmark.button': 'Bookmark',
|
|
18
|
+
'scroll-to-end.label': 'Scroll to latest',
|
|
19
19
|
|
|
20
|
-
'
|
|
20
|
+
'start-recording.label': 'Start recording',
|
|
21
|
+
'stop-recording.label': 'Stop recording',
|
|
22
|
+
|
|
23
|
+
'settings.entity-extraction.label': 'Entity extraction',
|
|
21
24
|
},
|
|
22
25
|
},
|
|
23
26
|
},
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
// @import-as-namespace
|
|
6
|
+
|
|
7
|
+
import * as Schema from 'effect/Schema';
|
|
8
|
+
|
|
9
|
+
import { AiService } from '@dxos/ai';
|
|
10
|
+
import { SpaceSchema } from '@dxos/client/echo';
|
|
11
|
+
import { Operation } from '@dxos/compute';
|
|
12
|
+
import { Database, Feed, Ref } from '@dxos/echo';
|
|
13
|
+
import { Message, Transcript } from '@dxos/types';
|
|
14
|
+
|
|
15
|
+
import { meta } from '#meta';
|
|
16
|
+
|
|
17
|
+
const TRANSCRIPT_OPERATION = `${meta.id}.operation`;
|
|
18
|
+
|
|
19
|
+
export const Create = Operation.make({
|
|
20
|
+
meta: { key: `${TRANSCRIPT_OPERATION}.create`, name: 'Create Transcript' },
|
|
21
|
+
input: Schema.Struct({
|
|
22
|
+
name: Schema.optional(Schema.String),
|
|
23
|
+
space: SpaceSchema,
|
|
24
|
+
}),
|
|
25
|
+
output: Schema.Struct({
|
|
26
|
+
object: Transcript.Transcript,
|
|
27
|
+
}),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
export const MessageWithRangeId = Schema.extend(
|
|
31
|
+
Message.Message,
|
|
32
|
+
Schema.Struct({
|
|
33
|
+
rangeId: Schema.optional(Schema.Array(Schema.String)).annotations({
|
|
34
|
+
description: 'The IDs of the messages that contain the sentences.',
|
|
35
|
+
}),
|
|
36
|
+
}),
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
export type MessageWithRangeIdType = Schema.Schema.Type<typeof MessageWithRangeId>;
|
|
40
|
+
|
|
41
|
+
export const Open = Operation.make({
|
|
42
|
+
meta: {
|
|
43
|
+
key: 'org.dxos.function.transcription.open',
|
|
44
|
+
name: 'Open',
|
|
45
|
+
description: 'Opens and reads the contents of a transcription object.',
|
|
46
|
+
},
|
|
47
|
+
input: Schema.Struct({
|
|
48
|
+
transcript: Ref.Ref(Transcript.Transcript).annotations({
|
|
49
|
+
description: 'The ID of the transcription object.',
|
|
50
|
+
}),
|
|
51
|
+
}),
|
|
52
|
+
output: Schema.Struct({
|
|
53
|
+
content: Schema.String,
|
|
54
|
+
}),
|
|
55
|
+
services: [Database.Service, Feed.FeedService],
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
export const Summarize = Operation.make({
|
|
59
|
+
meta: {
|
|
60
|
+
key: 'org.dxos.function.transcription.summarize',
|
|
61
|
+
name: 'Summarize',
|
|
62
|
+
description: 'Summarize a transcript of a meeting.',
|
|
63
|
+
},
|
|
64
|
+
input: Schema.Struct({
|
|
65
|
+
transcript: Schema.String.annotations({
|
|
66
|
+
description: 'The transcript of the meeting.',
|
|
67
|
+
}),
|
|
68
|
+
notes: Schema.optional(Schema.String).annotations({
|
|
69
|
+
description: 'Additional notes from the participants.',
|
|
70
|
+
}),
|
|
71
|
+
}),
|
|
72
|
+
output: Schema.Struct({
|
|
73
|
+
summary: Schema.String.annotations({
|
|
74
|
+
description: 'The summary of the transcript.',
|
|
75
|
+
}),
|
|
76
|
+
}),
|
|
77
|
+
services: [AiService.AiService],
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
export const SentenceNormalizationInput = Schema.Struct({
|
|
81
|
+
messages: Schema.Array(MessageWithRangeId).annotations({
|
|
82
|
+
description: 'Messages to normalize into sentences.',
|
|
83
|
+
}),
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
export type SentenceNormalizationInputType = Schema.Schema.Type<typeof SentenceNormalizationInput>;
|
|
87
|
+
|
|
88
|
+
export const SentenceNormalizationOutput = Schema.Struct({
|
|
89
|
+
sentences: Schema.Array(MessageWithRangeId.pipe(Schema.mutable)).pipe(Schema.mutable).annotations({
|
|
90
|
+
description: 'The sentences of the transcript.',
|
|
91
|
+
}),
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
export const SentenceNormalization = Operation.make({
|
|
95
|
+
meta: {
|
|
96
|
+
key: 'org.dxos.function.transcription.sentence-normalization',
|
|
97
|
+
name: 'Sentence Normalization',
|
|
98
|
+
description: 'Post process of transcription for sentence normalization',
|
|
99
|
+
},
|
|
100
|
+
input: SentenceNormalizationInput,
|
|
101
|
+
output: SentenceNormalizationOutput,
|
|
102
|
+
services: [],
|
|
103
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
// @import-as-namespace
|
|
6
|
+
|
|
7
|
+
import { Capability } from '@dxos/app-framework';
|
|
8
|
+
|
|
9
|
+
import { meta } from '#meta';
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
type MediaStreamRecorderProps,
|
|
13
|
+
type Transcriber as TranscriberType,
|
|
14
|
+
type TranscriberProps,
|
|
15
|
+
type TranscriptMessageEnricher,
|
|
16
|
+
type TranscriptionManager as TranscriptionManagerType,
|
|
17
|
+
} from '../transcriber';
|
|
18
|
+
|
|
19
|
+
export type GetTranscriberProps = {
|
|
20
|
+
audioStreamTrack: MediaStreamTrack;
|
|
21
|
+
recorderConfig?: Partial<MediaStreamRecorderProps['config']>;
|
|
22
|
+
transcriberConfig?: Partial<TranscriberProps['config']>;
|
|
23
|
+
onSegments: TranscriberProps['onSegments'];
|
|
24
|
+
transcribe?: TranscriberProps['transcribe'];
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type GetTranscriber = (props: GetTranscriberProps) => TranscriberType;
|
|
28
|
+
|
|
29
|
+
export type GetTranscriptionManagerProps = {
|
|
30
|
+
messageEnricher?: TranscriptMessageEnricher;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export type GetTranscriptionManager = (props: GetTranscriptionManagerProps) => TranscriptionManagerType;
|
|
34
|
+
|
|
35
|
+
export const Transcriber = Capability.make<GetTranscriber>(`${meta.id}.capability.transcriber`);
|
|
36
|
+
|
|
37
|
+
export const TranscriptionManager = Capability.make<GetTranscriptionManager>(
|
|
38
|
+
`${meta.id}.capability.transcription-manager`,
|
|
39
|
+
);
|
package/src/types/index.ts
CHANGED