@bendyline/squisq 2.13.5 → 2.13.6
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-F5WTRHWL.js → chunk-4O26IMVA.js} +149 -9
- package/dist/{chunk-FSZ6HB7S.js → chunk-B2MOGSWY.js} +331 -1
- package/dist/{chunk-CZHWFQ7C.js → chunk-CSR6VCSJ.js} +1 -0
- package/dist/{chunk-K75GTKSN.js → chunk-FGN4OZVK.js} +3 -3
- package/dist/{chunk-ZF4NWRZU.js → chunk-VQXOX3YN.js} +31 -6
- package/dist/doc/index.js +4 -4
- package/dist/index.d.ts +2 -2
- package/dist/index.js +11 -5
- package/dist/narration/index.d.ts +59 -2
- package/dist/narration/index.js +7 -3
- package/dist/recommend/index.js +1 -1
- package/dist/transform/index.d.ts +23 -2
- package/dist/transform/index.js +5 -3
- package/package.json +1 -1
|
@@ -4,15 +4,21 @@ import {
|
|
|
4
4
|
flattenRenderableBlocks,
|
|
5
5
|
getPinnedBlockMeta,
|
|
6
6
|
markdownToDoc
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-VQXOX3YN.js";
|
|
8
8
|
import {
|
|
9
9
|
deriveTemplateInputs,
|
|
10
|
+
extractEmbeddedVideos,
|
|
10
11
|
extractImages,
|
|
11
12
|
isAsciiDiagramFence,
|
|
12
13
|
isAsciiTimelineFence,
|
|
14
|
+
isExplicitDiagramLang,
|
|
15
|
+
isExplicitTimelineLang,
|
|
16
|
+
isExplicitTreeLang,
|
|
13
17
|
isPictureFence,
|
|
18
|
+
isPictureParagraph,
|
|
19
|
+
isStandaloneHtmlVideo,
|
|
14
20
|
isTreeFence
|
|
15
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-CSR6VCSJ.js";
|
|
16
22
|
import {
|
|
17
23
|
extractContent,
|
|
18
24
|
mapElementToBlock,
|
|
@@ -20,6 +26,7 @@ import {
|
|
|
20
26
|
} from "./chunk-SVN7T6BK.js";
|
|
21
27
|
import {
|
|
22
28
|
cloneAndFreezeData,
|
|
29
|
+
cloneData,
|
|
23
30
|
isTemplateBlock
|
|
24
31
|
} from "./chunk-WNEH3BZP.js";
|
|
25
32
|
import {
|
|
@@ -30,7 +37,9 @@ import {
|
|
|
30
37
|
} from "./chunk-DOOUVVOM.js";
|
|
31
38
|
import {
|
|
32
39
|
extractPlainText,
|
|
40
|
+
findBlockVideoEmbed,
|
|
33
41
|
getChildren,
|
|
42
|
+
parseTimeSeconds,
|
|
34
43
|
stringifyHtmlNodes
|
|
35
44
|
} from "./chunk-KVEOD57Z.js";
|
|
36
45
|
import {
|
|
@@ -57,7 +66,8 @@ var PRESENTATION_LAYOUTS = [
|
|
|
57
66
|
var PRESENTATION_LIMITS = {
|
|
58
67
|
sourceCharacters: 4e4,
|
|
59
68
|
beats: 80,
|
|
60
|
-
serializedCharacters: 16e4
|
|
69
|
+
serializedCharacters: 16e4,
|
|
70
|
+
mediaPerBeat: 4
|
|
61
71
|
};
|
|
62
72
|
function record(value) {
|
|
63
73
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
@@ -90,13 +100,15 @@ function parsePresentationPlan(input) {
|
|
|
90
100
|
if (!record(beat) || !keys(
|
|
91
101
|
beat,
|
|
92
102
|
["id", "sourceStart", "sourceEnd", "layout", "headline", "points"],
|
|
93
|
-
["imageSrc"]
|
|
103
|
+
["imageSrc", "media"]
|
|
94
104
|
) || !text(beat.id, 80) || ids.has(beat.id) || !Number.isInteger(beat.sourceStart) || !Number.isInteger(beat.sourceEnd) || typeof beat.sourceStart !== "number" || typeof beat.sourceEnd !== "number" || beat.sourceStart < end || beat.sourceEnd <= beat.sourceStart || beat.sourceEnd > value.sourceText.length || value.sourceText.slice(end, beat.sourceStart).trim() || !PRESENTATION_LAYOUTS.includes(beat.layout) || !text(beat.headline, 110) || !Array.isArray(beat.points) || beat.points.length > 4 || !beat.points.every((point) => text(point, 180)))
|
|
95
105
|
return null;
|
|
96
106
|
if (["comparison", "steps", "list"].includes(String(beat.layout)) && beat.points.length < 2)
|
|
97
107
|
return null;
|
|
98
108
|
if (beat.layout === "comparison" && beat.points.length !== 2) return null;
|
|
99
109
|
if (beat.layout === "image" ? !text(beat.imageSrc, 2048) : "imageSrc" in beat) return null;
|
|
110
|
+
if ("media" in beat && (!Array.isArray(beat.media) || !beat.media.length || beat.media.length > PRESENTATION_LIMITS.mediaPerBeat || new Set(beat.media).size !== beat.media.length || !beat.media.every((ref) => text(ref, 1100))))
|
|
111
|
+
return null;
|
|
100
112
|
ids.add(beat.id);
|
|
101
113
|
end = beat.sourceEnd;
|
|
102
114
|
beats.push({
|
|
@@ -106,7 +118,8 @@ function parsePresentationPlan(input) {
|
|
|
106
118
|
layout: beat.layout,
|
|
107
119
|
headline: beat.headline,
|
|
108
120
|
points: [...beat.points],
|
|
109
|
-
...beat.layout === "image" ? { imageSrc: beat.imageSrc } : {}
|
|
121
|
+
...beat.layout === "image" ? { imageSrc: beat.imageSrc } : {},
|
|
122
|
+
..."media" in beat ? { media: [...beat.media] } : {}
|
|
110
123
|
});
|
|
111
124
|
}
|
|
112
125
|
if (value.sourceText.slice(end).trim()) return null;
|
|
@@ -1638,6 +1651,55 @@ function videoBlock(video, index, segmentId, duration) {
|
|
|
1638
1651
|
};
|
|
1639
1652
|
}
|
|
1640
1653
|
|
|
1654
|
+
// src/transform/presentationMedia.ts
|
|
1655
|
+
function mediaKind(node) {
|
|
1656
|
+
if (node.type === "code")
|
|
1657
|
+
return isPictureFence(node) || isExplicitDiagramLang(node.lang) || isExplicitTreeLang(node.lang) || isExplicitTimelineLang(node.lang) ? { kind: "diagram", continuous: true } : null;
|
|
1658
|
+
if (isStandaloneHtmlVideo(node)) return { kind: "video", continuous: true };
|
|
1659
|
+
if (findBlockVideoEmbed(node) || isPictureParagraph(node) && extractEmbeddedVideos([node]).length > 0)
|
|
1660
|
+
return { kind: "video", continuous: false };
|
|
1661
|
+
return null;
|
|
1662
|
+
}
|
|
1663
|
+
function collectPresentationMedia(doc, sectionIds) {
|
|
1664
|
+
const sections = new Set(sectionIds);
|
|
1665
|
+
const result = /* @__PURE__ */ new Map();
|
|
1666
|
+
let owner = sectionIds[0];
|
|
1667
|
+
for (const block of flattenRenderableBlocks(doc.blocks)) {
|
|
1668
|
+
if (sections.has(block.id)) owner = block.id;
|
|
1669
|
+
if (!owner) continue;
|
|
1670
|
+
for (const node of block.contents ?? []) {
|
|
1671
|
+
const kind = mediaKind(node);
|
|
1672
|
+
if (!kind) continue;
|
|
1673
|
+
const items = result.get(owner) ?? [];
|
|
1674
|
+
items.push({ ...kind, ref: `${owner}#${items.length}`, node });
|
|
1675
|
+
result.set(owner, items);
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
return result;
|
|
1679
|
+
}
|
|
1680
|
+
function videoElements(node, found = []) {
|
|
1681
|
+
if (!node || typeof node !== "object") return found;
|
|
1682
|
+
const value = node;
|
|
1683
|
+
if (value.type === "htmlElement" && value.tagName === "video") found.push(value);
|
|
1684
|
+
for (const key of ["children", "htmlChildren"])
|
|
1685
|
+
if (Array.isArray(value[key])) for (const child of value[key]) videoElements(child, found);
|
|
1686
|
+
return found;
|
|
1687
|
+
}
|
|
1688
|
+
function presentationMediaNode(item, elapsed) {
|
|
1689
|
+
const node = cloneData(item.node);
|
|
1690
|
+
if (item.kind !== "video" || elapsed <= 0) return node;
|
|
1691
|
+
for (const element of videoElements(node)) {
|
|
1692
|
+
const attributes = element.attributes ?? {};
|
|
1693
|
+
const seconds = (name) => attributes[name] ? parseTimeSeconds(attributes[name]) : null;
|
|
1694
|
+
const from = (seconds("data-squisq-video-clip-start") ?? 0) + Math.max(0, elapsed - (seconds("data-squisq-video-start-at") ?? 0));
|
|
1695
|
+
const until = seconds("data-squisq-video-clip-end");
|
|
1696
|
+
if (until !== null && from >= until) return null;
|
|
1697
|
+
delete attributes["data-squisq-video-start-at"];
|
|
1698
|
+
element.attributes = { ...attributes, "data-squisq-video-clip-start": String(from) };
|
|
1699
|
+
}
|
|
1700
|
+
return node;
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1641
1703
|
// src/transform/presentationPlanner.ts
|
|
1642
1704
|
var SENTENCE_END = /[.!?][”"')\]]?$/u;
|
|
1643
1705
|
var SENTENCE_START = /^[\p{Lu}\p{N}"“‘'([]/u;
|
|
@@ -1847,6 +1909,27 @@ function createPresentationPlan(doc, hints = defaultPresentationHints()) {
|
|
|
1847
1909
|
throw new Error(
|
|
1848
1910
|
"This document has too many sections for one presentation. Split it into shorter documents."
|
|
1849
1911
|
);
|
|
1912
|
+
const sectionMedia = collectPresentationMedia(
|
|
1913
|
+
doc,
|
|
1914
|
+
script.blocks.map((block) => block.blockId)
|
|
1915
|
+
);
|
|
1916
|
+
for (const block of script.blocks) {
|
|
1917
|
+
const items = sectionMedia.get(block.blockId);
|
|
1918
|
+
if (!items?.length) continue;
|
|
1919
|
+
const own = beats.filter(
|
|
1920
|
+
(beat) => beat.sourceStart >= block.charStart && beat.sourceStart < block.charEnd
|
|
1921
|
+
);
|
|
1922
|
+
const open = own.filter((beat) => beat !== beats[0] && beat.layout !== "image");
|
|
1923
|
+
const slots = open.length ? open : own;
|
|
1924
|
+
const shown = /* @__PURE__ */ new Set();
|
|
1925
|
+
slots.forEach((beat, slot) => {
|
|
1926
|
+
const from = Math.floor(slot * items.length / slots.length);
|
|
1927
|
+
const to = Math.max(from + 1, Math.floor((slot + 1) * items.length / slots.length));
|
|
1928
|
+
const refs = items.slice(from, to).filter((item) => item.continuous || !shown.has(item.ref)).slice(0, PRESENTATION_LIMITS.mediaPerBeat).map((item) => item.ref);
|
|
1929
|
+
for (const ref of refs) shown.add(ref);
|
|
1930
|
+
if (refs.length) beat.media = refs;
|
|
1931
|
+
});
|
|
1932
|
+
}
|
|
1850
1933
|
const closing = beats[beats.length - 1];
|
|
1851
1934
|
if (beats.length > 2 && closing?.layout === "statement" && !hints.blocks.some(
|
|
1852
1935
|
(hint) => hint.layout && script.blocks.some(
|
|
@@ -1875,6 +1958,7 @@ function createPresentationPlan(doc, hints = defaultPresentationHints()) {
|
|
|
1875
1958
|
beat.headline = hint.wording.headline ?? beat.headline;
|
|
1876
1959
|
beat.points = hint.wording.points ?? beat.points;
|
|
1877
1960
|
}
|
|
1961
|
+
if (beat.media && beat.layout === "steps" && hint?.layout !== "steps") beat.layout = "list";
|
|
1878
1962
|
if (["steps", "list", "comparison"].includes(beat.layout) && (beat.points.length < 2 || beat.layout === "comparison" && beat.points.length !== 2))
|
|
1879
1963
|
beat.layout = "statement";
|
|
1880
1964
|
if (beat.layout !== "image") delete beat.imageSrc;
|
|
@@ -1913,6 +1997,18 @@ function compilePresentationPlan(doc, plan) {
|
|
|
1913
1997
|
throw new Error(
|
|
1914
1998
|
"A presentation image is no longer in the document. Make the presentation again."
|
|
1915
1999
|
);
|
|
2000
|
+
const media = new Map(
|
|
2001
|
+
[
|
|
2002
|
+
...collectPresentationMedia(
|
|
2003
|
+
doc,
|
|
2004
|
+
script.blocks.map((block) => block.blockId)
|
|
2005
|
+
).values()
|
|
2006
|
+
].flat().map((item) => [item.ref, item])
|
|
2007
|
+
);
|
|
2008
|
+
if (checked.beats.some((beat) => beat.media?.some((ref) => !media.has(ref))))
|
|
2009
|
+
throw new Error(
|
|
2010
|
+
"A presentation video or diagram is no longer in the document. Make the presentation again."
|
|
2011
|
+
);
|
|
1916
2012
|
const duration = narration ? narration.startTime + narration.duration : Math.max(4, script.tokens.length / 2.5);
|
|
1917
2013
|
const bookmarks = (narration?.bookmarks ?? []).filter(
|
|
1918
2014
|
(word) => Number.isFinite(word.time) && word.time >= 0 && word.time <= duration && Number.isInteger(word.charOffset) && word.charOffset >= 0 && word.charOffset < script.sourceText.length
|
|
@@ -1932,17 +2028,53 @@ function compilePresentationPlan(doc, plan) {
|
|
|
1932
2028
|
});
|
|
1933
2029
|
const authoredBlocks = flattenRenderableBlocks(doc.blocks);
|
|
1934
2030
|
const buildHints = parsePresentationHints(doc.frontmatter?.[PRESENTATION_HINTS_KEY]);
|
|
2031
|
+
const sourceOf = (beat) => script.blocks.find(
|
|
2032
|
+
(block) => beat.sourceStart >= block.charStart && beat.sourceStart < block.charEnd
|
|
2033
|
+
);
|
|
2034
|
+
const sectionEnds = /* @__PURE__ */ new Map();
|
|
2035
|
+
checked.beats.forEach((beat, index) => {
|
|
2036
|
+
const section = sourceOf(beat)?.blockId;
|
|
2037
|
+
if (section) sectionEnds.set(section, starts[index + 1] ?? duration);
|
|
2038
|
+
});
|
|
2039
|
+
const clipsPlaced = /* @__PURE__ */ new Set();
|
|
2040
|
+
const mediaStarts = /* @__PURE__ */ new Map();
|
|
1935
2041
|
const blocks = [];
|
|
1936
2042
|
checked.beats.forEach((beat, index) => {
|
|
1937
2043
|
const start = starts[index];
|
|
1938
2044
|
const end = starts[index + 1] ?? duration;
|
|
1939
2045
|
if (end <= start) return;
|
|
1940
|
-
const source =
|
|
1941
|
-
(block2) => beat.sourceStart >= block2.charStart && beat.sourceStart < block2.charEnd
|
|
1942
|
-
);
|
|
2046
|
+
const source = sourceOf(beat);
|
|
1943
2047
|
const build = buildHints?.blocks.find((hint) => hint.blockId === source?.blockId)?.build ?? authoredBlocks.find((block2) => block2.id === source?.blockId)?.build;
|
|
2048
|
+
const contents = (beat.media ?? []).flatMap((ref) => {
|
|
2049
|
+
const first = mediaStarts.get(ref) ?? start;
|
|
2050
|
+
mediaStarts.set(ref, first);
|
|
2051
|
+
const node = presentationMediaNode(media.get(ref), start - first);
|
|
2052
|
+
return node ? [node] : [];
|
|
2053
|
+
});
|
|
2054
|
+
let clips = [];
|
|
2055
|
+
if (source && !clipsPlaced.has(source.blockId)) {
|
|
2056
|
+
clipsPlaced.add(source.blockId);
|
|
2057
|
+
const sectionEnd = sectionEnds.get(source.blockId) ?? end;
|
|
2058
|
+
clips = (authoredBlocks.find((block2) => block2.id === source.blockId)?.media ?? []).flatMap(
|
|
2059
|
+
(clip2) => {
|
|
2060
|
+
if (clip2.spillover) return [clip2];
|
|
2061
|
+
const room = sectionEnd - start - clip2.startAt;
|
|
2062
|
+
if (room <= 0) return [];
|
|
2063
|
+
const clipStart = clip2.clipStart ?? 0;
|
|
2064
|
+
return [
|
|
2065
|
+
{
|
|
2066
|
+
...clip2,
|
|
2067
|
+
spillover: true,
|
|
2068
|
+
clipEnd: Math.min(clip2.clipEnd ?? Infinity, clipStart + room)
|
|
2069
|
+
}
|
|
2070
|
+
];
|
|
2071
|
+
}
|
|
2072
|
+
);
|
|
2073
|
+
}
|
|
1944
2074
|
const base = {
|
|
1945
2075
|
...build ? { build } : {},
|
|
2076
|
+
...contents.length ? { contents } : {},
|
|
2077
|
+
...clips.length ? { media: clips } : {},
|
|
1946
2078
|
id: beat.id,
|
|
1947
2079
|
duration: end - start,
|
|
1948
2080
|
startTime: start,
|
|
@@ -1980,7 +2112,14 @@ function visualBlock(beat, base, index) {
|
|
|
1980
2112
|
explanation: beat.points.join("\n\n")
|
|
1981
2113
|
};
|
|
1982
2114
|
case "list":
|
|
1983
|
-
return {
|
|
2115
|
+
return {
|
|
2116
|
+
...base,
|
|
2117
|
+
template: "list",
|
|
2118
|
+
title: beat.headline,
|
|
2119
|
+
items: beat.points,
|
|
2120
|
+
ordered: false,
|
|
2121
|
+
colorScheme
|
|
2122
|
+
};
|
|
1984
2123
|
case "comparison":
|
|
1985
2124
|
return {
|
|
1986
2125
|
...base,
|
|
@@ -2069,6 +2208,7 @@ export {
|
|
|
2069
2208
|
allocateTiming,
|
|
2070
2209
|
applyTransform,
|
|
2071
2210
|
transformNarratedSegment,
|
|
2211
|
+
collectPresentationMedia,
|
|
2072
2212
|
createPresentationPlan,
|
|
2073
2213
|
compilePresentationPlan,
|
|
2074
2214
|
applySavedPresentation
|
|
@@ -5,10 +5,11 @@ import {
|
|
|
5
5
|
} from "./chunk-NEWNNLWN.js";
|
|
6
6
|
import {
|
|
7
7
|
buildNarrationScript,
|
|
8
|
+
estimateSyllables,
|
|
8
9
|
expectedSyllablesAt,
|
|
9
10
|
flattenRenderableBlocks,
|
|
10
11
|
wordPosAtExpectedSyllables
|
|
11
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-VQXOX3YN.js";
|
|
12
13
|
|
|
13
14
|
// src/narration/types.ts
|
|
14
15
|
var DEFAULT_FEATURE_CONFIG = Object.freeze({
|
|
@@ -839,6 +840,333 @@ function proportionalAlignment(script, effectiveDuration, takeDuration, c, detec
|
|
|
839
840
|
return { words, blocks, detectedSyllables, cost: 0 };
|
|
840
841
|
}
|
|
841
842
|
|
|
843
|
+
// src/narration/transcriptAlign.ts
|
|
844
|
+
var MAX_DP_CELLS = 1e6;
|
|
845
|
+
var ANCHOR_GRAM = 3;
|
|
846
|
+
var EXACT_SCORE = 2;
|
|
847
|
+
var NEAR_SCORE = 1;
|
|
848
|
+
var MISMATCH_SCORE = -1;
|
|
849
|
+
var GAP_SCORE = -1;
|
|
850
|
+
var NEAR_SIMILARITY = 0.75;
|
|
851
|
+
var ISOLATED_MATCH_MAX_LENGTH = 3;
|
|
852
|
+
var NON_SPEECH = /^\s*[[(].*[\])]\s*$/u;
|
|
853
|
+
function transcriptWordKeys(text) {
|
|
854
|
+
return text.normalize("NFKD").replace(/\p{M}+/gu, "").toLowerCase().replace(/['’]/gu, "").split(/[^\p{L}\p{N}]+/u).filter(Boolean);
|
|
855
|
+
}
|
|
856
|
+
function clampTime(value, durationSec) {
|
|
857
|
+
return Number.isFinite(value) ? Math.min(Math.max(0, value), durationSec) : 0;
|
|
858
|
+
}
|
|
859
|
+
function heardFromSegments(segments, durationSec) {
|
|
860
|
+
const heard = [];
|
|
861
|
+
const units = [];
|
|
862
|
+
const add = (text, startSec, endSec) => {
|
|
863
|
+
if (NON_SPEECH.test(text)) return;
|
|
864
|
+
const keys = transcriptWordKeys(text);
|
|
865
|
+
if (!keys.length) return;
|
|
866
|
+
for (const key of keys) units.push({ key, index: heard.length });
|
|
867
|
+
heard.push({ startSec, endSec: Math.max(startSec, endSec) });
|
|
868
|
+
};
|
|
869
|
+
const ordered = [...segments].sort((a, b) => a.startSec - b.startSec);
|
|
870
|
+
for (const segment of ordered) {
|
|
871
|
+
const start = clampTime(segment.startSec, durationSec);
|
|
872
|
+
const end = Math.max(start, clampTime(segment.endSec, durationSec));
|
|
873
|
+
if (segment.words?.length) {
|
|
874
|
+
for (const word of segment.words) {
|
|
875
|
+
const wordStart = clampTime(word.startSec, durationSec);
|
|
876
|
+
add(word.text, wordStart, clampTime(word.endSec, durationSec));
|
|
877
|
+
}
|
|
878
|
+
continue;
|
|
879
|
+
}
|
|
880
|
+
const pieces = segment.text.split(/\s+/u).filter((piece) => piece && !NON_SPEECH.test(piece));
|
|
881
|
+
const weights = pieces.map((piece) => estimateSyllables(piece));
|
|
882
|
+
const total = weights.reduce((sum, weight) => sum + weight, 0) || 1;
|
|
883
|
+
let before = 0;
|
|
884
|
+
pieces.forEach((piece, i) => {
|
|
885
|
+
const from = start + before / total * (end - start);
|
|
886
|
+
before += weights[i];
|
|
887
|
+
add(piece, from, start + before / total * (end - start));
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
let running = 0;
|
|
891
|
+
for (const word of heard) {
|
|
892
|
+
word.startSec = Math.max(running, word.startSec);
|
|
893
|
+
word.endSec = Math.max(word.startSec, word.endSec);
|
|
894
|
+
running = word.startSec;
|
|
895
|
+
}
|
|
896
|
+
return { heard, units };
|
|
897
|
+
}
|
|
898
|
+
function scriptUnits(script) {
|
|
899
|
+
const units = [];
|
|
900
|
+
script.tokens.forEach((token, index) => {
|
|
901
|
+
if (!token.spoken) return;
|
|
902
|
+
for (const key of transcriptWordKeys(token.text)) units.push({ key, index });
|
|
903
|
+
});
|
|
904
|
+
return units;
|
|
905
|
+
}
|
|
906
|
+
function uniqueGrams(units) {
|
|
907
|
+
const grams = /* @__PURE__ */ new Map();
|
|
908
|
+
for (let i = 0; i + ANCHOR_GRAM <= units.length; i++) {
|
|
909
|
+
const gram = units.slice(i, i + ANCHOR_GRAM).map((unit) => unit.key).join(" ");
|
|
910
|
+
grams.set(gram, grams.has(gram) ? -1 : i);
|
|
911
|
+
}
|
|
912
|
+
return grams;
|
|
913
|
+
}
|
|
914
|
+
function anchorChain(script, heard) {
|
|
915
|
+
const heardGrams = uniqueGrams(heard);
|
|
916
|
+
const pairs = [];
|
|
917
|
+
for (const [gram, s] of uniqueGrams(script)) {
|
|
918
|
+
const t = heardGrams.get(gram);
|
|
919
|
+
if (s >= 0 && t !== void 0 && t >= 0) pairs.push([s, t]);
|
|
920
|
+
}
|
|
921
|
+
pairs.sort((a, b) => a[0] - b[0]);
|
|
922
|
+
const tails = [];
|
|
923
|
+
const previous = new Int32Array(pairs.length).fill(-1);
|
|
924
|
+
for (let i = 0; i < pairs.length; i++) {
|
|
925
|
+
let lo = 0;
|
|
926
|
+
let hi = tails.length;
|
|
927
|
+
while (lo < hi) {
|
|
928
|
+
const mid = lo + hi >> 1;
|
|
929
|
+
if (pairs[tails[mid]][1] < pairs[i][1]) lo = mid + 1;
|
|
930
|
+
else hi = mid;
|
|
931
|
+
}
|
|
932
|
+
if (lo > 0) previous[i] = tails[lo - 1];
|
|
933
|
+
tails[lo] = i;
|
|
934
|
+
}
|
|
935
|
+
const chain = [];
|
|
936
|
+
for (let i = tails.length ? tails[tails.length - 1] : -1; i >= 0; i = previous[i]) {
|
|
937
|
+
chain.push(pairs[i]);
|
|
938
|
+
}
|
|
939
|
+
return chain.reverse();
|
|
940
|
+
}
|
|
941
|
+
function editDistance(a, b) {
|
|
942
|
+
let row = Array.from({ length: b.length + 1 }, (_, j) => j);
|
|
943
|
+
for (let i = 1; i <= a.length; i++) {
|
|
944
|
+
const next = [i];
|
|
945
|
+
for (let j = 1; j <= b.length; j++) {
|
|
946
|
+
next[j] = Math.min(
|
|
947
|
+
row[j] + 1,
|
|
948
|
+
next[j - 1] + 1,
|
|
949
|
+
row[j - 1] + (a.charCodeAt(i - 1) === b.charCodeAt(j - 1) ? 0 : 1)
|
|
950
|
+
);
|
|
951
|
+
}
|
|
952
|
+
row = next;
|
|
953
|
+
}
|
|
954
|
+
return row[b.length];
|
|
955
|
+
}
|
|
956
|
+
function createScorer() {
|
|
957
|
+
const near = /* @__PURE__ */ new Map();
|
|
958
|
+
return (a, b) => {
|
|
959
|
+
if (a === b) return EXACT_SCORE;
|
|
960
|
+
if (a.length < 4 || b.length < 4 || a[0] !== b[0] || Math.abs(a.length - b.length) > 3)
|
|
961
|
+
return MISMATCH_SCORE;
|
|
962
|
+
const key = a < b ? `${a} ${b}` : `${b} ${a}`;
|
|
963
|
+
let similar = near.get(key);
|
|
964
|
+
if (similar === void 0) {
|
|
965
|
+
similar = 1 - editDistance(a, b) / Math.max(a.length, b.length) >= NEAR_SIMILARITY;
|
|
966
|
+
near.set(key, similar);
|
|
967
|
+
}
|
|
968
|
+
return similar ? NEAR_SCORE : MISMATCH_SCORE;
|
|
969
|
+
};
|
|
970
|
+
}
|
|
971
|
+
function alignStretch(script, sFrom, sTo, heard, tFrom, tTo, score) {
|
|
972
|
+
const rows = sTo - sFrom;
|
|
973
|
+
const cols = tTo - tFrom;
|
|
974
|
+
if (rows <= 0 || cols <= 0 || rows * cols > MAX_DP_CELLS) return [];
|
|
975
|
+
const width = cols + 1;
|
|
976
|
+
const moves = new Uint8Array((rows + 1) * width);
|
|
977
|
+
let prev = new Float64Array(width);
|
|
978
|
+
for (let j2 = 1; j2 <= cols; j2++) {
|
|
979
|
+
prev[j2] = j2 * GAP_SCORE;
|
|
980
|
+
moves[j2] = 2;
|
|
981
|
+
}
|
|
982
|
+
for (let i2 = 1; i2 <= rows; i2++) {
|
|
983
|
+
const row = new Float64Array(width);
|
|
984
|
+
row[0] = i2 * GAP_SCORE;
|
|
985
|
+
moves[i2 * width] = 1;
|
|
986
|
+
const key = script[sFrom + i2 - 1].key;
|
|
987
|
+
for (let j2 = 1; j2 <= cols; j2++) {
|
|
988
|
+
const diagonal = prev[j2 - 1] + score(key, heard[tFrom + j2 - 1].key);
|
|
989
|
+
const up = prev[j2] + GAP_SCORE;
|
|
990
|
+
const left = row[j2 - 1] + GAP_SCORE;
|
|
991
|
+
if (diagonal >= up && diagonal >= left) {
|
|
992
|
+
row[j2] = diagonal;
|
|
993
|
+
moves[i2 * width + j2] = 0;
|
|
994
|
+
} else if (up >= left) {
|
|
995
|
+
row[j2] = up;
|
|
996
|
+
moves[i2 * width + j2] = 1;
|
|
997
|
+
} else {
|
|
998
|
+
row[j2] = left;
|
|
999
|
+
moves[i2 * width + j2] = 2;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
prev = row;
|
|
1003
|
+
}
|
|
1004
|
+
const pairs = [];
|
|
1005
|
+
let i = rows;
|
|
1006
|
+
let j = cols;
|
|
1007
|
+
while (i > 0 || j > 0) {
|
|
1008
|
+
const move = moves[i * width + j];
|
|
1009
|
+
if (move === 0) {
|
|
1010
|
+
const s = sFrom + i - 1;
|
|
1011
|
+
const t = tFrom + j - 1;
|
|
1012
|
+
if (score(script[s].key, heard[t].key) > 0) pairs.push([s, t]);
|
|
1013
|
+
i--;
|
|
1014
|
+
j--;
|
|
1015
|
+
} else if (move === 1) i--;
|
|
1016
|
+
else j--;
|
|
1017
|
+
}
|
|
1018
|
+
return pairs.reverse();
|
|
1019
|
+
}
|
|
1020
|
+
function matchUnits(script, heard) {
|
|
1021
|
+
const anchored = [];
|
|
1022
|
+
let lastS = -1;
|
|
1023
|
+
let lastT = -1;
|
|
1024
|
+
for (const [s, t] of anchorChain(script, heard)) {
|
|
1025
|
+
for (let k = 0; k < ANCHOR_GRAM; k++) {
|
|
1026
|
+
if (s + k > lastS && t + k > lastT) {
|
|
1027
|
+
anchored.push([s + k, t + k]);
|
|
1028
|
+
lastS = s + k;
|
|
1029
|
+
lastT = t + k;
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
const score = createScorer();
|
|
1034
|
+
const pairs = [];
|
|
1035
|
+
let from = [-1, -1];
|
|
1036
|
+
for (const to of [...anchored, [script.length, heard.length]]) {
|
|
1037
|
+
pairs.push(...alignStretch(script, from[0] + 1, to[0], heard, from[1] + 1, to[1], score));
|
|
1038
|
+
if (to[0] < script.length) pairs.push(to);
|
|
1039
|
+
from = to;
|
|
1040
|
+
}
|
|
1041
|
+
return pairs.filter(([s, t], i) => {
|
|
1042
|
+
if (script[s].key.length > ISOLATED_MATCH_MAX_LENGTH) return true;
|
|
1043
|
+
const before = pairs[i - 1];
|
|
1044
|
+
const after = pairs[i + 1];
|
|
1045
|
+
return before !== void 0 && before[0] === s - 1 && before[1] === t - 1 || after !== void 0 && after[0] === s + 1 && after[1] === t + 1;
|
|
1046
|
+
});
|
|
1047
|
+
}
|
|
1048
|
+
function placeWords(script, matched, heard, speechEnd, durationSec, gapMinSec) {
|
|
1049
|
+
const n = script.tokens.length;
|
|
1050
|
+
const cumulative = script.cumulativeSyllables;
|
|
1051
|
+
if (!heard.length) {
|
|
1052
|
+
const total = Math.max(1, script.totalSyllables);
|
|
1053
|
+
return script.tokens.map((_, k) => ({
|
|
1054
|
+
tokenIndex: k,
|
|
1055
|
+
tSec: cumulative[k] / total * durationSec,
|
|
1056
|
+
interpolated: true
|
|
1057
|
+
}));
|
|
1058
|
+
}
|
|
1059
|
+
const startOf = (h) => h < heard.length ? heard[h].startSec : speechEnd;
|
|
1060
|
+
const words = new Array(n);
|
|
1061
|
+
let leftToken = -1;
|
|
1062
|
+
let leftHeard = -1;
|
|
1063
|
+
const fill = (rightToken, rightHeard) => {
|
|
1064
|
+
const from = leftToken + 1;
|
|
1065
|
+
const between = rightHeard - leftHeard - 1;
|
|
1066
|
+
const leftBlock = leftToken >= 0 ? script.tokens[leftToken].blockIndex : -1;
|
|
1067
|
+
let leftCount = 0;
|
|
1068
|
+
let rightCount = 0;
|
|
1069
|
+
for (let u = from; u < rightToken; u++) {
|
|
1070
|
+
if (!script.tokens[u].spoken) continue;
|
|
1071
|
+
if (script.tokens[u].blockIndex === leftBlock) leftCount++;
|
|
1072
|
+
else rightCount++;
|
|
1073
|
+
}
|
|
1074
|
+
if (between > 0 && between >= leftCount + rightCount) {
|
|
1075
|
+
let rightFloor = rightHeard - rightCount;
|
|
1076
|
+
for (let h = rightHeard; h > rightFloor && h > 0; h--) {
|
|
1077
|
+
if (startOf(h) - heard[h - 1].endSec >= gapMinSec) {
|
|
1078
|
+
rightFloor = h;
|
|
1079
|
+
break;
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
let leftRank = 0;
|
|
1083
|
+
let rightRank = 0;
|
|
1084
|
+
for (let u = from; u < rightToken; u++) {
|
|
1085
|
+
const token = script.tokens[u];
|
|
1086
|
+
const left = token.blockIndex === leftBlock;
|
|
1087
|
+
const position = left ? leftHeard + 1 + leftRank : Math.max(rightFloor, rightHeard - rightCount + rightRank);
|
|
1088
|
+
words[u] = { tokenIndex: u, tSec: startOf(position), interpolated: true };
|
|
1089
|
+
if (token.spoken && left) leftRank++;
|
|
1090
|
+
else if (token.spoken) rightRank++;
|
|
1091
|
+
}
|
|
1092
|
+
return;
|
|
1093
|
+
}
|
|
1094
|
+
const base = cumulative[from] ?? 0;
|
|
1095
|
+
const span = (rightToken < n ? cumulative[rightToken] : script.totalSyllables) - base;
|
|
1096
|
+
for (let u = from; u < rightToken; u++) {
|
|
1097
|
+
let tSec = startOf(rightHeard);
|
|
1098
|
+
if (between > 0) {
|
|
1099
|
+
const fraction = span > 0 ? (cumulative[u] - base) / span : (u - from) / (rightToken - from);
|
|
1100
|
+
const position = leftHeard + 1 + fraction * between;
|
|
1101
|
+
const index = Math.floor(position);
|
|
1102
|
+
tSec = startOf(index) + (position - index) * (startOf(index + 1) - startOf(index));
|
|
1103
|
+
}
|
|
1104
|
+
words[u] = { tokenIndex: u, tSec, interpolated: true };
|
|
1105
|
+
}
|
|
1106
|
+
};
|
|
1107
|
+
for (let k = 0; k < n; k++) {
|
|
1108
|
+
const h = matched[k];
|
|
1109
|
+
if (h === void 0) continue;
|
|
1110
|
+
fill(k, h);
|
|
1111
|
+
words[k] = { tokenIndex: k, tSec: heard[h].startSec, interpolated: false };
|
|
1112
|
+
leftToken = k;
|
|
1113
|
+
leftHeard = h;
|
|
1114
|
+
}
|
|
1115
|
+
fill(n, heard.length);
|
|
1116
|
+
let running = 0;
|
|
1117
|
+
for (const word of words) {
|
|
1118
|
+
running = Math.max(running, word.tSec);
|
|
1119
|
+
word.tSec = running;
|
|
1120
|
+
}
|
|
1121
|
+
return words;
|
|
1122
|
+
}
|
|
1123
|
+
function alignTranscript(input, config) {
|
|
1124
|
+
const c = { ...DEFAULT_ALIGN_CONFIG, ...config };
|
|
1125
|
+
const { script } = input;
|
|
1126
|
+
const durationSec = Number.isFinite(input.durationSec) && input.durationSec > 0 ? input.durationSec : 0;
|
|
1127
|
+
if (script.tokens.length > c.maxScriptTokens) {
|
|
1128
|
+
throw new RangeError(`Narration script exceeds the ${c.maxScriptTokens}-token safety limit`);
|
|
1129
|
+
}
|
|
1130
|
+
const spokenWords = script.tokens.filter((token) => token.spoken).length;
|
|
1131
|
+
const { heard, units: heardUnits } = heardFromSegments(input.segments, durationSec);
|
|
1132
|
+
if (script.tokens.length === 0 || durationSec === 0) {
|
|
1133
|
+
return { words: [], blocks: [], detectedSyllables: 0, cost: 0, matchedWords: 0, spokenWords };
|
|
1134
|
+
}
|
|
1135
|
+
const units = scriptUnits(script);
|
|
1136
|
+
const matched = new Array(script.tokens.length);
|
|
1137
|
+
for (const [s, t] of matchUnits(units, heardUnits)) {
|
|
1138
|
+
const token = units[s].index;
|
|
1139
|
+
matched[token] ?? (matched[token] = heardUnits[t].index);
|
|
1140
|
+
}
|
|
1141
|
+
const matchedWords = matched.filter((heardIndex) => heardIndex !== void 0).length;
|
|
1142
|
+
const lastSpeechEnd = heard.reduce((end, word) => Math.max(end, word.endSec), 0);
|
|
1143
|
+
const words = placeWords(
|
|
1144
|
+
script,
|
|
1145
|
+
matched,
|
|
1146
|
+
heard,
|
|
1147
|
+
lastSpeechEnd || durationSec,
|
|
1148
|
+
durationSec,
|
|
1149
|
+
c.gapMinSec
|
|
1150
|
+
);
|
|
1151
|
+
const gaps = [];
|
|
1152
|
+
for (let i = 1; i < heard.length; i++) {
|
|
1153
|
+
const startSec = heard[i - 1].endSec;
|
|
1154
|
+
const endSec = heard[i].startSec;
|
|
1155
|
+
if (endSec - startSec >= c.gapMinSec) {
|
|
1156
|
+
gaps.push({ kind: "gap", tSec: (startSec + endSec) / 2, startSec, endSec });
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
const blocks = deriveBlockRanges(script, words, gaps, durationSec, lastSpeechEnd, c);
|
|
1160
|
+
return {
|
|
1161
|
+
words,
|
|
1162
|
+
blocks,
|
|
1163
|
+
detectedSyllables: heard.length,
|
|
1164
|
+
cost: 0,
|
|
1165
|
+
matchedWords,
|
|
1166
|
+
spokenWords
|
|
1167
|
+
};
|
|
1168
|
+
}
|
|
1169
|
+
|
|
842
1170
|
// src/narration/advanceTiming.ts
|
|
843
1171
|
var EMPTY_ADVANCE_LOG = Object.freeze([]);
|
|
844
1172
|
function recordSlideShown(log, blockId, atMs) {
|
|
@@ -963,6 +1291,8 @@ export {
|
|
|
963
1291
|
traceWordPosAt,
|
|
964
1292
|
downsampleTrace,
|
|
965
1293
|
alignNarration,
|
|
1294
|
+
transcriptWordKeys,
|
|
1295
|
+
alignTranscript,
|
|
966
1296
|
EMPTY_ADVANCE_LOG,
|
|
967
1297
|
recordSlideShown,
|
|
968
1298
|
buildAdvanceTimingJson,
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-FTN6SGW5.js";
|
|
4
4
|
import {
|
|
5
5
|
applySavedPresentation
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-4O26IMVA.js";
|
|
7
7
|
import {
|
|
8
8
|
SHAPE_NAMES,
|
|
9
9
|
buildChartData,
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
templateRegistry,
|
|
32
32
|
writeCustomTemplatesToFrontmatter,
|
|
33
33
|
writeCustomThemesToFrontmatter
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-VQXOX3YN.js";
|
|
35
35
|
import {
|
|
36
36
|
ASCII_TREE_VOCAB,
|
|
37
37
|
ASCII_VOCAB,
|
|
@@ -54,7 +54,7 @@ import {
|
|
|
54
54
|
toCells,
|
|
55
55
|
toGrid,
|
|
56
56
|
traceBoxes
|
|
57
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-CSR6VCSJ.js";
|
|
58
58
|
import {
|
|
59
59
|
iconMarker
|
|
60
60
|
} from "./chunk-7ZAAICW4.js";
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
profileBlockContents,
|
|
33
33
|
renderMarkdownBlocksHtml,
|
|
34
34
|
treeToTemplateData
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-CSR6VCSJ.js";
|
|
36
36
|
import {
|
|
37
37
|
anchorPoint,
|
|
38
38
|
base64ToUtf8,
|
|
@@ -4508,6 +4508,17 @@ function dataTable(input, context) {
|
|
|
4508
4508
|
|
|
4509
4509
|
// src/doc/templates/chart/parse.ts
|
|
4510
4510
|
var NUMERIC_COLUMN_THRESHOLD = 0.6;
|
|
4511
|
+
function cellText(cell) {
|
|
4512
|
+
if (typeof cell === "string") return cell;
|
|
4513
|
+
if (cell === null || cell === void 0) return "";
|
|
4514
|
+
if (typeof cell === "number") return Number.isFinite(cell) ? String(cell) : "";
|
|
4515
|
+
return typeof cell === "object" ? "" : String(cell);
|
|
4516
|
+
}
|
|
4517
|
+
function normalizeChartTable(table) {
|
|
4518
|
+
const headers = Array.isArray(table.headers) ? table.headers.map(cellText) : [];
|
|
4519
|
+
const rows = Array.isArray(table.rows) ? table.rows.filter(Array.isArray).map((row) => row.map(cellText)) : [];
|
|
4520
|
+
return { headers, rows };
|
|
4521
|
+
}
|
|
4511
4522
|
function parseCellNumber(raw) {
|
|
4512
4523
|
if (typeof raw !== "string") return null;
|
|
4513
4524
|
let text = raw.trim();
|
|
@@ -4553,8 +4564,7 @@ function resolveColumnRef(ref, headers) {
|
|
|
4553
4564
|
return null;
|
|
4554
4565
|
}
|
|
4555
4566
|
function buildChartData(table, options = {}) {
|
|
4556
|
-
const headers =
|
|
4557
|
-
const rows = Array.isArray(table.rows) ? table.rows : [];
|
|
4567
|
+
const { headers, rows } = normalizeChartTable(table);
|
|
4558
4568
|
if (headers.length === 0 || rows.length === 0) return null;
|
|
4559
4569
|
const warnings = [];
|
|
4560
4570
|
let labelIndex = 0;
|
|
@@ -4972,7 +4982,7 @@ function renderChart(kind, input, context) {
|
|
|
4972
4982
|
}
|
|
4973
4983
|
function resolveTable(input, context) {
|
|
4974
4984
|
if (Array.isArray(input.headers) && input.headers.length > 0 && Array.isArray(input.rows) && input.rows.length > 0) {
|
|
4975
|
-
return
|
|
4985
|
+
return normalizeChartTable(input);
|
|
4976
4986
|
}
|
|
4977
4987
|
const contents = input.contents ?? context.block?.contents;
|
|
4978
4988
|
return extractTableFromContents(contents);
|
|
@@ -6276,14 +6286,15 @@ function mapForegroundLayers(layers, contentRect, viewport, fontScale, template)
|
|
|
6276
6286
|
if (isFullViewportBackground(layer, viewport)) return layer;
|
|
6277
6287
|
const position = mapPosition(layer.position, contentRect, viewport);
|
|
6278
6288
|
if (layer.type === "text") {
|
|
6289
|
+
const fontSize = Math.max(12, Math.round(layer.content.style.fontSize * fontScale));
|
|
6279
6290
|
return {
|
|
6280
6291
|
...layer,
|
|
6281
|
-
position,
|
|
6292
|
+
position: layer.content.flow?.role === "marker" ? markerPosition(layer, position, fontSize / layer.content.style.fontSize, viewport) : position,
|
|
6282
6293
|
content: {
|
|
6283
6294
|
...layer.content,
|
|
6284
6295
|
style: {
|
|
6285
6296
|
...layer.content.style,
|
|
6286
|
-
fontSize
|
|
6297
|
+
fontSize,
|
|
6287
6298
|
...layer.content.style.padding !== void 0 ? { padding: Math.round(layer.content.style.padding * fontScale) } : {}
|
|
6288
6299
|
}
|
|
6289
6300
|
}
|
|
@@ -6293,6 +6304,20 @@ function mapForegroundLayers(layers, contentRect, viewport, fontScale, template)
|
|
|
6293
6304
|
});
|
|
6294
6305
|
return arrangeTitleFamily(mapped, template, contentRect, viewport);
|
|
6295
6306
|
}
|
|
6307
|
+
function markerPosition(layer, mapped, textScale, viewport) {
|
|
6308
|
+
if (mapped.width === void 0 || layer.position.width === void 0) return mapped;
|
|
6309
|
+
const width = resolvePositionValue(mapped.width, viewport.width);
|
|
6310
|
+
const needed = Math.ceil(resolvePositionValue(layer.position.width, viewport.width) * textScale);
|
|
6311
|
+
if (needed <= width) return mapped;
|
|
6312
|
+
const grow = needed - width;
|
|
6313
|
+
const anchor = mapped.anchor ?? "top-left";
|
|
6314
|
+
const shift = layer.content.style.textAlign !== "right" || anchor.includes("right") ? 0 : anchor === "center" ? grow / 2 : grow;
|
|
6315
|
+
return {
|
|
6316
|
+
...mapped,
|
|
6317
|
+
x: resolvePositionValue(mapped.x, viewport.width) - shift,
|
|
6318
|
+
width: needed
|
|
6319
|
+
};
|
|
6320
|
+
}
|
|
6296
6321
|
function arrangeTitleFamily(layers, template, contentRect, viewport) {
|
|
6297
6322
|
const centerX = contentRect.x + contentRect.width / 2;
|
|
6298
6323
|
const centerY = contentRect.y + contentRect.height / 2;
|
package/dist/doc/index.js
CHANGED
|
@@ -75,9 +75,9 @@ import {
|
|
|
75
75
|
validateMarkdownSource,
|
|
76
76
|
wordRevealDelay,
|
|
77
77
|
writeDashboardLayoutsToFrontmatter
|
|
78
|
-
} from "../chunk-
|
|
78
|
+
} from "../chunk-FGN4OZVK.js";
|
|
79
79
|
import "../chunk-FTN6SGW5.js";
|
|
80
|
-
import "../chunk-
|
|
80
|
+
import "../chunk-4O26IMVA.js";
|
|
81
81
|
import {
|
|
82
82
|
BASE_INPUT_DESCRIPTORS,
|
|
83
83
|
BLOCK_MEDIA_LAYOUT_POLICIES,
|
|
@@ -195,7 +195,7 @@ import {
|
|
|
195
195
|
wrapWithPersistentLayers,
|
|
196
196
|
writeCustomTemplatesToFrontmatter,
|
|
197
197
|
writeCustomThemesToFrontmatter
|
|
198
|
-
} from "../chunk-
|
|
198
|
+
} from "../chunk-VQXOX3YN.js";
|
|
199
199
|
import {
|
|
200
200
|
ASCII_CHAR_H,
|
|
201
201
|
ASCII_CHAR_W,
|
|
@@ -248,7 +248,7 @@ import {
|
|
|
248
248
|
treeFromMarkdownList,
|
|
249
249
|
treeFromTemplateData,
|
|
250
250
|
treeToTemplateData
|
|
251
|
-
} from "../chunk-
|
|
251
|
+
} from "../chunk-CSR6VCSJ.js";
|
|
252
252
|
import "../chunk-SVN7T6BK.js";
|
|
253
253
|
import {
|
|
254
254
|
PATH_SHAPE_KINDS,
|
package/dist/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export { BuildCaptionTrackOptions, CaptionSegmentSource, DEFAULT_WORDS_PER_SECON
|
|
|
16
16
|
export { SeededRandom, hashString } from './random/index.js';
|
|
17
17
|
export { C as ComparisonData, D as DateData, a as DefinitionData, E as ExtractedElement, b as ExtractionOptions, c as ExtractionResult, d as ExtractionType, F as FactData, I as ImpactLineData, L as ListData, Q as QuoteData, S as StatData, e as extractContent, s as stripMarkdown } from './contentExtractor-BNfVJV2U.js';
|
|
18
18
|
export { AffinityAssignment, AffinityMatchResult, AffinityTarget, ClipSelectionOptions, ClipSource, KeywordExtractionOptions, MapOptions, SelectedClip, TranscriptSegmentSource, calculateKeywordAffinity, extractKeywords, mapElementToBlock, matchByKeywordAffinity, selectSafeZoneClips, selectTranscriptClips } from './generate/index.js';
|
|
19
|
-
export { AnalyzedBlock, BlockImage, DEFAULT_TRANSFORM_STYLE_ID, DYNAMIC_PRESENTATION_STYLE, NarratedSegmentInput, NarratedSegmentResult, NarratedSegmentTransformOptions, NarratedSegmentVideo, PRESENTATION_HINTS_KEY, PRESENTATION_KEY, PRESENTATION_LAYOUTS, PRESENTATION_LIMITS, PresentationBeat, PresentationBlockHint, PresentationHints, PresentationLayout, PresentationPlan, TransformImage, TransformOptions, TransformResult, TransformStyleConfig, TransformStyleId, TransformStyleInput, TransformStyleRegistry, TransformStyleSummary, allocateTiming, analyzeBlocks, applySavedPresentation, applyTransform, compilePresentationPlan, createPresentationPlan, createTransformStyleRegistry, defaultPresentationHints, extractDocImages, getTransformStyleIds, getTransformStyleSummaries, parsePresentationHints, parsePresentationPlan, presentationSections, resolveTransformStyle, serializePresentationHints, serializePresentationPlan, transformNarratedSegment, usesDynamicPresentation } from './transform/index.js';
|
|
19
|
+
export { AnalyzedBlock, BlockImage, DEFAULT_TRANSFORM_STYLE_ID, DYNAMIC_PRESENTATION_STYLE, NarratedSegmentInput, NarratedSegmentResult, NarratedSegmentTransformOptions, NarratedSegmentVideo, PRESENTATION_HINTS_KEY, PRESENTATION_KEY, PRESENTATION_LAYOUTS, PRESENTATION_LIMITS, PresentationBeat, PresentationBlockHint, PresentationHints, PresentationLayout, PresentationMediaItem, PresentationPlan, TransformImage, TransformOptions, TransformResult, TransformStyleConfig, TransformStyleId, TransformStyleInput, TransformStyleRegistry, TransformStyleSummary, allocateTiming, analyzeBlocks, applySavedPresentation, applyTransform, collectPresentationMedia, compilePresentationPlan, createPresentationPlan, createTransformStyleRegistry, defaultPresentationHints, extractDocImages, getTransformStyleIds, getTransformStyleSummaries, parsePresentationHints, parsePresentationPlan, presentationSections, resolveTransformStyle, serializePresentationHints, serializePresentationPlan, transformNarratedSegment, usesDynamicPresentation } from './transform/index.js';
|
|
20
20
|
export { C as CoalesceOptions, P as PrunePolicy, R as RevertFailureReason, a as RevertOptions, b as RevertResult, S as SaveVersionOptions, c as SaveVersionResult, V as Version } from './types-8QjefM9J.js';
|
|
21
21
|
export { DATA_BACKUP_PREFIX, DocumentVersionManager, DocumentVersionManagerOptions, VERSIONS_PREFIX, VERSION_TIMESTAMP_PATTERN, buildDataBackupPath, buildVersionPath, coalesceVersions, formatVersionTimestamp, getDocBasename, listVersions, parseVersionPath, parseVersionTimestamp, pruneVersions, readVersion, revertToVersion, saveVersion } from './versions/index.js';
|
|
22
22
|
export { BuildJsonFormTokensOptions, ControlKind, InferSchemaOptions, JsonFormValidationError, JsonFormValidator, SquisqAnnotatedSchema, SquisqHints, SquisqWhen, appendPointer, arrayItemKind, buildJsonFormTokens, chooseControl, escapePointerSegment, evaluateWhen, getByPointer, inferSchema, isSafeConditionRegex, pointerSegments, primaryType, resolveFlag, resolveJsonFormTheme, resolveRef, setByPointer, toPointer } from './jsonForm/index.js';
|
|
@@ -24,7 +24,7 @@ export { AnimatedImageFormat, AnimatedImageInfo, IMAGE_EDIT_ASSETS_PREFIX, IMAGE
|
|
|
24
24
|
export { I as ICONS, a as IconEntry, b as IconFamily, c as IconTextRun, h as hasIconMarker, i as iconClass, d as iconMarker, s as splitIconMarkers, e as stripIconMarkers } from './inlineIconMarker-BGjv-W4j.js';
|
|
25
25
|
export { IconSuggestion, canonicalIconToken, iconGlyph, looksLikeIconToken, resolveIcon, suggestIcons } from './icons/index.js';
|
|
26
26
|
export { BlockContentProfile, RecommendationResult, profileBlockContents, recommendTemplatesForBlock } from './recommend/index.js';
|
|
27
|
-
export { AdvanceCoverage, AlignConfig, AlignInput, BandpassState, BuildAdvanceTimingOptions, BuildNarrationTimingOptions, BuildScriptOptions, DEFAULT_ALIGN_CONFIG, DEFAULT_FEATURE_CONFIG, DEFAULT_NUCLEI_CONFIG, DEFAULT_PACING_CONFIG, DEFAULT_VAD_CONFIG, EMPTY_ADVANCE_LOG, FeatureConfig, FeatureState, FrameFeatures, NarrationAlignment, NarrationBlockRange, NarrationScript, NarrationSessionConfig, NarrationSessionState, NarrationTimingBlock, NarrationTimingGenerator, NarrationTimingJsonV3, NarrationTimingMethod, NarrationTrace, NucleiConfig, NucleiState, PacingConfig, PacingState, PacingTick, ScriptBlockRange, ScriptToken, SlideAdvance, SlideAdvanceLog, TraceSample, VadConfig, VadState, WordTiming, advanceCoverage, alignNarration, bandpassRun, buildAdvanceTimingJson, buildNarrationScript, buildNarrationTimingJson, createBandpass, createFeatureState, createNarrationSession, createNucleiState, createPacingState, createVadState, detectSyllableOnsets, downsampleTrace, estimateSyllables, expectedSyllablesAt, extractFrameFeatures, featureStep, narrationSessionStep, nucleiStep, pacingStep, parseNarrationTimingJson, reanchorPacing, reanchorSession, recordSlideShown, resolveNarrationTimingGenerator, traceWordPosAt, vadStep, wordIndexAtChar, wordIndexAtTime, wordPosAtExpectedSyllables } from './narration/index.js';
|
|
27
|
+
export { AdvanceCoverage, AlignConfig, AlignInput, BandpassState, BuildAdvanceTimingOptions, BuildNarrationTimingOptions, BuildScriptOptions, DEFAULT_ALIGN_CONFIG, DEFAULT_FEATURE_CONFIG, DEFAULT_NUCLEI_CONFIG, DEFAULT_PACING_CONFIG, DEFAULT_VAD_CONFIG, EMPTY_ADVANCE_LOG, FeatureConfig, FeatureState, FrameFeatures, NarrationAlignment, NarrationBlockRange, NarrationScript, NarrationSessionConfig, NarrationSessionState, NarrationTimingBlock, NarrationTimingGenerator, NarrationTimingJsonV3, NarrationTimingMethod, NarrationTrace, NucleiConfig, NucleiState, PacingConfig, PacingState, PacingTick, ScriptBlockRange, ScriptToken, SlideAdvance, SlideAdvanceLog, TraceSample, TranscriptAlignInput, TranscriptAlignment, TranscriptSegment, TranscriptWord, VadConfig, VadState, WordTiming, advanceCoverage, alignNarration, alignTranscript, bandpassRun, buildAdvanceTimingJson, buildNarrationScript, buildNarrationTimingJson, createBandpass, createFeatureState, createNarrationSession, createNucleiState, createPacingState, createVadState, detectSyllableOnsets, downsampleTrace, estimateSyllables, expectedSyllablesAt, extractFrameFeatures, featureStep, narrationSessionStep, nucleiStep, pacingStep, parseNarrationTimingJson, reanchorPacing, reanchorSession, recordSlideShown, resolveNarrationTimingGenerator, traceWordPosAt, transcriptWordKeys, vadStep, wordIndexAtChar, wordIndexAtTime, wordPosAtExpectedSyllables } from './narration/index.js';
|
|
28
28
|
export { FenceRenderContext, FenceRenderer, FenceRendererMap, fenceRendererLangs } from './fence/index.js';
|
|
29
29
|
export { P as PROOF_DIALECTS, a as ProofCategory, b as ProofDialect, c as ProofFinding, d as ProofRange, e as ProofSuggestion, f as ProofSuggestionKind } from './types-BQWu0gzi.js';
|
|
30
30
|
export { BlankProtectedSpansOptions, BlankedText, DEFAULT_PROOF_SETTINGS, JoinedSegments, LINT_KIND_CATEGORIES, PROOF_FRONTMATTER_KEYS, PROOF_JOIN_SEPARATOR, ProofingSettings, SegmentSpan, blankProtectedSpans, buildJoinedText, categorizeLintKind, dropMaskedFindings, formatProofDictionary, mapJoinedSpanToSegment, parseProofDictionary, readProofingSettings, resolveProofDialect } from './proof/index.js';
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
EMPTY_ADVANCE_LOG,
|
|
8
8
|
advanceCoverage,
|
|
9
9
|
alignNarration,
|
|
10
|
+
alignTranscript,
|
|
10
11
|
bandpassRun,
|
|
11
12
|
buildAdvanceTimingJson,
|
|
12
13
|
createBandpass,
|
|
@@ -26,8 +27,9 @@ import {
|
|
|
26
27
|
reanchorSession,
|
|
27
28
|
recordSlideShown,
|
|
28
29
|
traceWordPosAt,
|
|
30
|
+
transcriptWordKeys,
|
|
29
31
|
vadStep
|
|
30
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-B2MOGSWY.js";
|
|
31
33
|
import {
|
|
32
34
|
fenceRendererLangs
|
|
33
35
|
} from "./chunk-PGI7HSWE.js";
|
|
@@ -230,7 +232,7 @@ import {
|
|
|
230
232
|
validateMarkdownSource,
|
|
231
233
|
wordRevealDelay,
|
|
232
234
|
writeDashboardLayoutsToFrontmatter
|
|
233
|
-
} from "./chunk-
|
|
235
|
+
} from "./chunk-FGN4OZVK.js";
|
|
234
236
|
import {
|
|
235
237
|
buildNarrationTimingJson,
|
|
236
238
|
parseNarrationTimingJson,
|
|
@@ -247,6 +249,7 @@ import {
|
|
|
247
249
|
analyzeBlocks,
|
|
248
250
|
applySavedPresentation,
|
|
249
251
|
applyTransform,
|
|
252
|
+
collectPresentationMedia,
|
|
250
253
|
compilePresentationPlan,
|
|
251
254
|
createPresentationPlan,
|
|
252
255
|
createTransformStyleRegistry,
|
|
@@ -262,7 +265,7 @@ import {
|
|
|
262
265
|
serializePresentationPlan,
|
|
263
266
|
transformNarratedSegment,
|
|
264
267
|
usesDynamicPresentation
|
|
265
|
-
} from "./chunk-
|
|
268
|
+
} from "./chunk-4O26IMVA.js";
|
|
266
269
|
import {
|
|
267
270
|
BASE_INPUT_DESCRIPTORS,
|
|
268
271
|
BLOCK_MEDIA_LAYOUT_POLICIES,
|
|
@@ -386,7 +389,7 @@ import {
|
|
|
386
389
|
wrapWithPersistentLayers,
|
|
387
390
|
writeCustomTemplatesToFrontmatter,
|
|
388
391
|
writeCustomThemesToFrontmatter
|
|
389
|
-
} from "./chunk-
|
|
392
|
+
} from "./chunk-VQXOX3YN.js";
|
|
390
393
|
import {
|
|
391
394
|
ASCII_CHAR_H,
|
|
392
395
|
ASCII_CHAR_W,
|
|
@@ -441,7 +444,7 @@ import {
|
|
|
441
444
|
treeFromMarkdownList,
|
|
442
445
|
treeFromTemplateData,
|
|
443
446
|
treeToTemplateData
|
|
444
|
-
} from "./chunk-
|
|
447
|
+
} from "./chunk-CSR6VCSJ.js";
|
|
445
448
|
import {
|
|
446
449
|
extractContent,
|
|
447
450
|
mapElementToBlock,
|
|
@@ -830,6 +833,7 @@ export {
|
|
|
830
833
|
adjustY,
|
|
831
834
|
advanceCoverage,
|
|
832
835
|
alignNarration,
|
|
836
|
+
alignTranscript,
|
|
833
837
|
allocateTiming,
|
|
834
838
|
analyzeBlocks,
|
|
835
839
|
anchorPoint,
|
|
@@ -894,6 +898,7 @@ export {
|
|
|
894
898
|
coalesceImageEditVersions,
|
|
895
899
|
coalesceVersions,
|
|
896
900
|
coerceTemplateParams,
|
|
901
|
+
collectPresentationMedia,
|
|
897
902
|
comparisonBar,
|
|
898
903
|
compilePresentationPlan,
|
|
899
904
|
compileTheme,
|
|
@@ -1298,6 +1303,7 @@ export {
|
|
|
1298
1303
|
topFeature,
|
|
1299
1304
|
touch,
|
|
1300
1305
|
traceWordPosAt,
|
|
1306
|
+
transcriptWordKeys,
|
|
1301
1307
|
transformNarratedSegment,
|
|
1302
1308
|
transformOriginFor,
|
|
1303
1309
|
transposeCells,
|
|
@@ -568,6 +568,60 @@ interface AlignInput {
|
|
|
568
568
|
}
|
|
569
569
|
declare function alignNarration(input: AlignInput, config?: Partial<AlignConfig>): NarrationAlignment;
|
|
570
570
|
|
|
571
|
+
/**
|
|
572
|
+
* Transcript alignment: word/block timestamps for a recorded take from a
|
|
573
|
+
* speech recognizer's timed transcript.
|
|
574
|
+
*
|
|
575
|
+
* `alignNarration` infers timing from the take's acoustics against the
|
|
576
|
+
* script's expected syllables, so it needs a reader who follows the script
|
|
577
|
+
* closely. This matches the WORDS a recognizer heard to the script's words
|
|
578
|
+
* instead, so it tolerates paraphrase, ad-libs, skipped passages and long
|
|
579
|
+
* silent demos.
|
|
580
|
+
*
|
|
581
|
+
* Pipeline: both sides become normalized word units → word trigrams that
|
|
582
|
+
* occur exactly once on each side anchor a monotone chain (longest increasing
|
|
583
|
+
* subsequence) → the short stretches between anchors are aligned with a small
|
|
584
|
+
* global DP that also accepts near-miss spellings → script words left without
|
|
585
|
+
* a match are placed on the unmatched words heard between their matched
|
|
586
|
+
* neighbors, so a passage the speaker skipped collapses onto the next thing
|
|
587
|
+
* they said, and a long pause or an off-script aside stays with the slide
|
|
588
|
+
* already showing. Block
|
|
589
|
+
* ranges come from the same contiguous-range builder the acoustic aligner
|
|
590
|
+
* uses, with the silences between heard words as its breath gaps.
|
|
591
|
+
*
|
|
592
|
+
* Pure and deterministic, like the rest of the narration engine.
|
|
593
|
+
*/
|
|
594
|
+
|
|
595
|
+
/** One recognized word, in seconds on the take's timeline. */
|
|
596
|
+
interface TranscriptWord {
|
|
597
|
+
text: string;
|
|
598
|
+
startSec: number;
|
|
599
|
+
endSec: number;
|
|
600
|
+
}
|
|
601
|
+
/** One recognized phrase. Without `words`, its time is shared out by syllables. */
|
|
602
|
+
interface TranscriptSegment {
|
|
603
|
+
text: string;
|
|
604
|
+
startSec: number;
|
|
605
|
+
endSec: number;
|
|
606
|
+
words?: readonly TranscriptWord[];
|
|
607
|
+
}
|
|
608
|
+
interface TranscriptAlignInput {
|
|
609
|
+
script: NarrationScript;
|
|
610
|
+
/** Recognized segments on the take's timeline (seconds from its start). */
|
|
611
|
+
segments: readonly TranscriptSegment[];
|
|
612
|
+
/** Take length in seconds (decoded-PCM length). */
|
|
613
|
+
durationSec: number;
|
|
614
|
+
}
|
|
615
|
+
interface TranscriptAlignment extends NarrationAlignment {
|
|
616
|
+
/** Spoken script words whose time came from a matched recognized word. */
|
|
617
|
+
matchedWords: number;
|
|
618
|
+
/** Spoken script words in total. */
|
|
619
|
+
spokenWords: number;
|
|
620
|
+
}
|
|
621
|
+
/** Lowercased letter/digit runs; apostrophes join ("you're" → "youre"). */
|
|
622
|
+
declare function transcriptWordKeys(text: string): string[];
|
|
623
|
+
declare function alignTranscript(input: TranscriptAlignInput, config?: Partial<AlignConfig>): TranscriptAlignment;
|
|
624
|
+
|
|
571
625
|
/** Narration time range of one doc block at record time. */
|
|
572
626
|
interface NarrationTimingBlock {
|
|
573
627
|
/** Doc block id at record time (primary match key; ids can drift on heading edits). */
|
|
@@ -614,8 +668,11 @@ interface NarrationTimingJsonV3 {
|
|
|
614
668
|
* - `'tts'` — a host synthesized the narration (text-to-speech). Block and
|
|
615
669
|
* sentence boundaries are exact because each was synthesized separately;
|
|
616
670
|
* word times are interpolated.
|
|
671
|
+
* - `'transcript-align'` — a speech recognizer transcribed the take and its
|
|
672
|
+
* timed words were matched to the script's words. Paraphrase and skipped
|
|
673
|
+
* passages are tolerated; unmatched words are interpolated.
|
|
617
674
|
*/
|
|
618
|
-
type NarrationTimingMethod = 'dsp-align' | 'presenter-advance' | 'tts';
|
|
675
|
+
type NarrationTimingMethod = 'dsp-align' | 'presenter-advance' | 'tts' | 'transcript-align';
|
|
619
676
|
/** Provenance recorded in a sidecar's `generator` field. */
|
|
620
677
|
interface NarrationTimingGenerator {
|
|
621
678
|
/** Producer id, e.g. `'squisq-teleprompter'` or a host's TTS engine name. */
|
|
@@ -747,4 +804,4 @@ interface AdvanceCoverage {
|
|
|
747
804
|
/** Summarize an advance log against a doc. Pure; drives the review-panel warning. */
|
|
748
805
|
declare function advanceCoverage(doc: Doc, advances: SlideAdvanceLog): AdvanceCoverage;
|
|
749
806
|
|
|
750
|
-
export { type AdvanceCoverage, type AlignConfig, type AlignInput, type BandpassState, type BuildAdvanceTimingOptions, type BuildNarrationTimingOptions, type BuildScriptOptions, DEFAULT_ALIGN_CONFIG, DEFAULT_FEATURE_CONFIG, DEFAULT_NUCLEI_CONFIG, DEFAULT_PACING_CONFIG, DEFAULT_VAD_CONFIG, EMPTY_ADVANCE_LOG, type FeatureConfig, type FeatureState, type FrameFeatures, type NarrationAlignment, type NarrationBlockRange, type NarrationScript, type NarrationSessionConfig, type NarrationSessionState, type NarrationTimingBlock, type NarrationTimingGenerator, type NarrationTimingJsonV3, type NarrationTimingMethod, type NarrationTrace, type NucleiConfig, type NucleiState, type PacingConfig, type PacingState, type PacingTick, type ScriptBlockRange, type ScriptToken, type SlideAdvance, type SlideAdvanceLog, type TraceSample, type VadConfig, type VadState, type WordTiming, advanceCoverage, alignNarration, bandpassRun, buildAdvanceTimingJson, buildNarrationScript, buildNarrationTimingJson, createBandpass, createFeatureState, createNarrationSession, createNucleiState, createPacingState, createVadState, detectSyllableOnsets, downsampleTrace, estimateSyllables, expectedSyllablesAt, extractFrameFeatures, featureStep, narrationSessionStep, nucleiStep, pacingStep, parseNarrationTimingJson, reanchorPacing, reanchorSession, recordSlideShown, resolveNarrationTimingGenerator, traceWordPosAt, vadStep, wordIndexAtChar, wordIndexAtTime, wordPosAtExpectedSyllables };
|
|
807
|
+
export { type AdvanceCoverage, type AlignConfig, type AlignInput, type BandpassState, type BuildAdvanceTimingOptions, type BuildNarrationTimingOptions, type BuildScriptOptions, DEFAULT_ALIGN_CONFIG, DEFAULT_FEATURE_CONFIG, DEFAULT_NUCLEI_CONFIG, DEFAULT_PACING_CONFIG, DEFAULT_VAD_CONFIG, EMPTY_ADVANCE_LOG, type FeatureConfig, type FeatureState, type FrameFeatures, type NarrationAlignment, type NarrationBlockRange, type NarrationScript, type NarrationSessionConfig, type NarrationSessionState, type NarrationTimingBlock, type NarrationTimingGenerator, type NarrationTimingJsonV3, type NarrationTimingMethod, type NarrationTrace, type NucleiConfig, type NucleiState, type PacingConfig, type PacingState, type PacingTick, type ScriptBlockRange, type ScriptToken, type SlideAdvance, type SlideAdvanceLog, type TraceSample, type TranscriptAlignInput, type TranscriptAlignment, type TranscriptSegment, type TranscriptWord, type VadConfig, type VadState, type WordTiming, advanceCoverage, alignNarration, alignTranscript, bandpassRun, buildAdvanceTimingJson, buildNarrationScript, buildNarrationTimingJson, createBandpass, createFeatureState, createNarrationSession, createNucleiState, createPacingState, createVadState, detectSyllableOnsets, downsampleTrace, estimateSyllables, expectedSyllablesAt, extractFrameFeatures, featureStep, narrationSessionStep, nucleiStep, pacingStep, parseNarrationTimingJson, reanchorPacing, reanchorSession, recordSlideShown, resolveNarrationTimingGenerator, traceWordPosAt, transcriptWordKeys, vadStep, wordIndexAtChar, wordIndexAtTime, wordPosAtExpectedSyllables };
|
package/dist/narration/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
EMPTY_ADVANCE_LOG,
|
|
8
8
|
advanceCoverage,
|
|
9
9
|
alignNarration,
|
|
10
|
+
alignTranscript,
|
|
10
11
|
bandpassRun,
|
|
11
12
|
buildAdvanceTimingJson,
|
|
12
13
|
createBandpass,
|
|
@@ -26,8 +27,9 @@ import {
|
|
|
26
27
|
reanchorSession,
|
|
27
28
|
recordSlideShown,
|
|
28
29
|
traceWordPosAt,
|
|
30
|
+
transcriptWordKeys,
|
|
29
31
|
vadStep
|
|
30
|
-
} from "../chunk-
|
|
32
|
+
} from "../chunk-B2MOGSWY.js";
|
|
31
33
|
import "../chunk-NEWNNLWN.js";
|
|
32
34
|
import {
|
|
33
35
|
buildNarrationTimingJson,
|
|
@@ -41,8 +43,8 @@ import {
|
|
|
41
43
|
wordIndexAtChar,
|
|
42
44
|
wordIndexAtTime,
|
|
43
45
|
wordPosAtExpectedSyllables
|
|
44
|
-
} from "../chunk-
|
|
45
|
-
import "../chunk-
|
|
46
|
+
} from "../chunk-VQXOX3YN.js";
|
|
47
|
+
import "../chunk-CSR6VCSJ.js";
|
|
46
48
|
import "../chunk-FUBMT6SJ.js";
|
|
47
49
|
import "../chunk-WNEH3BZP.js";
|
|
48
50
|
import "../chunk-L7QZORLB.js";
|
|
@@ -60,6 +62,7 @@ export {
|
|
|
60
62
|
EMPTY_ADVANCE_LOG,
|
|
61
63
|
advanceCoverage,
|
|
62
64
|
alignNarration,
|
|
65
|
+
alignTranscript,
|
|
63
66
|
bandpassRun,
|
|
64
67
|
buildAdvanceTimingJson,
|
|
65
68
|
buildNarrationScript,
|
|
@@ -85,6 +88,7 @@ export {
|
|
|
85
88
|
recordSlideShown,
|
|
86
89
|
resolveNarrationTimingGenerator,
|
|
87
90
|
traceWordPosAt,
|
|
91
|
+
transcriptWordKeys,
|
|
88
92
|
vadStep,
|
|
89
93
|
wordIndexAtChar,
|
|
90
94
|
wordIndexAtTime,
|
package/dist/recommend/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { R as Doc, s as ColorScheme, k as Block, bt as TemplateBlock } from '../Doc-BQUVDooL.js';
|
|
2
2
|
import { i as PageTransformHints } from '../materializePageSection-_ftXlwvB.js';
|
|
3
3
|
import { d as ExtractionType, E as ExtractedElement, b as ExtractionOptions } from '../contentExtractor-BNfVJV2U.js';
|
|
4
|
-
import { f as BuildSpec } from '../types-Zk8qYuaT.js';
|
|
4
|
+
import { f as BuildSpec, M as MarkdownBlockNode } from '../types-Zk8qYuaT.js';
|
|
5
5
|
|
|
6
6
|
/** Identifier for a built-in or caller-registered transform style. */
|
|
7
7
|
type TransformStyleId = string;
|
|
@@ -336,6 +336,8 @@ interface PresentationBeat {
|
|
|
336
336
|
headline: string;
|
|
337
337
|
points: string[];
|
|
338
338
|
imageSrc?: string;
|
|
339
|
+
/** The section's videos and diagrams shown beside this slide's text (`presentationMedia`). */
|
|
340
|
+
media?: string[];
|
|
339
341
|
}
|
|
340
342
|
interface PresentationPlan {
|
|
341
343
|
version: 1;
|
|
@@ -347,6 +349,7 @@ declare const PRESENTATION_LIMITS: {
|
|
|
347
349
|
readonly sourceCharacters: 40000;
|
|
348
350
|
readonly beats: 80;
|
|
349
351
|
readonly serializedCharacters: 160000;
|
|
352
|
+
readonly mediaPerBeat: 4;
|
|
350
353
|
};
|
|
351
354
|
declare function parsePresentationPlan(input: unknown): PresentationPlan | null;
|
|
352
355
|
declare function serializePresentationPlan(plan: PresentationPlan): string;
|
|
@@ -400,4 +403,22 @@ declare function createPresentationPlan(doc: Doc, hints?: PresentationHints): Pr
|
|
|
400
403
|
declare function compilePresentationPlan(doc: Doc, plan: PresentationPlan): Doc;
|
|
401
404
|
declare function applySavedPresentation(doc: Doc): Doc;
|
|
402
405
|
|
|
403
|
-
|
|
406
|
+
/** The videos and diagrams a narrated section embeds, which dynamic slides show
|
|
407
|
+
* beside its summaries. Images keep their own full-bleed slides; these are the
|
|
408
|
+
* visuals rich-media layout places next to slide text (`appendRichContentLayers`).
|
|
409
|
+
*/
|
|
410
|
+
|
|
411
|
+
interface PresentationMediaItem {
|
|
412
|
+
/** `<section block id>#<index>`, stable while the section's visuals are unchanged. */
|
|
413
|
+
ref: string;
|
|
414
|
+
kind: 'video' | 'diagram';
|
|
415
|
+
/** The body node exactly as authored; slides render it through rich-media layout. */
|
|
416
|
+
node: MarkdownBlockNode;
|
|
417
|
+
/** A diagram, or an HTML video that can resume mid-clip on a following slide. */
|
|
418
|
+
continuous: boolean;
|
|
419
|
+
}
|
|
420
|
+
/** Each section's visuals in source order, claimed like images: a nested
|
|
421
|
+
* block's visuals belong to the nearest narrated section at or before it. */
|
|
422
|
+
declare function collectPresentationMedia(doc: Doc, sectionIds: string[]): Map<string, PresentationMediaItem[]>;
|
|
423
|
+
|
|
424
|
+
export { type AnalyzedBlock, type BlockImage, DEFAULT_TRANSFORM_STYLE_ID, DYNAMIC_PRESENTATION_STYLE, type NarratedSegmentInput, type NarratedSegmentResult, type NarratedSegmentTransformOptions, type NarratedSegmentVideo, PRESENTATION_HINTS_KEY, PRESENTATION_KEY, PRESENTATION_LAYOUTS, PRESENTATION_LIMITS, type PresentationBeat, type PresentationBlockHint, type PresentationHints, type PresentationLayout, type PresentationMediaItem, type PresentationPlan, type TransformImage, type TransformOptions, type TransformResult, type TransformStyleConfig, type TransformStyleId, type TransformStyleInput, type TransformStyleRegistry, type TransformStyleSummary, allocateTiming, analyzeBlocks, applySavedPresentation, applyTransform, collectPresentationMedia, compilePresentationPlan, createPresentationPlan, createTransformStyleRegistry, defaultPresentationHints, extractDocImages, getTransformStyleIds, getTransformStyleSummaries, parsePresentationHints, parsePresentationPlan, presentationSections, resolveTransformStyle, serializePresentationHints, serializePresentationPlan, transformNarratedSegment, usesDynamicPresentation };
|
package/dist/transform/index.js
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
analyzeBlocks,
|
|
10
10
|
applySavedPresentation,
|
|
11
11
|
applyTransform,
|
|
12
|
+
collectPresentationMedia,
|
|
12
13
|
compilePresentationPlan,
|
|
13
14
|
createPresentationPlan,
|
|
14
15
|
createTransformStyleRegistry,
|
|
@@ -24,9 +25,9 @@ import {
|
|
|
24
25
|
serializePresentationPlan,
|
|
25
26
|
transformNarratedSegment,
|
|
26
27
|
usesDynamicPresentation
|
|
27
|
-
} from "../chunk-
|
|
28
|
-
import "../chunk-
|
|
29
|
-
import "../chunk-
|
|
28
|
+
} from "../chunk-4O26IMVA.js";
|
|
29
|
+
import "../chunk-VQXOX3YN.js";
|
|
30
|
+
import "../chunk-CSR6VCSJ.js";
|
|
30
31
|
import "../chunk-SVN7T6BK.js";
|
|
31
32
|
import "../chunk-FUBMT6SJ.js";
|
|
32
33
|
import "../chunk-WNEH3BZP.js";
|
|
@@ -49,6 +50,7 @@ export {
|
|
|
49
50
|
analyzeBlocks,
|
|
50
51
|
applySavedPresentation,
|
|
51
52
|
applyTransform,
|
|
53
|
+
collectPresentationMedia,
|
|
52
54
|
compilePresentationPlan,
|
|
53
55
|
createPresentationPlan,
|
|
54
56
|
createTransformStyleRegistry,
|