@dxos/plugin-transcription 0.9.1-main.c7dcc2e112 → 0.10.0
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/PLUGIN.mdl +5 -5
- package/dist/lib/neutral/{TranscriptionArticle-S56VVOSF.mjs → TranscriptionArticle-FEWCWG4A.mjs} +3 -6
- package/dist/lib/neutral/TranscriptionArticle-FEWCWG4A.mjs.map +7 -0
- package/dist/lib/neutral/TranscriptionPlugin.mjs +25 -4
- package/dist/lib/neutral/TranscriptionPlugin.mjs.map +3 -3
- package/dist/lib/neutral/TranscriptionPlugin.node.mjs +3 -3
- package/dist/lib/neutral/TranscriptionPlugin.node.mjs.map +3 -3
- package/dist/lib/neutral/app-graph-builder-GQRMI22E.mjs +48 -0
- package/dist/lib/neutral/app-graph-builder-GQRMI22E.mjs.map +7 -0
- package/dist/lib/neutral/capabilities/index.mjs +17 -5
- package/dist/lib/neutral/capabilities/index.mjs.map +3 -3
- package/dist/lib/neutral/{chunk-XZVDAYM6.mjs → chunk-5BVHY75B.mjs} +2 -2
- package/dist/lib/neutral/{chunk-XZVDAYM6.mjs.map → chunk-5BVHY75B.mjs.map} +1 -1
- package/dist/lib/neutral/chunk-HNXSU7HJ.mjs +8 -0
- package/dist/lib/neutral/chunk-KOXLGGSL.mjs +30 -0
- package/dist/lib/neutral/chunk-KOXLGGSL.mjs.map +7 -0
- package/dist/lib/neutral/{chunk-2URVUJT4.mjs → chunk-MDV7NBFJ.mjs} +31 -8
- package/dist/lib/neutral/chunk-MDV7NBFJ.mjs.map +7 -0
- package/dist/lib/neutral/components/index.mjs +114 -258
- package/dist/lib/neutral/components/index.mjs.map +4 -4
- package/dist/lib/neutral/containers/index.mjs +1 -1
- package/dist/lib/neutral/{create-7NGOP7JP.mjs → create-HNHGCKZ4.mjs} +2 -2
- package/dist/lib/neutral/{enrich-message-F2AOM53F.mjs → enrich-message-DSJU4TXC.mjs} +2 -2
- package/dist/lib/neutral/entity-lookup-PCDW7NC4.mjs +25 -0
- package/dist/lib/neutral/entity-lookup-PCDW7NC4.mjs.map +7 -0
- package/dist/lib/neutral/hooks/index.mjs +93 -15
- package/dist/lib/neutral/hooks/index.mjs.map +4 -4
- package/dist/lib/neutral/index.mjs +6 -32
- package/dist/lib/neutral/markdown-extension-CCDXXY7E.mjs +16 -0
- package/dist/lib/neutral/markdown-extension-CCDXXY7E.mjs.map +7 -0
- package/dist/lib/neutral/meta.json +1 -1
- package/dist/lib/neutral/meta.mjs +1 -1
- package/dist/lib/neutral/{open-42H72C4G.mjs → open-SNMZXXYO.mjs} +4 -6
- package/dist/lib/neutral/open-SNMZXXYO.mjs.map +7 -0
- package/dist/lib/neutral/operations/index.mjs +1 -1
- package/dist/lib/neutral/pipeline-status-XMWMAUJY.mjs +17 -0
- package/dist/lib/neutral/pipeline-status-XMWMAUJY.mjs.map +7 -0
- package/dist/lib/neutral/plugin.mjs +2 -2
- package/dist/lib/neutral/recording-session-IADO7ATU.mjs +15 -0
- package/dist/lib/neutral/recording-session-IADO7ATU.mjs.map +7 -0
- package/dist/lib/neutral/{settings-DUS32HOM.mjs → settings-7KE4MABW.mjs} +3 -2
- package/dist/lib/neutral/{settings-DUS32HOM.mjs.map → settings-7KE4MABW.mjs.map} +3 -3
- package/dist/lib/neutral/skill-definition-DXNK324V.mjs +15 -0
- package/dist/lib/neutral/skill-definition-DXNK324V.mjs.map +7 -0
- package/dist/lib/neutral/skills/index.mjs +8 -0
- package/dist/lib/neutral/{summarize-45WVUPED.mjs → summarize-LBUZTOTH.mjs} +4 -4
- package/dist/lib/neutral/summarize-LBUZTOTH.mjs.map +7 -0
- package/dist/lib/neutral/{text-content-XZ3HK4OT.mjs → text-content-NOWR642C.mjs} +2 -4
- package/dist/lib/neutral/text-content-NOWR642C.mjs.map +7 -0
- package/dist/lib/neutral/transcriber-6XZHUUHK.mjs +174 -0
- package/dist/lib/neutral/transcriber-6XZHUUHK.mjs.map +7 -0
- package/dist/lib/neutral/transcription-driver-DN6ELQXZ.mjs +207 -0
- package/dist/lib/neutral/transcription-driver-DN6ELQXZ.mjs.map +7 -0
- package/dist/lib/neutral/translations.mjs +7 -0
- package/dist/lib/neutral/translations.mjs.map +2 -2
- package/dist/lib/neutral/types/index.mjs +1 -1
- package/dist/types/src/TranscriptionPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/app-graph-builder.d.ts +5 -0
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
- package/dist/types/src/capabilities/entity-lookup.d.ts +10 -0
- package/dist/types/src/capabilities/entity-lookup.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +7 -1
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/markdown-extension.d.ts +5 -0
- package/dist/types/src/capabilities/markdown-extension.d.ts.map +1 -0
- package/dist/types/src/capabilities/pipeline-status.d.ts +9 -0
- package/dist/types/src/capabilities/pipeline-status.d.ts.map +1 -0
- package/dist/types/src/capabilities/react-surface.d.ts +1 -1
- package/dist/types/src/capabilities/recording-session.d.ts +5 -0
- package/dist/types/src/capabilities/recording-session.d.ts.map +1 -0
- package/dist/types/src/capabilities/settings.d.ts +1 -3
- package/dist/types/src/capabilities/settings.d.ts.map +1 -1
- package/dist/types/src/capabilities/skill-definition.d.ts +5 -0
- package/dist/types/src/capabilities/skill-definition.d.ts.map +1 -0
- package/dist/types/src/capabilities/text-content.d.ts +1 -4
- 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/capabilities/transcription-driver.d.ts +5 -0
- package/dist/types/src/capabilities/transcription-driver.d.ts.map +1 -0
- package/dist/types/src/components/Mic/Mic.d.ts +12 -0
- package/dist/types/src/components/Mic/Mic.d.ts.map +1 -0
- package/dist/types/src/components/{Oracle/Oracle.stories.d.ts → Mic/Mic.stories.d.ts} +9 -7
- package/dist/types/src/components/Mic/Mic.stories.d.ts.map +1 -0
- package/dist/types/src/components/Mic/index.d.ts +2 -0
- package/dist/types/src/components/Mic/index.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +1 -2
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/containers/TranscriptionArticle/TranscriptionArticle.d.ts.map +1 -1
- package/dist/types/src/containers/TranscriptionArticle/TranscriptionArticle.stories.d.ts +7 -0
- package/dist/types/src/containers/TranscriptionArticle/TranscriptionArticle.stories.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +0 -5
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useTranscriptionRecording.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -3
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +4 -0
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/normalization/message-normalizer.d.ts +2 -2
- package/dist/types/src/normalization/message-normalizer.d.ts.map +1 -1
- package/dist/types/src/normalization/normalization.d.ts +98 -733
- package/dist/types/src/normalization/normalization.d.ts.map +1 -1
- package/dist/types/src/operations/open.d.ts.map +1 -1
- package/dist/types/src/operations/summarize.d.ts.map +1 -1
- package/dist/types/src/skills/index.d.ts +2 -0
- package/dist/types/src/skills/index.d.ts.map +1 -0
- package/dist/types/src/skills/transcription-skill.d.ts +4 -0
- package/dist/types/src/skills/transcription-skill.d.ts.map +1 -0
- package/dist/types/src/stories/Keyword.stories.d.ts +51 -0
- package/dist/types/src/stories/Keyword.stories.d.ts.map +1 -0
- package/dist/types/src/stories/Pipeline.stories.d.ts +60 -0
- package/dist/types/src/stories/Pipeline.stories.d.ts.map +1 -0
- package/dist/types/src/stories/Transcription.stories.d.ts +23 -0
- package/dist/types/src/stories/Transcription.stories.d.ts.map +1 -0
- package/dist/types/src/testing/decorators.d.ts +21 -0
- package/dist/types/src/testing/decorators.d.ts.map +1 -0
- package/dist/types/src/testing/index.d.ts +1 -0
- package/dist/types/src/testing/index.d.ts.map +1 -1
- package/dist/types/src/testing/testing.d.ts +3 -9
- package/dist/types/src/testing/testing.d.ts.map +1 -1
- package/dist/types/src/{transcriber/transcription-manager.d.ts → transcription-manager.d.ts} +6 -5
- package/dist/types/src/transcription-manager.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +7 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/Settings.d.ts +6 -0
- package/dist/types/src/types/Settings.d.ts.map +1 -1
- package/dist/types/src/types/TranscriptOperation.d.ts +114 -1971
- package/dist/types/src/types/TranscriptOperation.d.ts.map +1 -1
- package/dist/types/src/types/TranscriptionCapabilities.d.ts +51 -13
- package/dist/types/src/types/TranscriptionCapabilities.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +0 -2
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/dx.config.ts +1 -1
- package/package.json +68 -69
- package/src/TranscriptionPlugin.node.ts +2 -2
- package/src/TranscriptionPlugin.test.ts +1 -1
- package/src/TranscriptionPlugin.tsx +31 -2
- package/src/capabilities/app-graph-builder.tsx +49 -0
- package/src/capabilities/entity-lookup.ts +32 -0
- package/src/capabilities/index.ts +7 -1
- package/src/capabilities/markdown-extension.ts +17 -0
- package/src/capabilities/pipeline-status.ts +23 -0
- package/src/capabilities/recording-session.ts +17 -0
- package/src/capabilities/settings.ts +1 -0
- package/src/capabilities/skill-definition.ts +15 -0
- package/src/capabilities/text-content.ts +1 -2
- package/src/capabilities/transcriber.ts +5 -48
- package/src/capabilities/transcription-driver.tsx +263 -0
- package/src/components/Mic/Mic.stories.tsx +66 -0
- package/src/components/Mic/Mic.tsx +136 -0
- package/src/components/Mic/index.ts +5 -0
- package/src/components/index.ts +1 -2
- package/src/containers/TranscriptionArticle/TranscriptionArticle.stories.tsx +4 -0
- package/src/containers/TranscriptionArticle/TranscriptionArticle.tsx +4 -5
- package/src/hooks/index.ts +0 -5
- package/src/hooks/useTranscriptionRecording.ts +4 -8
- package/src/index.ts +1 -5
- package/src/normalization/message-normalizer.ts +3 -3
- package/src/normalization/normalization.ts +3 -0
- package/src/operations/open.ts +2 -2
- package/src/operations/summarize.ts +2 -2
- package/src/skills/index.ts +5 -0
- package/src/skills/transcription-skill.ts +29 -0
- package/src/stories/Keyword.stories.tsx +98 -0
- package/src/stories/Pipeline.stories.tsx +361 -0
- package/src/stories/Transcription.stories.tsx +178 -0
- package/src/testing/decorators.ts +78 -0
- package/src/testing/index.ts +1 -0
- package/src/testing/testing.ts +13 -48
- package/src/{transcriber/transcription-manager.ts → transcription-manager.ts} +13 -12
- package/src/translations.ts +8 -0
- package/src/types/Settings.ts +38 -0
- package/src/types/TranscriptOperation.ts +6 -4
- package/src/types/TranscriptionCapabilities.ts +57 -21
- package/src/util/index.ts +0 -2
- package/dist/lib/neutral/TranscriptionArticle-S56VVOSF.mjs.map +0 -7
- package/dist/lib/neutral/blueprint-definition-DA4QFRYJ.mjs +0 -15
- package/dist/lib/neutral/blueprint-definition-DA4QFRYJ.mjs.map +0 -7
- package/dist/lib/neutral/blueprints/index.mjs +0 -8
- package/dist/lib/neutral/chunk-2URVUJT4.mjs.map +0 -7
- package/dist/lib/neutral/chunk-J4ONEYPJ.mjs +0 -8
- package/dist/lib/neutral/chunk-MLRJWAQH.mjs +0 -179
- package/dist/lib/neutral/chunk-MLRJWAQH.mjs.map +0 -7
- package/dist/lib/neutral/chunk-XMHH34NI.mjs +0 -318
- package/dist/lib/neutral/chunk-XMHH34NI.mjs.map +0 -7
- package/dist/lib/neutral/chunk-XOXHWMXR.mjs +0 -35
- package/dist/lib/neutral/chunk-XOXHWMXR.mjs.map +0 -7
- package/dist/lib/neutral/chunk-XWC5BBOY.mjs +0 -435
- package/dist/lib/neutral/chunk-XWC5BBOY.mjs.map +0 -7
- package/dist/lib/neutral/chunk-ZR4BH4QQ.mjs +0 -30
- package/dist/lib/neutral/chunk-ZR4BH4QQ.mjs.map +0 -7
- package/dist/lib/neutral/open-42H72C4G.mjs.map +0 -7
- package/dist/lib/neutral/summarize-45WVUPED.mjs.map +0 -7
- package/dist/lib/neutral/text-content-XZ3HK4OT.mjs.map +0 -7
- package/dist/lib/neutral/transcriber-KYV6NWI5.mjs +0 -59
- package/dist/lib/neutral/transcriber-KYV6NWI5.mjs.map +0 -7
- package/dist/types/src/blueprints/index.d.ts +0 -2
- package/dist/types/src/blueprints/index.d.ts.map +0 -1
- package/dist/types/src/blueprints/transcription-blueprint.d.ts +0 -4
- package/dist/types/src/blueprints/transcription-blueprint.d.ts.map +0 -1
- package/dist/types/src/capabilities/blueprint-definition.d.ts +0 -6
- package/dist/types/src/capabilities/blueprint-definition.d.ts.map +0 -1
- package/dist/types/src/components/Oracle/Oracle.d.ts +0 -24
- package/dist/types/src/components/Oracle/Oracle.d.ts.map +0 -1
- package/dist/types/src/components/Oracle/Oracle.stories.d.ts.map +0 -1
- package/dist/types/src/components/Oracle/index.d.ts +0 -2
- package/dist/types/src/components/Oracle/index.d.ts.map +0 -1
- package/dist/types/src/components/Transcription/Transcription.d.ts +0 -11
- package/dist/types/src/components/Transcription/Transcription.d.ts.map +0 -1
- package/dist/types/src/components/Transcription/Transcription.stories.d.ts +0 -37
- package/dist/types/src/components/Transcription/Transcription.stories.d.ts.map +0 -1
- package/dist/types/src/components/Transcription/index.d.ts +0 -2
- package/dist/types/src/components/Transcription/index.d.ts.map +0 -1
- package/dist/types/src/components/Transcription/transcription-extension.d.ts +0 -15
- package/dist/types/src/components/Transcription/transcription-extension.d.ts.map +0 -1
- package/dist/types/src/enrichment/conversation.test.d.ts +0 -2
- package/dist/types/src/enrichment/conversation.test.d.ts.map +0 -1
- package/dist/types/src/enrichment/operations.d.ts +0 -200
- package/dist/types/src/enrichment/operations.d.ts.map +0 -1
- package/dist/types/src/enrichment/parser.d.ts +0 -26
- package/dist/types/src/enrichment/parser.d.ts.map +0 -1
- package/dist/types/src/enrichment/stream-simulator.d.ts +0 -38
- package/dist/types/src/enrichment/stream-simulator.d.ts.map +0 -1
- package/dist/types/src/hooks/useAudioFile.d.ts +0 -7
- package/dist/types/src/hooks/useAudioFile.d.ts.map +0 -1
- package/dist/types/src/hooks/useAudioTrack.d.ts +0 -5
- package/dist/types/src/hooks/useAudioTrack.d.ts.map +0 -1
- package/dist/types/src/hooks/useFeedModelAdapter.d.ts +0 -12
- package/dist/types/src/hooks/useFeedModelAdapter.d.ts.map +0 -1
- package/dist/types/src/hooks/useTranscriber.d.ts +0 -7
- package/dist/types/src/hooks/useTranscriber.d.ts.map +0 -1
- package/dist/types/src/hooks/useVoiceInput.d.ts +0 -11
- package/dist/types/src/hooks/useVoiceInput.d.ts.map +0 -1
- package/dist/types/src/model/index.d.ts +0 -2
- package/dist/types/src/model/index.d.ts.map +0 -1
- package/dist/types/src/model/model.d.ts +0 -68
- package/dist/types/src/model/model.d.ts.map +0 -1
- package/dist/types/src/model/model.test.d.ts +0 -2
- package/dist/types/src/model/model.test.d.ts.map +0 -1
- package/dist/types/src/stories/FileTranscription.stories.d.ts +0 -20
- package/dist/types/src/stories/FileTranscription.stories.d.ts.map +0 -1
- package/dist/types/src/stories/KeyWordRecognition.stories.d.ts +0 -14
- package/dist/types/src/stories/KeyWordRecognition.stories.d.ts.map +0 -1
- package/dist/types/src/stories/LiveTranscription.stories.d.ts +0 -19
- package/dist/types/src/stories/LiveTranscription.stories.d.ts.map +0 -1
- package/dist/types/src/stories/ProperNounExtraction.stories.d.ts +0 -13
- package/dist/types/src/stories/ProperNounExtraction.stories.d.ts.map +0 -1
- package/dist/types/src/stories/TranscriptionStory.d.ts +0 -21
- package/dist/types/src/stories/TranscriptionStory.d.ts.map +0 -1
- package/dist/types/src/stories/common.d.ts +0 -248
- package/dist/types/src/stories/common.d.ts.map +0 -1
- package/dist/types/src/transcriber/audio-recorder.d.ts +0 -47
- package/dist/types/src/transcriber/audio-recorder.d.ts.map +0 -1
- package/dist/types/src/transcriber/index.d.ts +0 -5
- package/dist/types/src/transcriber/index.d.ts.map +0 -1
- package/dist/types/src/transcriber/media-stream-recorder.d.ts +0 -30
- package/dist/types/src/transcriber/media-stream-recorder.d.ts.map +0 -1
- package/dist/types/src/transcriber/transcriber.browser.test.d.ts +0 -2
- package/dist/types/src/transcriber/transcriber.browser.test.d.ts.map +0 -1
- package/dist/types/src/transcriber/transcriber.d.ts +0 -105
- package/dist/types/src/transcriber/transcriber.d.ts.map +0 -1
- package/dist/types/src/transcriber/transcriber.test.d.ts +0 -2
- package/dist/types/src/transcriber/transcriber.test.d.ts.map +0 -1
- package/dist/types/src/transcriber/transcription-manager.d.ts.map +0 -1
- package/dist/types/src/util/array.d.ts +0 -2
- package/dist/types/src/util/array.d.ts.map +0 -1
- package/dist/types/src/util/render-byline.d.ts +0 -4
- package/dist/types/src/util/render-byline.d.ts.map +0 -1
- package/src/blueprints/index.ts +0 -5
- package/src/blueprints/transcription-blueprint.ts +0 -29
- package/src/capabilities/blueprint-definition.ts +0 -19
- package/src/components/Oracle/Oracle.stories.tsx +0 -147
- package/src/components/Oracle/Oracle.tsx +0 -142
- package/src/components/Oracle/index.ts +0 -5
- package/src/components/Transcription/Transcription.stories.tsx +0 -213
- package/src/components/Transcription/Transcription.tsx +0 -55
- package/src/components/Transcription/index.ts +0 -5
- package/src/components/Transcription/transcription-extension.ts +0 -203
- package/src/enrichment/conversation.test.ts +0 -162
- package/src/enrichment/conversation.txt +0 -23
- package/src/enrichment/operations.ts +0 -271
- package/src/enrichment/parser.ts +0 -101
- package/src/enrichment/stream-simulator.ts +0 -125
- package/src/hooks/useAudioFile.ts +0 -88
- package/src/hooks/useAudioTrack.ts +0 -35
- package/src/hooks/useFeedModelAdapter.ts +0 -46
- package/src/hooks/useTranscriber.ts +0 -47
- package/src/hooks/useVoiceInput.ts +0 -66
- package/src/model/index.ts +0 -5
- package/src/model/model.test.ts +0 -175
- package/src/model/model.ts +0 -229
- package/src/stories/FileTranscription.stories.tsx +0 -143
- package/src/stories/KeyWordRecognition.stories.tsx +0 -132
- package/src/stories/LiveTranscription.stories.tsx +0 -99
- package/src/stories/ProperNounExtraction.stories.tsx +0 -99
- package/src/stories/TranscriptionStory.tsx +0 -101
- package/src/stories/common.ts +0 -234
- package/src/transcriber/audio-recorder.ts +0 -56
- package/src/transcriber/index.ts +0 -8
- package/src/transcriber/media-stream-recorder.ts +0 -120
- package/src/transcriber/transcriber.browser.test.ts +0 -230
- package/src/transcriber/transcriber.test.ts +0 -104
- package/src/transcriber/transcriber.ts +0 -303
- package/src/util/array.ts +0 -14
- package/src/util/render-byline.ts +0 -33
- /package/dist/lib/neutral/{chunk-J4ONEYPJ.mjs.map → chunk-HNXSU7HJ.mjs.map} +0 -0
- /package/dist/lib/neutral/{create-7NGOP7JP.mjs.map → create-HNHGCKZ4.mjs.map} +0 -0
- /package/dist/lib/neutral/{enrich-message-F2AOM53F.mjs.map → enrich-message-DSJU4TXC.mjs.map} +0 -0
- /package/dist/lib/neutral/{blueprints → skills}/index.mjs.map +0 -0
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import React, {
|
|
6
|
-
type ChangeEvent,
|
|
7
|
-
type Dispatch,
|
|
8
|
-
type RefObject,
|
|
9
|
-
type SetStateAction,
|
|
10
|
-
useCallback,
|
|
11
|
-
useRef,
|
|
12
|
-
} from 'react';
|
|
13
|
-
|
|
14
|
-
import { IconButton, ScrollContainer, Toolbar } from '@dxos/react-ui';
|
|
15
|
-
import { type Message } from '@dxos/types';
|
|
16
|
-
|
|
17
|
-
import { Transcription } from '../components';
|
|
18
|
-
import { type SerializationModel } from '../model';
|
|
19
|
-
|
|
20
|
-
export type TranscriptionStoryProps = {
|
|
21
|
-
audioRef?: RefObject<HTMLAudioElement | null>;
|
|
22
|
-
model: SerializationModel<Message.Message>;
|
|
23
|
-
running: boolean;
|
|
24
|
-
disabled?: boolean;
|
|
25
|
-
uploadAccept?: string;
|
|
26
|
-
onRunningChange: Dispatch<SetStateAction<boolean>>;
|
|
27
|
-
onUpload?: (file: File) => void;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Story wrapper that renders a transcript with playback controls, an optional audio file
|
|
32
|
-
* upload affordance, and a toolbar slot for additional controls.
|
|
33
|
-
*
|
|
34
|
-
* @param onUpload - Callback fired when the user picks a local audio file via the upload button.
|
|
35
|
-
* @param uploadAccept - HTML `accept` filter for the hidden file input. Defaults to `audio/*`.
|
|
36
|
-
*/
|
|
37
|
-
export const TranscriptionStory = ({
|
|
38
|
-
audioRef,
|
|
39
|
-
model,
|
|
40
|
-
running,
|
|
41
|
-
disabled,
|
|
42
|
-
uploadAccept = 'audio/*',
|
|
43
|
-
onRunningChange,
|
|
44
|
-
onUpload,
|
|
45
|
-
}: TranscriptionStoryProps) => {
|
|
46
|
-
const fileInputRef = useRef<HTMLInputElement>(null);
|
|
47
|
-
|
|
48
|
-
const handleFileChange = useCallback(
|
|
49
|
-
(event: ChangeEvent<HTMLInputElement>) => {
|
|
50
|
-
const file = event.target.files?.[0];
|
|
51
|
-
if (file && onUpload) {
|
|
52
|
-
onUpload(file);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Reset so the same file can be re-selected.
|
|
56
|
-
event.target.value = '';
|
|
57
|
-
},
|
|
58
|
-
[onUpload],
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
return (
|
|
62
|
-
<>
|
|
63
|
-
{audioRef && <audio ref={audioRef} autoPlay />}
|
|
64
|
-
<Toolbar.Root>
|
|
65
|
-
<IconButton
|
|
66
|
-
iconOnly
|
|
67
|
-
disabled={disabled}
|
|
68
|
-
icon={running ? 'ph--pause--regular' : 'ph--play--regular'}
|
|
69
|
-
label={running ? 'Pause' : 'Play'}
|
|
70
|
-
onClick={() => onRunningChange((running) => !running)}
|
|
71
|
-
/>
|
|
72
|
-
{onUpload && (
|
|
73
|
-
<>
|
|
74
|
-
<input
|
|
75
|
-
ref={fileInputRef}
|
|
76
|
-
type='file'
|
|
77
|
-
accept={uploadAccept}
|
|
78
|
-
disabled={disabled}
|
|
79
|
-
className='hidden'
|
|
80
|
-
onChange={handleFileChange}
|
|
81
|
-
/>
|
|
82
|
-
<IconButton
|
|
83
|
-
iconOnly
|
|
84
|
-
disabled={disabled}
|
|
85
|
-
icon='ph--upload--regular'
|
|
86
|
-
label='Upload audio'
|
|
87
|
-
onClick={() => fileInputRef.current?.click()}
|
|
88
|
-
/>
|
|
89
|
-
</>
|
|
90
|
-
)}
|
|
91
|
-
</Toolbar.Root>
|
|
92
|
-
<ScrollContainer.Root pin>
|
|
93
|
-
<ScrollContainer.Content>
|
|
94
|
-
<ScrollContainer.Viewport>
|
|
95
|
-
<Transcription model={model} />
|
|
96
|
-
</ScrollContainer.Viewport>
|
|
97
|
-
</ScrollContainer.Content>
|
|
98
|
-
</ScrollContainer.Root>
|
|
99
|
-
</>
|
|
100
|
-
);
|
|
101
|
-
};
|
package/src/stories/common.ts
DELETED
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
// Helpers shared between LiveTranscription / FileTranscription stories.
|
|
6
|
-
// Each "live" story differs only in its *audio source* (mic vs file); everything else —
|
|
7
|
-
// the local in-memory message buffer, the transcriber lifecycle, and the plugin-manager
|
|
8
|
-
// decorator stack — is identical and lives here.
|
|
9
|
-
|
|
10
|
-
import { type Decorator } from '@storybook/react-vite';
|
|
11
|
-
import * as Effect from 'effect/Effect';
|
|
12
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
13
|
-
|
|
14
|
-
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
15
|
-
import { AppActivationEvents } from '@dxos/app-toolkit';
|
|
16
|
-
import { scheduleTask } from '@dxos/async';
|
|
17
|
-
import { SpeakingMonitor } from '@dxos/av';
|
|
18
|
-
import { Context } from '@dxos/context';
|
|
19
|
-
import { Obj } from '@dxos/echo';
|
|
20
|
-
import { ClientPlugin, initializeIdentity } from '@dxos/plugin-client/testing';
|
|
21
|
-
import { PreviewPlugin } from '@dxos/plugin-preview/testing';
|
|
22
|
-
import { StorybookPlugin, corePlugins } from '@dxos/plugin-testing';
|
|
23
|
-
import { IndexKind } from '@dxos/react-client/echo';
|
|
24
|
-
import { withLayout } from '@dxos/react-ui/testing';
|
|
25
|
-
import { Message, Organization, Person } from '@dxos/types';
|
|
26
|
-
import { seedTestData } from '@dxos/types/testing';
|
|
27
|
-
|
|
28
|
-
import { useFeedModelAdapter, useTranscriber } from '#hooks';
|
|
29
|
-
import { TestItem } from '#testing';
|
|
30
|
-
import { type TranscriptionCapabilities } from '#types';
|
|
31
|
-
|
|
32
|
-
import { type Transcriber, type TranscriberProps } from '../transcriber';
|
|
33
|
-
import { TranscriptionPlugin } from '../TranscriptionPlugin';
|
|
34
|
-
import { renderByline } from '../util';
|
|
35
|
-
|
|
36
|
-
export const useIsSpeaking = (track?: MediaStreamTrack) => {
|
|
37
|
-
const [isSpeaking, setIsSpeaking] = useState(false);
|
|
38
|
-
const speakingMonitor = useMemo(() => {
|
|
39
|
-
if (!track) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return new SpeakingMonitor(track);
|
|
44
|
-
}, [track]);
|
|
45
|
-
|
|
46
|
-
useEffect(() => {
|
|
47
|
-
if (!speakingMonitor) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const ctx = new Context();
|
|
52
|
-
scheduleTask(ctx, async () => {
|
|
53
|
-
speakingMonitor.speakingChanged.on(ctx, () => setIsSpeaking(speakingMonitor.isSpeaking));
|
|
54
|
-
await speakingMonitor.open();
|
|
55
|
-
ctx.onDispose(() => speakingMonitor.close());
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
return () => {
|
|
59
|
-
void ctx.dispose();
|
|
60
|
-
};
|
|
61
|
-
}, [speakingMonitor]);
|
|
62
|
-
|
|
63
|
-
return isSpeaking;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
//
|
|
67
|
-
// Message model.
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* In-memory message buffer + model adapter for storybook use (production wires up a real
|
|
72
|
-
* space-backed `Feed`). Returns the renderable `model` plus an `appendMessage` callback.
|
|
73
|
-
*/
|
|
74
|
-
export const useStoryMessageModel = () => {
|
|
75
|
-
const [messages, setMessages] = useState<Message.Message[]>([]);
|
|
76
|
-
const appendMessage = useCallback((message: Message.Message) => setMessages((prev) => [...prev, message]), []);
|
|
77
|
-
const model = useFeedModelAdapter(renderByline([]), messages);
|
|
78
|
-
return { model, appendMessage };
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Wraps blocks in a `Message.Message` with the given sender and appends it to the local buffer.
|
|
83
|
-
* Provided as a convenience for stories that don't need entity-extraction or custom enrichment.
|
|
84
|
-
*/
|
|
85
|
-
export const useStoryAppendSegments = (
|
|
86
|
-
appendMessage: (message: Message.Message) => void,
|
|
87
|
-
sender: Message.Message['sender'] = {},
|
|
88
|
-
): TranscriberProps['onSegments'] =>
|
|
89
|
-
useCallback<TranscriberProps['onSegments']>(
|
|
90
|
-
async (blocks) => {
|
|
91
|
-
appendMessage(
|
|
92
|
-
Obj.make(Message.Message, {
|
|
93
|
-
created: new Date().toISOString(),
|
|
94
|
-
sender,
|
|
95
|
-
blocks,
|
|
96
|
-
}),
|
|
97
|
-
);
|
|
98
|
-
},
|
|
99
|
-
[appendMessage, sender],
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
//
|
|
103
|
-
// Transcriber lifecycle.
|
|
104
|
-
//
|
|
105
|
-
|
|
106
|
-
export type UseStoryTranscriberOptions = Pick<
|
|
107
|
-
TranscriptionCapabilities.TranscriberProviderProps,
|
|
108
|
-
'transcriberConfig' | 'recorderConfig' | 'onSegments'
|
|
109
|
-
> & {
|
|
110
|
-
audioStreamTrack?: MediaStreamTrack;
|
|
111
|
-
/** Whether the user has the toolbar toggle on. */
|
|
112
|
-
running: boolean;
|
|
113
|
-
/** Voice-activity flag — chunks recording only fires while `true`. */
|
|
114
|
-
isSpeaking: boolean;
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Drives the transcriber's open/close + chunk-recording lifecycle off `running`,
|
|
119
|
-
* the open flag, and an `isSpeaking` voice-activity gate. Returns the transcriber instance
|
|
120
|
-
* (`undefined` until the capability resolves and an audio track is available).
|
|
121
|
-
*/
|
|
122
|
-
export const useStoryTranscriber = ({
|
|
123
|
-
audioStreamTrack,
|
|
124
|
-
running,
|
|
125
|
-
isSpeaking,
|
|
126
|
-
transcriberConfig,
|
|
127
|
-
recorderConfig,
|
|
128
|
-
onSegments,
|
|
129
|
-
}: UseStoryTranscriberOptions): Transcriber | undefined => {
|
|
130
|
-
const transcriber = useTranscriber({
|
|
131
|
-
audioStreamTrack,
|
|
132
|
-
onSegments,
|
|
133
|
-
transcriberConfig,
|
|
134
|
-
recorderConfig,
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
// Open the transcriber when it becomes available; close on teardown.
|
|
138
|
-
// `tokenRef` is a per-effect identity so a late `close()` completion from a stale
|
|
139
|
-
// transcriber instance can't clobber `isOpen` after a newer instance has opened.
|
|
140
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
141
|
-
const tokenRef = useRef<symbol | null>(null);
|
|
142
|
-
useEffect(() => {
|
|
143
|
-
if (!transcriber) {
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
const token = Symbol();
|
|
147
|
-
tokenRef.current = token;
|
|
148
|
-
void transcriber.open().then(
|
|
149
|
-
() => tokenRef.current === token && setIsOpen(true),
|
|
150
|
-
() => tokenRef.current === token && setIsOpen(false),
|
|
151
|
-
);
|
|
152
|
-
return () => {
|
|
153
|
-
void transcriber.close().then(() => {
|
|
154
|
-
if (tokenRef.current === token) {
|
|
155
|
-
setIsOpen(false);
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
};
|
|
159
|
-
}, [transcriber]);
|
|
160
|
-
|
|
161
|
-
// Start/stop chunk recording based on running + open + isSpeaking.
|
|
162
|
-
useEffect(() => {
|
|
163
|
-
if (!transcriber || !isOpen) {
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
if (running && isSpeaking) {
|
|
167
|
-
transcriber.startChunksRecording();
|
|
168
|
-
} else {
|
|
169
|
-
transcriber.stopChunksRecording();
|
|
170
|
-
}
|
|
171
|
-
}, [transcriber, isOpen, running, isSpeaking]);
|
|
172
|
-
|
|
173
|
-
return transcriber;
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
//
|
|
177
|
-
// Plugin manager decorator.
|
|
178
|
-
//
|
|
179
|
-
|
|
180
|
-
export type StoryDecoratorsOptions = {
|
|
181
|
-
/**
|
|
182
|
-
* Enable schema/graph/vector indexes after the client boots; needed for entity-extraction
|
|
183
|
-
* queries over seeded `Person` / `Organization` objects.
|
|
184
|
-
* @default false
|
|
185
|
-
*/
|
|
186
|
-
enableVectorIndex?: boolean;
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Standard plugin-manager decorator for transcription stories: core plugins,
|
|
191
|
-
* `ClientPlugin` with `Person`/`Organization`/`TestItem` schemas + seeded test data, plus
|
|
192
|
-
* the `PreviewPlugin` and `TranscriptionPlugin`. Toggle `enableVectorIndex` for entity-extraction.
|
|
193
|
-
*/
|
|
194
|
-
export const createStoryDecorators = ({ enableVectorIndex = false }: StoryDecoratorsOptions = {}): Decorator[] => [
|
|
195
|
-
withLayout({ layout: 'column' }),
|
|
196
|
-
withPluginManager({
|
|
197
|
-
plugins: [
|
|
198
|
-
...corePlugins(),
|
|
199
|
-
StorybookPlugin({}),
|
|
200
|
-
ClientPlugin({
|
|
201
|
-
types: [TestItem, Person.Person, Organization.Organization],
|
|
202
|
-
onClientInitialized: ({ client }) =>
|
|
203
|
-
Effect.gen(function* () {
|
|
204
|
-
const { personalSpace } = yield* initializeIdentity(client);
|
|
205
|
-
if (enableVectorIndex) {
|
|
206
|
-
yield* enableQueryIndexes(client.services.services);
|
|
207
|
-
}
|
|
208
|
-
yield* Effect.promise(() => seedTestData(personalSpace));
|
|
209
|
-
}),
|
|
210
|
-
}),
|
|
211
|
-
PreviewPlugin(),
|
|
212
|
-
TranscriptionPlugin(),
|
|
213
|
-
],
|
|
214
|
-
fireEvents: [AppActivationEvents.SetupAppGraph],
|
|
215
|
-
}),
|
|
216
|
-
];
|
|
217
|
-
|
|
218
|
-
// TODO(mykola): Make API easier to use.
|
|
219
|
-
// TODO(mykola): Delete after enabling vector indexing by default.
|
|
220
|
-
const enableQueryIndexes = (services: { QueryService?: any }) =>
|
|
221
|
-
Effect.gen(function* () {
|
|
222
|
-
yield* Effect.promise(() =>
|
|
223
|
-
services.QueryService!.setConfig({
|
|
224
|
-
enabled: true,
|
|
225
|
-
indexes: [
|
|
226
|
-
{ kind: IndexKind.Kind.SCHEMA_MATCH },
|
|
227
|
-
{ kind: IndexKind.Kind.GRAPH },
|
|
228
|
-
{ kind: IndexKind.Kind.VECTOR },
|
|
229
|
-
{ kind: IndexKind.Kind.FULL_TEXT },
|
|
230
|
-
],
|
|
231
|
-
}),
|
|
232
|
-
);
|
|
233
|
-
yield* Effect.promise(() => services.QueryService!.reindex());
|
|
234
|
-
});
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
export type AudioChunk = {
|
|
6
|
-
/**
|
|
7
|
-
* Timestamp of the beginning of the chunk.
|
|
8
|
-
*/
|
|
9
|
-
timestamp: number;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* 16-bit PCM data.
|
|
13
|
-
*/
|
|
14
|
-
data: Float64Array;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export type WavConfig = {
|
|
18
|
-
channels: number;
|
|
19
|
-
sampleRate: number;
|
|
20
|
-
bitDepthCode: string;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Records MediaStreamTrack to Uint8Array 16-bit PCM data.
|
|
25
|
-
* The data is passed to the onChunk callback with the timestamp of the chunk.
|
|
26
|
-
* All chunks are aligned and sequential.
|
|
27
|
-
* Time ─────────────────────────────────────────────────►
|
|
28
|
-
*
|
|
29
|
-
* Recording:
|
|
30
|
-
* t1 ┌──────┐
|
|
31
|
-
* t2 ┌──────┬──────┐
|
|
32
|
-
* t3 ┌──────┬──────┬──────┐
|
|
33
|
-
* t4 ┌──────┬──────┬──────┬──────┐
|
|
34
|
-
* └──────┴──────┴──────┴──────┘
|
|
35
|
-
* 1st 2nd 3rd 4th
|
|
36
|
-
* chunk chunk chunk chunk
|
|
37
|
-
*
|
|
38
|
-
*/
|
|
39
|
-
export interface AudioRecorder {
|
|
40
|
-
wavConfig: WavConfig;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Sets callback for receiving audio chunks.
|
|
44
|
-
*/
|
|
45
|
-
setOnChunk(onChunk: (chunk: AudioChunk) => void): void;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Starts the recorder.
|
|
49
|
-
*/
|
|
50
|
-
start(): Promise<void>;
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Stops the recorder.
|
|
54
|
-
*/
|
|
55
|
-
stop(): Promise<void>;
|
|
56
|
-
}
|
package/src/transcriber/index.ts
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2025 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { type IBlobEvent, type IMediaRecorder, MediaRecorder, register } from 'extendable-media-recorder';
|
|
6
|
-
import { WaveFile } from 'wavefile';
|
|
7
|
-
|
|
8
|
-
import { synchronized } from '@dxos/async';
|
|
9
|
-
import { invariant } from '@dxos/invariant';
|
|
10
|
-
import { log } from '@dxos/log';
|
|
11
|
-
import { trace } from '@dxos/tracing';
|
|
12
|
-
|
|
13
|
-
import { type AudioChunk, type AudioRecorder, type WavConfig } from './audio-recorder';
|
|
14
|
-
|
|
15
|
-
let initializingPromise: Promise<void> | undefined;
|
|
16
|
-
|
|
17
|
-
const initializeExtendableMediaRecorder = async () => {
|
|
18
|
-
const { connect } = await import('extendable-media-recorder-wav-encoder');
|
|
19
|
-
await register(await connect());
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export type MediaStreamRecorderProps = {
|
|
23
|
-
mediaStreamTrack: MediaStreamTrack;
|
|
24
|
-
config: {
|
|
25
|
-
interval: number;
|
|
26
|
-
};
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Recorder that uses the MediaContext API and AudioNode API to record audio.
|
|
31
|
-
*
|
|
32
|
-
* It records MediaStream using https://www.npmjs.com/package/extendable-media-recorder.
|
|
33
|
-
*/
|
|
34
|
-
@trace.resource()
|
|
35
|
-
export class MediaStreamRecorder implements AudioRecorder {
|
|
36
|
-
private readonly _mediaStreamTrack: MediaStreamTrack;
|
|
37
|
-
/**
|
|
38
|
-
* Default MediaRecorder implementation do not support wav encoding.
|
|
39
|
-
*/
|
|
40
|
-
private readonly _config: MediaStreamRecorderProps['config'];
|
|
41
|
-
private _mediaRecorder?: IMediaRecorder = undefined;
|
|
42
|
-
private _header?: Uint8Array = undefined;
|
|
43
|
-
private _onChunk?: (chunk: AudioChunk) => void;
|
|
44
|
-
|
|
45
|
-
constructor({ mediaStreamTrack, config }: MediaStreamRecorderProps) {
|
|
46
|
-
this._mediaStreamTrack = mediaStreamTrack;
|
|
47
|
-
this._config = config;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
get wavConfig(): WavConfig {
|
|
51
|
-
const settings = this._mediaStreamTrack.getSettings();
|
|
52
|
-
return {
|
|
53
|
-
channels: settings.channelCount ?? 1,
|
|
54
|
-
sampleRate: settings.sampleRate ?? 16000,
|
|
55
|
-
bitDepthCode: settings.sampleSize ? String(settings.sampleSize) : '16',
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
get mediaStreamTrack() {
|
|
60
|
-
return this._mediaStreamTrack;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
setOnChunk(onChunk: (chunk: AudioChunk) => void): void {
|
|
64
|
-
this._onChunk = onChunk;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
async start(): Promise<void> {
|
|
68
|
-
await (initializingPromise ??= initializeExtendableMediaRecorder()).catch((err) =>
|
|
69
|
-
log.info('initializeExtendableMediaRecorder', { err }),
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
if (!this._mediaRecorder) {
|
|
73
|
-
const stream = new MediaStream([this._mediaStreamTrack]);
|
|
74
|
-
this._mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/wav' });
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (this._mediaRecorder.state === 'recording') {
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
invariant(this._onChunk, 'MediaStreamRecorder: onChunk is not set');
|
|
81
|
-
this._mediaRecorder.ondataavailable = (event) => this._ondataavailable(event);
|
|
82
|
-
this._mediaRecorder.start(this._config.interval);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
async stop(): Promise<void> {
|
|
86
|
-
if (this._mediaRecorder?.state !== 'recording') {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
this._mediaRecorder.stop();
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
@synchronized
|
|
93
|
-
private async _ondataavailable(event: IBlobEvent): Promise<void> {
|
|
94
|
-
const blob = event.data;
|
|
95
|
-
const uint8Array = new Uint8Array(await blob.arrayBuffer());
|
|
96
|
-
|
|
97
|
-
// First chunk from the MediaRecorder has a header.
|
|
98
|
-
const isHeader =
|
|
99
|
-
uint8Array[0] === 0x52 && // R
|
|
100
|
-
uint8Array[1] === 0x49 && // I
|
|
101
|
-
uint8Array[2] === 0x46 && // F
|
|
102
|
-
uint8Array[3] === 0x46; // F
|
|
103
|
-
let wav: WaveFile;
|
|
104
|
-
|
|
105
|
-
if (isHeader) {
|
|
106
|
-
wav = new WaveFile(uint8Array);
|
|
107
|
-
this._header = uint8Array.slice(0, 44);
|
|
108
|
-
} else if (this._header) {
|
|
109
|
-
wav = new WaveFile(new Uint8Array([...this._header, ...uint8Array]));
|
|
110
|
-
} else {
|
|
111
|
-
log.warn('MediaStreamRecorder: no header');
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
this._onChunk!({
|
|
116
|
-
timestamp: Date.now(),
|
|
117
|
-
data: wav.getSamples(),
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
}
|