@dxos/plugin-transcription 0.8.0 → 0.8.1-main.ae460ac

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.
Files changed (72) hide show
  1. package/dist/lib/browser/{TranscriptContainer-SX6PNFEC.mjs → TranscriptContainer-N4KQHMY4.mjs} +2 -2
  2. package/dist/lib/browser/{chunk-AS364WZZ.mjs → chunk-BDVUIRBP.mjs} +2 -2
  3. package/dist/lib/browser/chunk-GHTRJTEB.mjs +35 -0
  4. package/dist/lib/browser/chunk-GHTRJTEB.mjs.map +7 -0
  5. package/dist/lib/browser/{chunk-R4HHS6FA.mjs → chunk-YX447BJ4.mjs} +16 -16
  6. package/dist/lib/browser/chunk-YX447BJ4.mjs.map +7 -0
  7. package/dist/lib/browser/index.mjs +180 -72
  8. package/dist/lib/browser/index.mjs.map +4 -4
  9. package/dist/lib/browser/{intent-resolver-EAR2TFK2.mjs → intent-resolver-RW6DEJC2.mjs} +2 -2
  10. package/dist/lib/browser/meta.json +1 -1
  11. package/dist/lib/browser/{react-surface-FOEWLLTZ.mjs → react-surface-UPTZBHVB.mjs} +3 -3
  12. package/dist/lib/node/{TranscriptContainer-HU763SN3.cjs → TranscriptContainer-4BWXOVML.cjs} +7 -7
  13. package/dist/lib/node/{TranscriptContainer-HU763SN3.cjs.map → TranscriptContainer-4BWXOVML.cjs.map} +2 -2
  14. package/dist/lib/node/{chunk-YV74Z74I.cjs → chunk-ANSWGFMS.cjs} +18 -18
  15. package/dist/lib/node/chunk-ANSWGFMS.cjs.map +7 -0
  16. package/dist/lib/node/{chunk-JBN3P6ZF.cjs → chunk-HDRXDMK2.cjs} +4 -46
  17. package/dist/lib/node/chunk-HDRXDMK2.cjs.map +7 -0
  18. package/dist/lib/node/{chunk-QWXLQPP5.cjs → chunk-I35KHI2G.cjs} +5 -5
  19. package/dist/lib/node/index.cjs +182 -74
  20. package/dist/lib/node/index.cjs.map +4 -4
  21. package/dist/lib/node/{intent-resolver-3KJZGGUQ.cjs → intent-resolver-KLBZ25XJ.cjs} +7 -7
  22. package/dist/lib/node/meta.json +1 -1
  23. package/dist/lib/node/{react-surface-AGGGDOUC.cjs → react-surface-NCKXB7EQ.cjs} +7 -7
  24. package/dist/lib/node-esm/{TranscriptContainer-DVBXQIQ4.mjs → TranscriptContainer-6IKRASR6.mjs} +2 -2
  25. package/dist/lib/node-esm/{chunk-WEZGRUG6.mjs → chunk-2CPKXRN6.mjs} +2 -2
  26. package/dist/lib/node-esm/chunk-LORUIVS4.mjs +37 -0
  27. package/dist/lib/node-esm/chunk-LORUIVS4.mjs.map +7 -0
  28. package/dist/lib/node-esm/{chunk-36EQXBWR.mjs → chunk-ZMK2QLW2.mjs} +16 -16
  29. package/dist/lib/node-esm/chunk-ZMK2QLW2.mjs.map +7 -0
  30. package/dist/lib/node-esm/index.mjs +180 -72
  31. package/dist/lib/node-esm/index.mjs.map +4 -4
  32. package/dist/lib/node-esm/{intent-resolver-UGLYRD4X.mjs → intent-resolver-4FMISUPW.mjs} +2 -2
  33. package/dist/lib/node-esm/meta.json +1 -1
  34. package/dist/lib/node-esm/{react-surface-6AYPLJ2B.mjs → react-surface-2WJQ67LB.mjs} +3 -3
  35. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  36. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  37. package/dist/types/src/hooks/index.d.ts +0 -1
  38. package/dist/types/src/hooks/index.d.ts.map +1 -1
  39. package/dist/types/src/index.d.ts +1 -0
  40. package/dist/types/src/index.d.ts.map +1 -1
  41. package/dist/types/src/transcriber/media-stream-recorder.d.ts +1 -0
  42. package/dist/types/src/transcriber/media-stream-recorder.d.ts.map +1 -1
  43. package/dist/types/src/transcription-manager.d.ts +36 -0
  44. package/dist/types/src/transcription-manager.d.ts.map +1 -0
  45. package/package.json +36 -36
  46. package/src/components/TranscriptContainer.tsx +11 -15
  47. package/src/hooks/index.ts +0 -1
  48. package/src/index.ts +1 -0
  49. package/src/transcriber/media-stream-recorder.ts +4 -0
  50. package/src/transcription-manager.ts +173 -0
  51. package/dist/lib/browser/chunk-R4HHS6FA.mjs.map +0 -7
  52. package/dist/lib/browser/chunk-ZMES3U2D.mjs +0 -78
  53. package/dist/lib/browser/chunk-ZMES3U2D.mjs.map +0 -7
  54. package/dist/lib/node/chunk-JBN3P6ZF.cjs.map +0 -7
  55. package/dist/lib/node/chunk-YV74Z74I.cjs.map +0 -7
  56. package/dist/lib/node-esm/chunk-36EQXBWR.mjs.map +0 -7
  57. package/dist/lib/node-esm/chunk-XYU6B73V.mjs +0 -80
  58. package/dist/lib/node-esm/chunk-XYU6B73V.mjs.map +0 -7
  59. package/dist/types/src/hooks/useIsSpeaking.d.ts +0 -2
  60. package/dist/types/src/hooks/useIsSpeaking.d.ts.map +0 -1
  61. package/src/hooks/useIsSpeaking.ts +0 -77
  62. /package/dist/lib/browser/{TranscriptContainer-SX6PNFEC.mjs.map → TranscriptContainer-N4KQHMY4.mjs.map} +0 -0
  63. /package/dist/lib/browser/{chunk-AS364WZZ.mjs.map → chunk-BDVUIRBP.mjs.map} +0 -0
  64. /package/dist/lib/browser/{intent-resolver-EAR2TFK2.mjs.map → intent-resolver-RW6DEJC2.mjs.map} +0 -0
  65. /package/dist/lib/browser/{react-surface-FOEWLLTZ.mjs.map → react-surface-UPTZBHVB.mjs.map} +0 -0
  66. /package/dist/lib/node/{chunk-QWXLQPP5.cjs.map → chunk-I35KHI2G.cjs.map} +0 -0
  67. /package/dist/lib/node/{intent-resolver-3KJZGGUQ.cjs.map → intent-resolver-KLBZ25XJ.cjs.map} +0 -0
  68. /package/dist/lib/node/{react-surface-AGGGDOUC.cjs.map → react-surface-NCKXB7EQ.cjs.map} +0 -0
  69. /package/dist/lib/node-esm/{TranscriptContainer-DVBXQIQ4.mjs.map → TranscriptContainer-6IKRASR6.mjs.map} +0 -0
  70. /package/dist/lib/node-esm/{chunk-WEZGRUG6.mjs.map → chunk-2CPKXRN6.mjs.map} +0 -0
  71. /package/dist/lib/node-esm/{intent-resolver-UGLYRD4X.mjs.map → intent-resolver-4FMISUPW.mjs.map} +0 -0
  72. /package/dist/lib/node-esm/{react-surface-6AYPLJ2B.mjs.map → react-surface-2WJQ67LB.mjs.map} +0 -0
@@ -1,80 +0,0 @@
1
- import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
-
3
- // packages/plugins/experimental/plugin-transcription/src/util/get-time-str.ts
4
- var getTimeStr = (timestamp) => new Date(timestamp ?? Date.now()).toLocaleTimeString("en-US", {
5
- timeZone: "UTC",
6
- hour12: true,
7
- hour: "numeric",
8
- minute: "2-digit",
9
- second: "2-digit"
10
- });
11
-
12
- // packages/plugins/experimental/plugin-transcription/src/util/random-queue-dxn.ts
13
- import { ObjectId } from "@dxos/echo-schema";
14
- import { DXN, QueueSubspaceTags, SpaceId } from "@dxos/keys";
15
- var randomQueueDxn = () => new DXN(DXN.kind.QUEUE, [
16
- QueueSubspaceTags.DATA,
17
- SpaceId.random(),
18
- ObjectId.random()
19
- ]);
20
-
21
- // packages/plugins/experimental/plugin-transcription/src/util/array.ts
22
- var mergeFloat64Arrays = (arrays) => {
23
- const newArray = new Float64Array(arrays.reduce((acc, array) => array.length + acc, 0));
24
- let offset = 0;
25
- for (const array of arrays) {
26
- newArray.set(array, offset);
27
- offset += array.length;
28
- }
29
- return newArray;
30
- };
31
-
32
- // packages/plugins/experimental/plugin-transcription/src/util/monitor-audio-level.ts
33
- var monitorAudioLevel = ({ mediaStreamTrack, onMeasure, intervalMs = 1e3 / 10 }) => {
34
- let timeout = -1;
35
- let interval = -1;
36
- const audioContext = new AudioContext();
37
- const stream = new MediaStream();
38
- stream.addTrack(mediaStreamTrack);
39
- const mediaStreamAudioSourceNode = audioContext.createMediaStreamSource(stream);
40
- const analyserNode = audioContext.createAnalyser();
41
- mediaStreamAudioSourceNode.connect(analyserNode);
42
- analyserNode.fftSize = 32;
43
- const pcmData = new Float32Array(analyserNode.fftSize);
44
- let peak = 0;
45
- interval = window.setInterval(() => {
46
- onMeasure(peak);
47
- peak = 0;
48
- }, intervalMs);
49
- const tick = () => {
50
- timeout = window.setTimeout(() => {
51
- analyserNode.getFloatTimeDomainData(pcmData);
52
- let sumSquares = 0;
53
- for (const amplitude of pcmData) {
54
- sumSquares += amplitude * amplitude;
55
- }
56
- const current = Math.sqrt(sumSquares / pcmData.length);
57
- if (current > peak) {
58
- peak = current;
59
- }
60
- tick();
61
- }, intervalMs);
62
- };
63
- tick();
64
- return () => {
65
- mediaStreamAudioSourceNode.disconnect();
66
- analyserNode.disconnect();
67
- void audioContext.close();
68
- clearInterval(interval);
69
- clearTimeout(timeout);
70
- stream.removeTrack(mediaStreamTrack);
71
- };
72
- };
73
-
74
- export {
75
- mergeFloat64Arrays,
76
- getTimeStr,
77
- monitorAudioLevel,
78
- randomQueueDxn
79
- };
80
- //# sourceMappingURL=chunk-XYU6B73V.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/util/get-time-str.ts", "../../../src/util/random-queue-dxn.ts", "../../../src/util/array.ts", "../../../src/util/monitor-audio-level.ts"],
4
- "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nexport const getTimeStr = (timestamp?: number) =>\n new Date(timestamp ?? Date.now()).toLocaleTimeString('en-US', {\n timeZone: 'UTC',\n hour12: true,\n hour: 'numeric',\n minute: '2-digit',\n second: '2-digit',\n });\n", "//\n// Copyright 2025 DXOS.org\n//\n\nimport { ObjectId } from '@dxos/echo-schema';\nimport { DXN, QueueSubspaceTags, SpaceId } from '@dxos/keys';\n\nexport const randomQueueDxn = () =>\n new DXN(DXN.kind.QUEUE, [QueueSubspaceTags.DATA, SpaceId.random(), ObjectId.random()]);\n", "//\n// Copyright 2025 DXOS.org\n//\n\nexport const mergeFloat64Arrays = (arrays: Float64Array[]) => {\n const newArray = new Float64Array(arrays.reduce((acc, array) => array.length + acc, 0));\n let offset = 0;\n for (const array of arrays) {\n newArray.set(array, offset);\n offset += array.length;\n }\n\n return newArray;\n};\n", "//\n// Copyright 2025 DXOS.org\n//\n\nexport const monitorAudioLevel = ({\n mediaStreamTrack,\n onMeasure,\n intervalMs = 1000 / 10, // 12 fps.\n}: {\n mediaStreamTrack: MediaStreamTrack;\n onMeasure: (value: number) => void;\n intervalMs?: number;\n}) => {\n let timeout = -1;\n let interval = -1;\n const audioContext = new AudioContext();\n const stream = new MediaStream();\n stream.addTrack(mediaStreamTrack);\n const mediaStreamAudioSourceNode = audioContext.createMediaStreamSource(stream);\n const analyserNode = audioContext.createAnalyser();\n mediaStreamAudioSourceNode.connect(analyserNode);\n // Since we just need a rough approximation and will be measuring\n // frequently, we want to drop this down from the default of 2048.\n analyserNode.fftSize = 32;\n\n const pcmData = new Float32Array(analyserNode.fftSize);\n let peak = 0;\n\n interval = window.setInterval(() => {\n onMeasure(peak);\n peak = 0;\n }, intervalMs);\n\n const tick = () => {\n timeout = window.setTimeout(() => {\n analyserNode.getFloatTimeDomainData(pcmData);\n let sumSquares = 0.0;\n for (const amplitude of pcmData) {\n sumSquares += amplitude * amplitude;\n }\n const current = Math.sqrt(sumSquares / pcmData.length);\n if (current > peak) {\n peak = current;\n }\n tick();\n }, intervalMs);\n };\n tick();\n\n return () => {\n mediaStreamAudioSourceNode.disconnect();\n analyserNode.disconnect();\n void audioContext.close();\n clearInterval(interval);\n clearTimeout(timeout);\n stream.removeTrack(mediaStreamTrack);\n };\n};\n"],
5
- "mappings": ";;;AAIO,IAAMA,aAAa,CAACC,cACzB,IAAIC,KAAKD,aAAaC,KAAKC,IAAG,CAAA,EAAIC,mBAAmB,SAAS;EAC5DC,UAAU;EACVC,QAAQ;EACRC,MAAM;EACNC,QAAQ;EACRC,QAAQ;AACV,CAAA;;;ACPF,SAASC,gBAAgB;AACzB,SAASC,KAAKC,mBAAmBC,eAAe;AAEzC,IAAMC,iBAAiB,MAC5B,IAAIC,IAAIA,IAAIC,KAAKC,OAAO;EAACC,kBAAkBC;EAAMC,QAAQC,OAAM;EAAIC,SAASD,OAAM;CAAG;;;ACJhF,IAAME,qBAAqB,CAACC,WAAAA;AACjC,QAAMC,WAAW,IAAIC,aAAaF,OAAOG,OAAO,CAACC,KAAKC,UAAUA,MAAMC,SAASF,KAAK,CAAA,CAAA;AACpF,MAAIG,SAAS;AACb,aAAWF,SAASL,QAAQ;AAC1BC,aAASO,IAAIH,OAAOE,MAAAA;AACpBA,cAAUF,MAAMC;EAClB;AAEA,SAAOL;AACT;;;ACTO,IAAMQ,oBAAoB,CAAC,EAChCC,kBACAC,WACAC,aAAa,MAAO,GAAE,MAKvB;AACC,MAAIC,UAAU;AACd,MAAIC,WAAW;AACf,QAAMC,eAAe,IAAIC,aAAAA;AACzB,QAAMC,SAAS,IAAIC,YAAAA;AACnBD,SAAOE,SAAST,gBAAAA;AAChB,QAAMU,6BAA6BL,aAAaM,wBAAwBJ,MAAAA;AACxE,QAAMK,eAAeP,aAAaQ,eAAc;AAChDH,6BAA2BI,QAAQF,YAAAA;AAGnCA,eAAaG,UAAU;AAEvB,QAAMC,UAAU,IAAIC,aAAaL,aAAaG,OAAO;AACrD,MAAIG,OAAO;AAEXd,aAAWe,OAAOC,YAAY,MAAA;AAC5BnB,cAAUiB,IAAAA;AACVA,WAAO;EACT,GAAGhB,UAAAA;AAEH,QAAMmB,OAAO,MAAA;AACXlB,cAAUgB,OAAOG,WAAW,MAAA;AAC1BV,mBAAaW,uBAAuBP,OAAAA;AACpC,UAAIQ,aAAa;AACjB,iBAAWC,aAAaT,SAAS;AAC/BQ,sBAAcC,YAAYA;MAC5B;AACA,YAAMC,UAAUC,KAAKC,KAAKJ,aAAaR,QAAQa,MAAM;AACrD,UAAIH,UAAUR,MAAM;AAClBA,eAAOQ;MACT;AACAL,WAAAA;IACF,GAAGnB,UAAAA;EACL;AACAmB,OAAAA;AAEA,SAAO,MAAA;AACLX,+BAA2BoB,WAAU;AACrClB,iBAAakB,WAAU;AACvB,SAAKzB,aAAa0B,MAAK;AACvBC,kBAAc5B,QAAAA;AACd6B,iBAAa9B,OAAAA;AACbI,WAAO2B,YAAYlC,gBAAAA;EACrB;AACF;",
6
- "names": ["getTimeStr", "timestamp", "Date", "now", "toLocaleTimeString", "timeZone", "hour12", "hour", "minute", "second", "ObjectId", "DXN", "QueueSubspaceTags", "SpaceId", "randomQueueDxn", "DXN", "kind", "QUEUE", "QueueSubspaceTags", "DATA", "SpaceId", "random", "ObjectId", "mergeFloat64Arrays", "arrays", "newArray", "Float64Array", "reduce", "acc", "array", "length", "offset", "set", "monitorAudioLevel", "mediaStreamTrack", "onMeasure", "intervalMs", "timeout", "interval", "audioContext", "AudioContext", "stream", "MediaStream", "addTrack", "mediaStreamAudioSourceNode", "createMediaStreamSource", "analyserNode", "createAnalyser", "connect", "fftSize", "pcmData", "Float32Array", "peak", "window", "setInterval", "tick", "setTimeout", "getFloatTimeDomainData", "sumSquares", "amplitude", "current", "Math", "sqrt", "length", "disconnect", "close", "clearInterval", "clearTimeout", "removeTrack"]
7
- }
@@ -1,2 +0,0 @@
1
- export declare const useIsSpeaking: (mediaStreamTrack?: MediaStreamTrack) => boolean;
2
- //# sourceMappingURL=useIsSpeaking.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useIsSpeaking.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useIsSpeaking.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,aAAa,sBAAuB,gBAAgB,YAoEhE,CAAC"}
@@ -1,77 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import { useEffect, useRef, useState } from 'react';
6
-
7
- import { monitorAudioLevel } from '../util';
8
-
9
- export const useIsSpeaking = (mediaStreamTrack?: MediaStreamTrack) => {
10
- const [isSpeaking, setIsSpeaking] = useState(false);
11
-
12
- // The audio level is monitored very rapidly, and we don't want
13
- // react involved in tracking the state because it causes way
14
- // too many re-renders. To work around this, we use the isSpeakingRef
15
- // to track the state and then sync it using another effect.
16
- const isSpeakingRef = useRef(isSpeaking);
17
-
18
- // this effect syncs the state on a 50ms interval
19
- useEffect(() => {
20
- if (!mediaStreamTrack) {
21
- setIsSpeaking(false);
22
- return;
23
- }
24
-
25
- isSpeakingRef.current = isSpeaking;
26
- const interval = window.setInterval(() => {
27
- // state is already in sync do nothing
28
- if (isSpeaking === isSpeakingRef.current) {
29
- return;
30
- }
31
-
32
- // sync state
33
- setIsSpeaking(isSpeakingRef.current);
34
- }, 50);
35
-
36
- return () => {
37
- clearInterval(interval);
38
- };
39
- }, [isSpeaking, isSpeakingRef, mediaStreamTrack]);
40
-
41
- useEffect(() => {
42
- if (!mediaStreamTrack) {
43
- return;
44
- }
45
-
46
- let timeout = -1;
47
- const cleanup = monitorAudioLevel({
48
- mediaStreamTrack,
49
- onMeasure: (vol) => {
50
- // Once the user has been determined to be speaking, we want
51
- // to lower the threshold because speech patterns don't always
52
- // kick up above 0.05
53
- const audioLevelAboveThreshold = vol > (isSpeakingRef.current ? 0.02 : 0.05);
54
- if (audioLevelAboveThreshold) {
55
- // user is still speaking, clear timeout & reset.
56
- clearTimeout(timeout);
57
- timeout = -1;
58
- // track state.
59
- isSpeakingRef.current = true;
60
- } else if (timeout === -1) {
61
- // user is not speaking and timeout is not set.
62
- timeout = window.setTimeout(() => {
63
- isSpeakingRef.current = false;
64
- // reset timeout
65
- timeout = -1;
66
- }, 1_000);
67
- }
68
- },
69
- });
70
-
71
- return () => {
72
- cleanup();
73
- };
74
- }, [isSpeaking, mediaStreamTrack]);
75
-
76
- return isSpeaking;
77
- };