@bendyline/squisq-editor-react 2.13.7 → 2.13.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-2MP7QE7O.js → chunk-7MAL27C2.js} +2 -2
- package/dist/{chunk-ZS6G2P57.js → chunk-CWSV5YGZ.js} +4 -23
- package/dist/{chunk-PCIVTLQG.js → chunk-D2QFSFG2.js} +9 -2
- package/dist/{chunk-QZHUSMWA.js → chunk-F4D3VBAS.js} +1 -1
- package/dist/{chunk-LXGQA2SY.js → chunk-FOKUOC7E.js} +8 -6
- package/dist/chunk-GG35EBRB.js +25 -0
- package/dist/{chunk-WZONLKTC.js → chunk-JD7IATM6.js} +404 -215
- package/dist/{chunk-DJS5I5NO.js → chunk-PQSFLC2R.js} +1 -1
- package/dist/{chunk-K56KR27T.js → chunk-ZEWQ7DTP.js} +6 -2
- package/dist/{dictationSession-SLDNYIZ2.js → dictationSession-4JBKD5EU.js} +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +12 -10
- package/dist/narrationTimingsFromAudio-ICMDSWPI.js +158 -0
- package/dist/recorder/index.js +8 -6
- package/dist/review/index.js +1 -1
- package/dist/shell/index.d.ts +2 -2
- package/dist/shell/index.js +6 -5
- package/dist/{shell-D0XgDAZj.d.ts → shell-dM2AHXc3.d.ts} +7 -1
- package/dist/speech/index.d.ts +2 -2
- package/dist/speech/index.js +1 -1
- package/dist/{speechAudioWav-WKIQWGIJ.js → speechAudioWav-TBAG7W3V.js} +3 -1
- package/dist/styles/index.css +34 -0
- package/dist/teleprompter/index.js +3 -2
- package/dist/{types-Bi4ZVKvN.d.ts → types-BiKUg5nY.d.ts} +33 -1
- package/package.json +6 -6
|
@@ -4,6 +4,10 @@ import {
|
|
|
4
4
|
|
|
5
5
|
// src/speech/speechAudioWav.ts
|
|
6
6
|
async function microphoneTakeAsWav(blob) {
|
|
7
|
+
const samples = await decodeSpeechPcm(blob);
|
|
8
|
+
return encodeMonoPcm16Wav([samples], SPEECH_INPUT_SAMPLE_RATE).buffer;
|
|
9
|
+
}
|
|
10
|
+
async function decodeSpeechPcm(blob) {
|
|
7
11
|
const encoded = await blobBytes(blob);
|
|
8
12
|
let audio;
|
|
9
13
|
try {
|
|
@@ -17,8 +21,7 @@ async function microphoneTakeAsWav(blob) {
|
|
|
17
21
|
(_, index) => audio.getChannelData(index)
|
|
18
22
|
);
|
|
19
23
|
const mono = downmixToMono(channels);
|
|
20
|
-
|
|
21
|
-
return encodeMonoPcm16Wav([samples], SPEECH_INPUT_SAMPLE_RATE).buffer;
|
|
24
|
+
return audio.sampleRate === SPEECH_INPUT_SAMPLE_RATE ? mono : resampleLinear(mono, audio.sampleRate, SPEECH_INPUT_SAMPLE_RATE);
|
|
22
25
|
}
|
|
23
26
|
function blobBytes(blob) {
|
|
24
27
|
if (typeof blob.arrayBuffer === "function") return blob.arrayBuffer();
|
|
@@ -135,6 +138,7 @@ function writeAscii(view, offset, value) {
|
|
|
135
138
|
|
|
136
139
|
export {
|
|
137
140
|
microphoneTakeAsWav,
|
|
141
|
+
decodeSpeechPcm,
|
|
138
142
|
downmixToMono,
|
|
139
143
|
resampleLinear,
|
|
140
144
|
encodeMonoPcm16Wav
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as CodeContext, E as EditorHostMode, S as SceneTextChannel, a as CalcEngineFactory, b as EditorView$1, c as CsvSourceMeta, X as XlsxSourceMeta, F as FormulaEditRecord } from './shell-
|
|
2
|
-
export { A as ApplySourceEditsOptions, B as BlockInsertionBuilder, d as BlockInsertionContext, e as BlockPlacement, f as BlockRange, g as BlockSlice, h as BlockTagVisibility, i as CodeContextSection, j as CoverImageSaveOutput, D as DashboardImageSaveOutput, k as DocumentLinkCandidate, l as DocumentLinkProvider, m as EditorActions, n as EditorColorScheme, o as EditorContextMenuContext, p as EditorContextMenuItem, q as EditorContextMenuItemVisibility, r as EditorContextMenuProvider, s as EditorContextMenuProviderProps, t as EditorContextValue, u as EditorInsertMenuItem, v as EditorMode, w as EditorProvider, x as EditorProviderProps, y as EditorSelectionInfo, z as EditorShell, G as EditorShellProps, H as EditorState, I as FindOptions, J as FindRequest, K as FormulaSessionOptions, L as ImageDisplayMode, M as IngestedSidecar, N as InsertBlockOptions, O as LayoutMode, P as MentionCandidate, Q as MentionProvider, R as OutlineBlock, T as OutlineInsertion, U as PreviewPanel, V as PreviewPanelProps, W as RawEditor, Y as RawEditorProps, Z as ThemeInheritance, _ as ViewPreferences, $ as WriteCanvasSettings, a0 as WysiwygEditor, a1 as WysiwygEditorProps, a2 as XLSX_LOCKED_REASON, a3 as XlsxFormulaSession, a4 as applySourceEditsToText, a5 as blockInsertionPoint, a6 as createXlsxFormulaSession, a7 as getBlockSlices, a8 as headingDepthForInsertion, a9 as ingestSidecarBytes, aa as joinBlockAt, ab as lineToOffset, ac as minimalReplaceEdit, ad as normalizeSourceEdits, ae as offsetToLine, af as resolveOutlineInsertion, ag as sliceIndexAtOffset, ah as sourceOutline, ai as spliceBlock, aj as useEditorContext, ak as useEditorContextMenuItems, al as useEditorInsertMenuItems } from './shell-
|
|
1
|
+
import { C as CodeContext, E as EditorHostMode, S as SceneTextChannel, a as CalcEngineFactory, b as EditorView$1, c as CsvSourceMeta, X as XlsxSourceMeta, F as FormulaEditRecord } from './shell-dM2AHXc3.js';
|
|
2
|
+
export { A as ApplySourceEditsOptions, B as BlockInsertionBuilder, d as BlockInsertionContext, e as BlockPlacement, f as BlockRange, g as BlockSlice, h as BlockTagVisibility, i as CodeContextSection, j as CoverImageSaveOutput, D as DashboardImageSaveOutput, k as DocumentLinkCandidate, l as DocumentLinkProvider, m as EditorActions, n as EditorColorScheme, o as EditorContextMenuContext, p as EditorContextMenuItem, q as EditorContextMenuItemVisibility, r as EditorContextMenuProvider, s as EditorContextMenuProviderProps, t as EditorContextValue, u as EditorInsertMenuItem, v as EditorMode, w as EditorProvider, x as EditorProviderProps, y as EditorSelectionInfo, z as EditorShell, G as EditorShellProps, H as EditorState, I as FindOptions, J as FindRequest, K as FormulaSessionOptions, L as ImageDisplayMode, M as IngestedSidecar, N as InsertBlockOptions, O as LayoutMode, P as MentionCandidate, Q as MentionProvider, R as OutlineBlock, T as OutlineInsertion, U as PreviewPanel, V as PreviewPanelProps, W as RawEditor, Y as RawEditorProps, Z as ThemeInheritance, _ as ViewPreferences, $ as WriteCanvasSettings, a0 as WysiwygEditor, a1 as WysiwygEditorProps, a2 as XLSX_LOCKED_REASON, a3 as XlsxFormulaSession, a4 as applySourceEditsToText, a5 as blockInsertionPoint, a6 as createXlsxFormulaSession, a7 as getBlockSlices, a8 as headingDepthForInsertion, a9 as ingestSidecarBytes, aa as joinBlockAt, ab as lineToOffset, ac as minimalReplaceEdit, ad as normalizeSourceEdits, ae as offsetToLine, af as resolveOutlineInsertion, ag as sliceIndexAtOffset, ah as sourceOutline, ai as spliceBlock, aj as useEditorContext, ak as useEditorContextMenuItems, al as useEditorInsertMenuItems } from './shell-dM2AHXc3.js';
|
|
3
3
|
import * as react from 'react';
|
|
4
4
|
import { ReactNode, CSSProperties, ReactElement } from 'react';
|
|
5
5
|
import { Doc, ScheduledClip, VideoPlacement, VideoPipSize, VideoPipShape, VideoPipPosition, MediaEdits, MediaProvider, Theme, CustomTemplateDefinition, ThemeSeedColors, ViewportPreset, ViewportConfig, Block, MediaEntry, DiagramEdgeAnchor } from '@bendyline/squisq/schemas';
|
|
@@ -35,7 +35,7 @@ export { EYE_LINE_FRACTION, ExecuteNarrationSaveDeps, NarrationSavePlan, Narrati
|
|
|
35
35
|
export { H as HarperProofingConfig, a as ProofingCapability, b as ProofingDocumentRef, c as ProofingIgnoreStore, d as ProofingLanguage, e as ProofingLintOptions, P as ProofingProvider, f as ProofingProviderFactory } from './types-qxwhho3e.js';
|
|
36
36
|
export { createHarperProofingProvider } from './proofing/index.js';
|
|
37
37
|
export { PROOF_DIALECTS, PROOF_FRONTMATTER_KEYS, ProofCategory, ProofDialect, ProofFinding, ProofRange, ProofSuggestion, ProofSuggestionKind } from '@bendyline/squisq/proof';
|
|
38
|
-
export { D as DictationControl, a as SPEECH_INPUT_SAMPLE_RATE, b as SpeechInputCapability, S as SpeechInputProvider, c as SpeechInputProviderFactory, d as SpeechInputReadiness, e as SpeechInputReadinessState,
|
|
38
|
+
export { D as DictationControl, a as SPEECH_INPUT_SAMPLE_RATE, b as SpeechInputCapability, S as SpeechInputProvider, c as SpeechInputProviderFactory, d as SpeechInputReadiness, e as SpeechInputReadinessState, g as SpeechInputTranscribeOptions, h as SpeechInputTranscript, k as isSpeechInputProviderFactory, r as resolveSpeechInputProvider } from './types-BiKUg5nY.js';
|
|
39
39
|
import '@bendyline/squisq-calc';
|
|
40
40
|
import '@bendyline/squisq-formats/xlsx';
|
|
41
41
|
import '@bendyline/squisq/versions';
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
PROOF_FRONTMATTER_KEYS,
|
|
4
4
|
createHarperProofingProvider
|
|
5
5
|
} from "./chunk-VRRT4WP4.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-7MAL27C2.js";
|
|
7
7
|
import {
|
|
8
8
|
configureMonacoWorkers
|
|
9
9
|
} from "./chunk-BWPFPHWY.js";
|
|
@@ -243,7 +243,7 @@ import {
|
|
|
243
243
|
videoEmbedParagraphJson,
|
|
244
244
|
viewStateFromBinding,
|
|
245
245
|
writeHeadingViewState
|
|
246
|
-
} from "./chunk-
|
|
246
|
+
} from "./chunk-JD7IATM6.js";
|
|
247
247
|
import {
|
|
248
248
|
EditorProvider,
|
|
249
249
|
applySourceEditsToText,
|
|
@@ -264,7 +264,7 @@ import {
|
|
|
264
264
|
useBlockNavigator,
|
|
265
265
|
useEditorContext,
|
|
266
266
|
useEditorInsertMenuItems
|
|
267
|
-
} from "./chunk-
|
|
267
|
+
} from "./chunk-D2QFSFG2.js";
|
|
268
268
|
import {
|
|
269
269
|
SPEECH_INPUT_SAMPLE_RATE,
|
|
270
270
|
isSpeechInputProviderFactory,
|
|
@@ -290,7 +290,7 @@ import {
|
|
|
290
290
|
} from "./chunk-HLU6ZBS7.js";
|
|
291
291
|
import {
|
|
292
292
|
RecorderButton
|
|
293
|
-
} from "./chunk-
|
|
293
|
+
} from "./chunk-F4D3VBAS.js";
|
|
294
294
|
import {
|
|
295
295
|
RecorderDeviceQuickPicks,
|
|
296
296
|
RecorderDeviceSettingsPanel,
|
|
@@ -315,7 +315,7 @@ import {
|
|
|
315
315
|
unshownSlidesWarning,
|
|
316
316
|
useMediaDevices,
|
|
317
317
|
useMediaRecorder
|
|
318
|
-
} from "./chunk-
|
|
318
|
+
} from "./chunk-FOKUOC7E.js";
|
|
319
319
|
import {
|
|
320
320
|
DEFAULT_RECORDER_DEVICE_SETTINGS,
|
|
321
321
|
buildRecorderAudioConstraints,
|
|
@@ -329,7 +329,7 @@ import {
|
|
|
329
329
|
} from "./chunk-UYB5CPRE.js";
|
|
330
330
|
import {
|
|
331
331
|
TeleprompterView
|
|
332
|
-
} from "./chunk-
|
|
332
|
+
} from "./chunk-PQSFLC2R.js";
|
|
333
333
|
import {
|
|
334
334
|
DEFAULT_TELEPROMPTER_PREFS,
|
|
335
335
|
EYE_LINE_FRACTION,
|
|
@@ -340,11 +340,9 @@ import {
|
|
|
340
340
|
TeleprompterControls,
|
|
341
341
|
TeleprompterSurface,
|
|
342
342
|
buildNarrationSavePlan,
|
|
343
|
-
buildTimingJson,
|
|
344
343
|
cameraVideoLine,
|
|
345
344
|
createFloatingWindowManager,
|
|
346
345
|
detectFloatTiers,
|
|
347
|
-
encodeTimingJson,
|
|
348
346
|
ensureTeleprompterStyles,
|
|
349
347
|
executeNarrationSave,
|
|
350
348
|
insertNarrationPreamble,
|
|
@@ -355,7 +353,6 @@ import {
|
|
|
355
353
|
requestCameraStream,
|
|
356
354
|
stepScroll,
|
|
357
355
|
targetOffsetFor,
|
|
358
|
-
timingPathFor,
|
|
359
356
|
useFloatingWindow,
|
|
360
357
|
useMicAnalysis,
|
|
361
358
|
useNarrationRecorder,
|
|
@@ -363,7 +360,7 @@ import {
|
|
|
363
360
|
useStreamPreview,
|
|
364
361
|
useTeleprompter,
|
|
365
362
|
vadConfigForSensitivity
|
|
366
|
-
} from "./chunk-
|
|
363
|
+
} from "./chunk-CWSV5YGZ.js";
|
|
367
364
|
import {
|
|
368
365
|
buildFilename,
|
|
369
366
|
requestMicStream,
|
|
@@ -372,6 +369,11 @@ import {
|
|
|
372
369
|
supportsMediaRecorder,
|
|
373
370
|
supportsUserMedia
|
|
374
371
|
} from "./chunk-DNJ6HOES.js";
|
|
372
|
+
import {
|
|
373
|
+
buildTimingJson,
|
|
374
|
+
encodeTimingJson,
|
|
375
|
+
timingPathFor
|
|
376
|
+
} from "./chunk-GG35EBRB.js";
|
|
375
377
|
|
|
376
378
|
// src/FolderView.tsx
|
|
377
379
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SPEECH_INPUT_SAMPLE_RATE
|
|
3
|
+
} from "./chunk-DNEVUOBZ.js";
|
|
4
|
+
import {
|
|
5
|
+
encodeNarrationTimingJson,
|
|
6
|
+
timingPathFor
|
|
7
|
+
} from "./chunk-GG35EBRB.js";
|
|
8
|
+
|
|
9
|
+
// src/documentTray/narrationTimingsFromAudio.ts
|
|
10
|
+
import { markdownToDoc } from "@bendyline/squisq/doc";
|
|
11
|
+
import { parseMarkdown } from "@bendyline/squisq/markdown";
|
|
12
|
+
import {
|
|
13
|
+
alignTranscript,
|
|
14
|
+
buildNarrationScript,
|
|
15
|
+
buildNarrationTimingJson,
|
|
16
|
+
parseNarrationTimingJson
|
|
17
|
+
} from "@bendyline/squisq/narration";
|
|
18
|
+
var MAX_PIECE_SEC = 29;
|
|
19
|
+
var CUT_SEARCH_SEC = 6;
|
|
20
|
+
var CUT_FRAME_SEC = 0.05;
|
|
21
|
+
var MIN_PIECE_SEC = 1;
|
|
22
|
+
var MIN_MATCHED_SHARE = 0.2;
|
|
23
|
+
var PROMPT_TAIL_CHARS = 1e3;
|
|
24
|
+
function quietestSample(pcm, lo, hi, frame) {
|
|
25
|
+
let best = hi;
|
|
26
|
+
let bestEnergy = Number.POSITIVE_INFINITY;
|
|
27
|
+
for (let at = lo; at + frame <= hi; at += frame >> 1) {
|
|
28
|
+
let energy = 0;
|
|
29
|
+
for (let i = at; i < at + frame; i++) energy += pcm[i] * pcm[i];
|
|
30
|
+
if (energy < bestEnergy) {
|
|
31
|
+
bestEnergy = energy;
|
|
32
|
+
best = at + (frame >> 1);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return best;
|
|
36
|
+
}
|
|
37
|
+
function cutSpeechPieces(pcm, sampleRate, startSec, endSec) {
|
|
38
|
+
const end = Math.min(pcm.length, Math.max(0, Math.round(endSec * sampleRate)));
|
|
39
|
+
const max = Math.round(MAX_PIECE_SEC * sampleRate);
|
|
40
|
+
const frame = Math.max(2, Math.round(CUT_FRAME_SEC * sampleRate));
|
|
41
|
+
const pieces = [];
|
|
42
|
+
let from = Math.min(end, Math.max(0, Math.round(startSec * sampleRate)));
|
|
43
|
+
while (from < end) {
|
|
44
|
+
if (end - from <= max) {
|
|
45
|
+
pieces.push({ from, to: end });
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
const to = quietestSample(
|
|
49
|
+
pcm,
|
|
50
|
+
from + max - Math.round(CUT_SEARCH_SEC * sampleRate),
|
|
51
|
+
from + max,
|
|
52
|
+
frame
|
|
53
|
+
);
|
|
54
|
+
pieces.push({ from, to });
|
|
55
|
+
from = to;
|
|
56
|
+
}
|
|
57
|
+
const last = pieces[pieces.length - 1];
|
|
58
|
+
if (pieces.length > 1 && last && last.to - last.from < MIN_PIECE_SEC * sampleRate) {
|
|
59
|
+
pieces.pop();
|
|
60
|
+
pieces[pieces.length - 1].to = last.to;
|
|
61
|
+
}
|
|
62
|
+
return pieces;
|
|
63
|
+
}
|
|
64
|
+
function timedSegments(transcript, offsetSec, endSec) {
|
|
65
|
+
if (transcript.segments?.length) {
|
|
66
|
+
return transcript.segments.map((segment) => ({
|
|
67
|
+
text: segment.text,
|
|
68
|
+
startSec: offsetSec + segment.start,
|
|
69
|
+
endSec: offsetSec + segment.end,
|
|
70
|
+
...segment.words?.length ? {
|
|
71
|
+
words: segment.words.map((word) => ({
|
|
72
|
+
text: word.text,
|
|
73
|
+
startSec: offsetSec + word.start,
|
|
74
|
+
endSec: offsetSec + word.end
|
|
75
|
+
}))
|
|
76
|
+
} : {}
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
const text = transcript.text.trim();
|
|
80
|
+
return text ? [{ text, startSec: offsetSec, endSec }] : [];
|
|
81
|
+
}
|
|
82
|
+
async function readTake(mediaProvider, container, src) {
|
|
83
|
+
const url = await mediaProvider.resolveUrl(src);
|
|
84
|
+
if (url && url !== src) {
|
|
85
|
+
const response = await fetch(url);
|
|
86
|
+
if (response.ok) return response.blob();
|
|
87
|
+
}
|
|
88
|
+
const bytes = await container.readFile(src);
|
|
89
|
+
if (!bytes) throw new Error("The recording could not be read.");
|
|
90
|
+
return new Blob([bytes]);
|
|
91
|
+
}
|
|
92
|
+
async function updateNarrationTimingsFromAudio(input) {
|
|
93
|
+
const { src, provider, container, signal } = input;
|
|
94
|
+
const report = (phase, fraction) => input.onProgress?.({ phase, fraction });
|
|
95
|
+
const doc = markdownToDoc(parseMarkdown(input.markdownSource));
|
|
96
|
+
const clip = (doc.documentMedia ?? []).find(
|
|
97
|
+
(entry) => entry.anchor === "document" && entry.src === src
|
|
98
|
+
);
|
|
99
|
+
if (!clip) throw new Error("This recording is not the document narration.");
|
|
100
|
+
const script = buildNarrationScript(doc);
|
|
101
|
+
if (!script.tokens.some((token) => token.spoken)) {
|
|
102
|
+
throw new Error("The document has no text to match the recording against.");
|
|
103
|
+
}
|
|
104
|
+
report("reading", 0);
|
|
105
|
+
await provider.prepare?.(signal);
|
|
106
|
+
const { decodeSpeechPcm, encodeMonoPcm16Wav } = await import("./speechAudioWav-TBAG7W3V.js");
|
|
107
|
+
const pcm = await decodeSpeechPcm(await readTake(input.mediaProvider, container, src));
|
|
108
|
+
signal.throwIfAborted();
|
|
109
|
+
const rate = SPEECH_INPUT_SAMPLE_RATE;
|
|
110
|
+
const durationSec = pcm.length / rate;
|
|
111
|
+
const pieces = cutSpeechPieces(pcm, rate, clip.clipStart ?? 0, clip.clipEnd ?? durationSec);
|
|
112
|
+
if (!pieces.length) throw new Error("The recording has no audio to transcribe.");
|
|
113
|
+
const segments = [];
|
|
114
|
+
let tail = "";
|
|
115
|
+
for (const [index, piece] of pieces.entries()) {
|
|
116
|
+
report("transcribing", 0.05 + 0.9 * index / pieces.length);
|
|
117
|
+
const wav = encodeMonoPcm16Wav([pcm.subarray(piece.from, piece.to)], rate).buffer;
|
|
118
|
+
const transcript = await provider.transcribe(wav, {
|
|
119
|
+
signal,
|
|
120
|
+
timestamps: true,
|
|
121
|
+
...tail ? { prompt: tail } : {}
|
|
122
|
+
});
|
|
123
|
+
signal.throwIfAborted();
|
|
124
|
+
segments.push(...timedSegments(transcript, piece.from / rate, piece.to / rate));
|
|
125
|
+
const text = transcript.text.trim();
|
|
126
|
+
if (text) tail = `${tail} ${text}`.slice(-PROMPT_TAIL_CHARS).replace(/^\S*\s/u, "");
|
|
127
|
+
}
|
|
128
|
+
report("matching", 0.95);
|
|
129
|
+
const alignment = alignTranscript({ script, segments, durationSec });
|
|
130
|
+
if (alignment.matchedWords < Math.max(3, alignment.spokenWords * MIN_MATCHED_SHARE)) {
|
|
131
|
+
throw new Error(
|
|
132
|
+
`Only ${alignment.matchedWords} of ${alignment.spokenWords} words in the document were heard in the recording, so its timings were left unchanged.`
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
report("saving", 0.98);
|
|
136
|
+
const sidecarPath = timingPathFor(src);
|
|
137
|
+
const existing = await container.readFile(sidecarPath);
|
|
138
|
+
const previous = existing ? parseNarrationTimingJson(existing) : null;
|
|
139
|
+
const payload = buildNarrationTimingJson(script, alignment, durationSec, {
|
|
140
|
+
generator: { name: provider.id, method: "transcript-align" },
|
|
141
|
+
...previous?.cameraOffsetSec !== void 0 ? { cameraOffsetSec: previous.cameraOffsetSec } : {}
|
|
142
|
+
});
|
|
143
|
+
signal.throwIfAborted();
|
|
144
|
+
await container.writeFile(
|
|
145
|
+
sidecarPath,
|
|
146
|
+
encodeNarrationTimingJson(previous?.builds ? { ...payload, builds: previous.builds } : payload),
|
|
147
|
+
"application/json"
|
|
148
|
+
);
|
|
149
|
+
return {
|
|
150
|
+
matchedWords: alignment.matchedWords,
|
|
151
|
+
spokenWords: alignment.spokenWords,
|
|
152
|
+
sidecarPath
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
export {
|
|
156
|
+
cutSpeechPieces,
|
|
157
|
+
updateNarrationTimingsFromAudio
|
|
158
|
+
};
|
package/dist/recorder/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
RecorderButton
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-F4D3VBAS.js";
|
|
4
4
|
import {
|
|
5
5
|
RecorderDeviceQuickPicks,
|
|
6
6
|
RecorderDeviceSettingsPanel,
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
requestScreenStream,
|
|
15
15
|
useMediaDevices,
|
|
16
16
|
useMediaRecorder
|
|
17
|
-
} from "../chunk-
|
|
17
|
+
} from "../chunk-FOKUOC7E.js";
|
|
18
18
|
import {
|
|
19
19
|
DEFAULT_RECORDER_DEVICE_SETTINGS,
|
|
20
20
|
buildRecorderAudioConstraints,
|
|
@@ -25,12 +25,9 @@ import {
|
|
|
25
25
|
} from "../chunk-LRZJD5YD.js";
|
|
26
26
|
import "../chunk-UYB5CPRE.js";
|
|
27
27
|
import {
|
|
28
|
-
buildTimingJson,
|
|
29
|
-
encodeTimingJson,
|
|
30
28
|
requestCameraStream,
|
|
31
|
-
timingPathFor,
|
|
32
29
|
useStreamPreview
|
|
33
|
-
} from "../chunk-
|
|
30
|
+
} from "../chunk-CWSV5YGZ.js";
|
|
34
31
|
import {
|
|
35
32
|
buildFilename,
|
|
36
33
|
requestMicStream,
|
|
@@ -39,6 +36,11 @@ import {
|
|
|
39
36
|
supportsMediaRecorder,
|
|
40
37
|
supportsUserMedia
|
|
41
38
|
} from "../chunk-DNJ6HOES.js";
|
|
39
|
+
import {
|
|
40
|
+
buildTimingJson,
|
|
41
|
+
encodeTimingJson,
|
|
42
|
+
timingPathFor
|
|
43
|
+
} from "../chunk-GG35EBRB.js";
|
|
42
44
|
export {
|
|
43
45
|
DEFAULT_RECORDER_DEVICE_SETTINGS,
|
|
44
46
|
RecorderButton,
|
package/dist/review/index.js
CHANGED
package/dist/shell/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { h as BlockTagVisibility, k as DocumentLinkCandidate, l as DocumentLinkProvider, m as EditorActions, n as EditorColorScheme, o as EditorContextMenuContext, p as EditorContextMenuItem, q as EditorContextMenuItemVisibility, r as EditorContextMenuProvider, s as EditorContextMenuProviderProps, t as EditorContextValue, E as EditorHostMode, u as EditorInsertMenuItem, v as EditorMode, w as EditorProvider, x as EditorProviderProps, z as EditorShell, G as EditorShellProps, H as EditorState, b as EditorView, L as ImageDisplayMode, O as LayoutMode, P as MentionCandidate, Q as MentionProvider, U as PreviewPanel, V as PreviewPanelProps, W as RawEditor, Y as RawEditorProps, Z as ThemeInheritance, _ as ViewPreferences, a0 as WysiwygEditor, a1 as WysiwygEditorProps, aj as useEditorContext, ak as useEditorContextMenuItems, al as useEditorInsertMenuItems } from '../shell-
|
|
1
|
+
export { h as BlockTagVisibility, k as DocumentLinkCandidate, l as DocumentLinkProvider, m as EditorActions, n as EditorColorScheme, o as EditorContextMenuContext, p as EditorContextMenuItem, q as EditorContextMenuItemVisibility, r as EditorContextMenuProvider, s as EditorContextMenuProviderProps, t as EditorContextValue, E as EditorHostMode, u as EditorInsertMenuItem, v as EditorMode, w as EditorProvider, x as EditorProviderProps, z as EditorShell, G as EditorShellProps, H as EditorState, b as EditorView, L as ImageDisplayMode, O as LayoutMode, P as MentionCandidate, Q as MentionProvider, U as PreviewPanel, V as PreviewPanelProps, W as RawEditor, Y as RawEditorProps, Z as ThemeInheritance, _ as ViewPreferences, a0 as WysiwygEditor, a1 as WysiwygEditorProps, aj as useEditorContext, ak as useEditorContextMenuItems, al as useEditorInsertMenuItems } from '../shell-dM2AHXc3.js';
|
|
2
2
|
import 'react';
|
|
3
3
|
import '@bendyline/squisq/table';
|
|
4
4
|
import '@bendyline/squisq-calc';
|
|
@@ -11,7 +11,7 @@ import '@bendyline/squisq-react';
|
|
|
11
11
|
import '@bendyline/squisq/storage';
|
|
12
12
|
import '../types-qxwhho3e.js';
|
|
13
13
|
import '@bendyline/squisq/proof';
|
|
14
|
-
import '../types-
|
|
14
|
+
import '../types-BiKUg5nY.js';
|
|
15
15
|
import '@bendyline/squisq/versions';
|
|
16
16
|
import '@tiptap/core';
|
|
17
17
|
import 'monaco-editor';
|
package/dist/shell/index.js
CHANGED
|
@@ -5,23 +5,24 @@ import {
|
|
|
5
5
|
RawEditor,
|
|
6
6
|
WysiwygEditor,
|
|
7
7
|
useEditorContextMenuItems
|
|
8
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-JD7IATM6.js";
|
|
9
9
|
import {
|
|
10
10
|
EditorProvider,
|
|
11
11
|
useEditorContext,
|
|
12
12
|
useEditorInsertMenuItems
|
|
13
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-D2QFSFG2.js";
|
|
14
14
|
import "../chunk-DNEVUOBZ.js";
|
|
15
15
|
import "../chunk-A2H3JOA5.js";
|
|
16
16
|
import "../chunk-4MBH7MMU.js";
|
|
17
17
|
import "../chunk-ZLKINE4Y.js";
|
|
18
18
|
import "../chunk-HLU6ZBS7.js";
|
|
19
|
-
import "../chunk-
|
|
19
|
+
import "../chunk-FOKUOC7E.js";
|
|
20
20
|
import "../chunk-LRZJD5YD.js";
|
|
21
21
|
import "../chunk-UYB5CPRE.js";
|
|
22
|
-
import "../chunk-
|
|
23
|
-
import "../chunk-
|
|
22
|
+
import "../chunk-PQSFLC2R.js";
|
|
23
|
+
import "../chunk-CWSV5YGZ.js";
|
|
24
24
|
import "../chunk-DNJ6HOES.js";
|
|
25
|
+
import "../chunk-GG35EBRB.js";
|
|
25
26
|
export {
|
|
26
27
|
EditorContextMenuProvider,
|
|
27
28
|
EditorProvider,
|
|
@@ -10,7 +10,7 @@ import { FenceRendererMap } from '@bendyline/squisq/fence';
|
|
|
10
10
|
import { CodeBlockCopyHandler } from '@bendyline/squisq-react';
|
|
11
11
|
import { ContentContainer } from '@bendyline/squisq/storage';
|
|
12
12
|
import { a as ProofingCapability, c as ProofingIgnoreStore } from './types-qxwhho3e.js';
|
|
13
|
-
import { D as DictationControl, b as SpeechInputCapability } from './types-
|
|
13
|
+
import { D as DictationControl, j as SpeechRecognizerAccess, b as SpeechInputCapability } from './types-BiKUg5nY.js';
|
|
14
14
|
import { DocumentVersionManager, SaveVersionOptions, SaveVersionResult, PrunePolicy } from '@bendyline/squisq/versions';
|
|
15
15
|
import { Editor } from '@tiptap/core';
|
|
16
16
|
import { editor } from 'monaco-editor';
|
|
@@ -823,6 +823,12 @@ interface EditorContextValue extends EditorState, EditorActions {
|
|
|
823
823
|
* was injected. See docs/speech-input.md.
|
|
824
824
|
*/
|
|
825
825
|
dictation: DictationControl | null;
|
|
826
|
+
/**
|
|
827
|
+
* The same capability's resolved recognizer, for transcribing recorded
|
|
828
|
+
* audio (e.g. updating a document narration's timings). `null` when no
|
|
829
|
+
* capability was injected.
|
|
830
|
+
*/
|
|
831
|
+
speechRecognizer: SpeechRecognizerAccess | null;
|
|
826
832
|
/** The document's article id — part of the proofing document ref. */
|
|
827
833
|
articleId: string;
|
|
828
834
|
/**
|
package/dist/speech/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { R as RecorderDeviceSettings } from '../deviceSettings-BSkIQncC.js';
|
|
2
|
-
import { S as SpeechInputProvider } from '../types-
|
|
3
|
-
export { D as DictationControl, a as SPEECH_INPUT_SAMPLE_RATE, b as SpeechInputCapability, c as SpeechInputProviderFactory, d as SpeechInputReadiness, e as SpeechInputReadinessState, f as
|
|
2
|
+
import { S as SpeechInputProvider } from '../types-BiKUg5nY.js';
|
|
3
|
+
export { D as DictationControl, a as SPEECH_INPUT_SAMPLE_RATE, b as SpeechInputCapability, c as SpeechInputProviderFactory, d as SpeechInputReadiness, e as SpeechInputReadinessState, f as SpeechInputSegment, g as SpeechInputTranscribeOptions, h as SpeechInputTranscript, i as SpeechInputWord, j as SpeechRecognizerAccess, k as isSpeechInputProviderFactory, r as resolveSpeechInputProvider } from '../types-BiKUg5nY.js';
|
|
4
4
|
import '../screenRegion-Ci_RsCzG.js';
|
|
5
5
|
|
|
6
6
|
/**
|
package/dist/speech/index.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
+
decodeSpeechPcm,
|
|
2
3
|
downmixToMono,
|
|
3
4
|
encodeMonoPcm16Wav,
|
|
4
5
|
microphoneTakeAsWav,
|
|
5
6
|
resampleLinear
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ZEWQ7DTP.js";
|
|
7
8
|
import "./chunk-DNEVUOBZ.js";
|
|
8
9
|
export {
|
|
10
|
+
decodeSpeechPcm,
|
|
9
11
|
downmixToMono,
|
|
10
12
|
encodeMonoPcm16Wav,
|
|
11
13
|
microphoneTakeAsWav,
|
package/dist/styles/index.css
CHANGED
|
@@ -15143,6 +15143,40 @@ button.squisq-view-menu-radio-row:focus-visible {
|
|
|
15143
15143
|
.squisq-document-tray-detail button:hover {
|
|
15144
15144
|
background: var(--squisq-danger-soft);
|
|
15145
15145
|
}
|
|
15146
|
+
.squisq-document-tray-timing {
|
|
15147
|
+
display: flex;
|
|
15148
|
+
flex-wrap: wrap;
|
|
15149
|
+
align-items: center;
|
|
15150
|
+
gap: 6px 10px;
|
|
15151
|
+
margin-top: 8px;
|
|
15152
|
+
color: var(--squisq-text-muted);
|
|
15153
|
+
font-size: 12px;
|
|
15154
|
+
}
|
|
15155
|
+
.squisq-document-tray-timing button {
|
|
15156
|
+
flex-shrink: 0;
|
|
15157
|
+
border: 1px solid var(--squisq-border);
|
|
15158
|
+
border-radius: 4px;
|
|
15159
|
+
padding: 4px 10px;
|
|
15160
|
+
background: var(--squisq-surface);
|
|
15161
|
+
color: var(--squisq-text-soft);
|
|
15162
|
+
font: inherit;
|
|
15163
|
+
cursor: pointer;
|
|
15164
|
+
}
|
|
15165
|
+
.squisq-document-tray-timing button:hover {
|
|
15166
|
+
background: var(--squisq-surface-hover);
|
|
15167
|
+
}
|
|
15168
|
+
.squisq-document-tray-timing button:focus-visible {
|
|
15169
|
+
outline: 2px solid var(--squisq-accent);
|
|
15170
|
+
outline-offset: 2px;
|
|
15171
|
+
}
|
|
15172
|
+
.squisq-document-tray-timing progress {
|
|
15173
|
+
flex: 1 1 120px;
|
|
15174
|
+
max-width: 240px;
|
|
15175
|
+
accent-color: var(--squisq-accent);
|
|
15176
|
+
}
|
|
15177
|
+
.squisq-document-tray-timing-error {
|
|
15178
|
+
color: var(--squisq-danger-strong);
|
|
15179
|
+
}
|
|
15146
15180
|
|
|
15147
15181
|
/* src/styles/code-context.css */
|
|
15148
15182
|
.squisq-ccx-zone {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
TeleprompterView
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-PQSFLC2R.js";
|
|
4
4
|
import {
|
|
5
5
|
DEFAULT_TELEPROMPTER_PREFS,
|
|
6
6
|
EYE_LINE_FRACTION,
|
|
@@ -31,8 +31,9 @@ import {
|
|
|
31
31
|
useNarrationStage,
|
|
32
32
|
useTeleprompter,
|
|
33
33
|
vadConfigForSensitivity
|
|
34
|
-
} from "../chunk-
|
|
34
|
+
} from "../chunk-CWSV5YGZ.js";
|
|
35
35
|
import "../chunk-DNJ6HOES.js";
|
|
36
|
+
import "../chunk-GG35EBRB.js";
|
|
36
37
|
export {
|
|
37
38
|
DEFAULT_TELEPROMPTER_PREFS,
|
|
38
39
|
EYE_LINE_FRACTION,
|
|
@@ -48,15 +48,36 @@ interface SpeechInputTranscribeOptions {
|
|
|
48
48
|
readonly prompt?: string;
|
|
49
49
|
/** BCP-47-ish language hint. The editor does not currently set it. */
|
|
50
50
|
readonly language?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Ask for {@link SpeechInputTranscript.segments} with times (and word times
|
|
53
|
+
* where the engine has them). Set when timing narration from its audio;
|
|
54
|
+
* dictation leaves it off. A provider that cannot time its output ignores it.
|
|
55
|
+
*/
|
|
56
|
+
readonly timestamps?: boolean;
|
|
51
57
|
/**
|
|
52
58
|
* Aborted when the user cancels dictation or the editor unmounts. A
|
|
53
59
|
* provider should stop promptly; a rejection after abort is ignored.
|
|
54
60
|
*/
|
|
55
61
|
readonly signal: AbortSignal;
|
|
56
62
|
}
|
|
63
|
+
/** A recognized word, in seconds from the start of the take. */
|
|
64
|
+
interface SpeechInputWord {
|
|
65
|
+
readonly start: number;
|
|
66
|
+
readonly end: number;
|
|
67
|
+
readonly text: string;
|
|
68
|
+
}
|
|
69
|
+
/** A recognized phrase, in seconds from the start of the take. */
|
|
70
|
+
interface SpeechInputSegment {
|
|
71
|
+
readonly start: number;
|
|
72
|
+
readonly end: number;
|
|
73
|
+
readonly text: string;
|
|
74
|
+
readonly words?: readonly SpeechInputWord[];
|
|
75
|
+
}
|
|
57
76
|
interface SpeechInputTranscript {
|
|
58
77
|
/** Recognized text. Blank (or Whisper's `[BLANK_AUDIO]`) means silence. */
|
|
59
78
|
readonly text: string;
|
|
79
|
+
/** Timed phrases, when `timestamps` was requested and the engine supports it. */
|
|
80
|
+
readonly segments?: readonly SpeechInputSegment[];
|
|
60
81
|
}
|
|
61
82
|
interface SpeechInputProvider {
|
|
62
83
|
/** Stable identifier, e.g. `whisper-local`. */
|
|
@@ -80,6 +101,17 @@ interface SpeechInputProvider {
|
|
|
80
101
|
/** Release resources. Called by the editor only for a provider it created from a factory. */
|
|
81
102
|
dispose?(): void;
|
|
82
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* The host's resolved recognizer on the editor context
|
|
106
|
+
* (`useEditorContext().speechRecognizer`), for features beyond dictation that
|
|
107
|
+
* transcribe recorded audio — e.g. timing a document narration from its take.
|
|
108
|
+
* `null` when the host injected no `speechInput` capability.
|
|
109
|
+
*/
|
|
110
|
+
interface SpeechRecognizerAccess {
|
|
111
|
+
readonly provider: SpeechInputProvider;
|
|
112
|
+
/** Last known readiness; `null` until the provider first answers. */
|
|
113
|
+
readonly readiness: SpeechInputReadiness | null;
|
|
114
|
+
}
|
|
83
115
|
/**
|
|
84
116
|
* Deferred construction. The shell creates the provider when it mounts with
|
|
85
117
|
* the capability (it needs `status()` to decide whether to render the
|
|
@@ -123,4 +155,4 @@ interface DictationControl {
|
|
|
123
155
|
toggle(): void;
|
|
124
156
|
}
|
|
125
157
|
|
|
126
|
-
export { type DictationControl as D, type SpeechInputProvider as S, SPEECH_INPUT_SAMPLE_RATE as a, type SpeechInputCapability as b, type SpeechInputProviderFactory as c, type SpeechInputReadiness as d, type SpeechInputReadinessState as e, type
|
|
158
|
+
export { type DictationControl as D, type SpeechInputProvider as S, SPEECH_INPUT_SAMPLE_RATE as a, type SpeechInputCapability as b, type SpeechInputProviderFactory as c, type SpeechInputReadiness as d, type SpeechInputReadinessState as e, type SpeechInputSegment as f, type SpeechInputTranscribeOptions as g, type SpeechInputTranscript as h, type SpeechInputWord as i, type SpeechRecognizerAccess as j, isSpeechInputProviderFactory as k, resolveSpeechInputProvider as r };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bendyline/squisq-editor-react",
|
|
3
|
-
"version": "2.13.
|
|
3
|
+
"version": "2.13.9",
|
|
4
4
|
"description": "React editor shell with raw/WYSIWYG/preview modes for Squisq documents",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Bendyline",
|
|
@@ -102,12 +102,12 @@
|
|
|
102
102
|
}
|
|
103
103
|
},
|
|
104
104
|
"dependencies": {
|
|
105
|
-
"@bendyline/squisq": "2.13.
|
|
105
|
+
"@bendyline/squisq": "2.13.6",
|
|
106
106
|
"@bendyline/squisq-calc": "2.11.2",
|
|
107
|
-
"@bendyline/squisq-formats": "2.8.
|
|
108
|
-
"@bendyline/squisq-grid-react": "2.11.
|
|
109
|
-
"@bendyline/squisq-react": "2.12.
|
|
110
|
-
"@bendyline/squisq-video-react": "2.5.
|
|
107
|
+
"@bendyline/squisq-formats": "2.8.7",
|
|
108
|
+
"@bendyline/squisq-grid-react": "2.11.35",
|
|
109
|
+
"@bendyline/squisq-react": "2.12.16",
|
|
110
|
+
"@bendyline/squisq-video-react": "2.5.17",
|
|
111
111
|
"@fortawesome/fontawesome-free": "7.3.1",
|
|
112
112
|
"@tiptap/core": "2.27.3",
|
|
113
113
|
"@tiptap/extension-heading": "2.27.3",
|