@storyteller-platform/align 0.1.48 → 0.1.50
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/align/align.cjs +6 -1
- package/dist/align/align.js +10 -2
- package/dist/align/interpolateSentenceRanges.cjs +79 -33
- package/dist/align/interpolateSentenceRanges.d.cts +15 -2
- package/dist/align/interpolateSentenceRanges.d.ts +15 -2
- package/dist/align/interpolateSentenceRanges.js +77 -32
- package/package.json +1 -1
package/dist/align/align.cjs
CHANGED
|
@@ -689,17 +689,22 @@ class Aligner {
|
|
|
689
689
|
});
|
|
690
690
|
const sentenceRanges = [];
|
|
691
691
|
const chapterSentenceCounts = {};
|
|
692
|
+
const sentenceLengths = {};
|
|
692
693
|
for (const alignedChapter of audioOrderedChapters) {
|
|
693
694
|
sentenceRanges.push(...alignedChapter.sentenceRanges);
|
|
694
695
|
const sentences = await this.getChapterSentences(
|
|
695
696
|
alignedChapter.chapter.id
|
|
696
697
|
);
|
|
697
698
|
chapterSentenceCounts[alignedChapter.chapter.id] = sentences.length;
|
|
699
|
+
for (const [id, sentence] of (0, import_itertools.enumerate)(sentences)) {
|
|
700
|
+
sentenceLengths[(0, import_interpolateSentenceRanges.slotKey)({ chapterId: alignedChapter.chapter.id, id })] = sentence.text.length;
|
|
701
|
+
}
|
|
698
702
|
}
|
|
699
703
|
const interpolated = (0, import_interpolateSentenceRanges.interpolateSentenceRanges)(
|
|
700
704
|
sentenceRanges,
|
|
701
705
|
chapterSentenceCounts,
|
|
702
|
-
this.audioFileDurations
|
|
706
|
+
this.audioFileDurations,
|
|
707
|
+
sentenceLengths
|
|
703
708
|
);
|
|
704
709
|
const expanded = (0, import_getSentenceRanges.expandEmptySentenceRanges)(interpolated);
|
|
705
710
|
const collapsed = await (0, import_getSentenceRanges.collapseSentenceRangeGaps)(expanded);
|
package/dist/align/align.js
CHANGED
|
@@ -43,7 +43,10 @@ import {
|
|
|
43
43
|
getSentenceRanges,
|
|
44
44
|
mapTranscriptionTimeline
|
|
45
45
|
} from "./getSentenceRanges.js";
|
|
46
|
-
import {
|
|
46
|
+
import {
|
|
47
|
+
interpolateSentenceRanges,
|
|
48
|
+
slotKey
|
|
49
|
+
} from "./interpolateSentenceRanges.js";
|
|
47
50
|
import { findBoundaries } from "./search.js";
|
|
48
51
|
import { slugify } from "./slugify.js";
|
|
49
52
|
import { TextFragmentFactory } from "./textFragments.js";
|
|
@@ -635,17 +638,22 @@ class Aligner {
|
|
|
635
638
|
});
|
|
636
639
|
const sentenceRanges = [];
|
|
637
640
|
const chapterSentenceCounts = {};
|
|
641
|
+
const sentenceLengths = {};
|
|
638
642
|
for (const alignedChapter of audioOrderedChapters) {
|
|
639
643
|
sentenceRanges.push(...alignedChapter.sentenceRanges);
|
|
640
644
|
const sentences = await this.getChapterSentences(
|
|
641
645
|
alignedChapter.chapter.id
|
|
642
646
|
);
|
|
643
647
|
chapterSentenceCounts[alignedChapter.chapter.id] = sentences.length;
|
|
648
|
+
for (const [id, sentence] of enumerate(sentences)) {
|
|
649
|
+
sentenceLengths[slotKey({ chapterId: alignedChapter.chapter.id, id })] = sentence.text.length;
|
|
650
|
+
}
|
|
644
651
|
}
|
|
645
652
|
const interpolated = interpolateSentenceRanges(
|
|
646
653
|
sentenceRanges,
|
|
647
654
|
chapterSentenceCounts,
|
|
648
|
-
this.audioFileDurations
|
|
655
|
+
this.audioFileDurations,
|
|
656
|
+
sentenceLengths
|
|
649
657
|
);
|
|
650
658
|
const expanded = expandEmptySentenceRanges(interpolated);
|
|
651
659
|
const collapsed = await collapseSentenceRangeGaps(expanded);
|
|
@@ -18,55 +18,76 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var interpolateSentenceRanges_exports = {};
|
|
20
20
|
__export(interpolateSentenceRanges_exports, {
|
|
21
|
-
interpolateSentenceRanges: () => interpolateSentenceRanges
|
|
21
|
+
interpolateSentenceRanges: () => interpolateSentenceRanges,
|
|
22
|
+
slotKey: () => slotKey
|
|
22
23
|
});
|
|
23
24
|
module.exports = __toCommonJS(interpolateSentenceRanges_exports);
|
|
24
|
-
function
|
|
25
|
+
function slotKey(slot) {
|
|
26
|
+
return `${slot.chapterId}\0${slot.id}`;
|
|
27
|
+
}
|
|
28
|
+
function slotWeight(slot, sentenceLengths) {
|
|
29
|
+
const length = sentenceLengths[slotKey(slot)];
|
|
30
|
+
return length && length > 0 ? length : 1;
|
|
31
|
+
}
|
|
32
|
+
function buildGapRanges(slots, left, right, audioFileDurations, sentenceLengths) {
|
|
25
33
|
const n = slots.length;
|
|
26
34
|
if (n === 0) return [];
|
|
35
|
+
const weights = slots.map((slot) => slotWeight(slot, sentenceLengths));
|
|
27
36
|
if (left.audiofile === right.audiofile) {
|
|
28
37
|
const span = right.time - left.time;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
38
|
+
const totalWeight2 = weights.reduce((a, b) => a + b, 0);
|
|
39
|
+
const result2 = [];
|
|
40
|
+
let cursor = left.time;
|
|
41
|
+
for (const [i, slot] of slots.entries()) {
|
|
42
|
+
const start = cursor;
|
|
43
|
+
const end = start + span * weights[i] / totalWeight2;
|
|
44
|
+
result2.push({ ...slot, audiofile: left.audiofile, start, end });
|
|
45
|
+
cursor = end;
|
|
46
|
+
}
|
|
47
|
+
return result2;
|
|
35
48
|
}
|
|
36
49
|
const leftDuration = audioFileDurations[left.audiofile] ?? left.time;
|
|
37
50
|
const leftAvail = leftDuration - left.time;
|
|
38
51
|
const rightAvail = right.time;
|
|
39
52
|
const total = leftAvail + rightAvail;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
n1 =
|
|
43
|
-
|
|
53
|
+
const totalWeight = weights.reduce((a, b) => a + b, 0);
|
|
54
|
+
const leftWeightShare = total > 0 ? totalWeight * (leftAvail / total) : totalWeight;
|
|
55
|
+
let n1 = 0;
|
|
56
|
+
let accumulatedWeight = 0;
|
|
57
|
+
while (n1 < n && // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
58
|
+
accumulatedWeight + weights[n1] / 2 <= leftWeightShare) {
|
|
59
|
+
accumulatedWeight += weights[n1];
|
|
60
|
+
n1++;
|
|
61
|
+
}
|
|
62
|
+
const n2 = n - n1;
|
|
44
63
|
const result = [];
|
|
45
64
|
if (n1 > 0) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
});
|
|
65
|
+
const leftSlots = slots.slice(0, n1);
|
|
66
|
+
const leftWeights = weights.slice(0, n1);
|
|
67
|
+
const leftTotalWeight = leftWeights.reduce((a, b) => a + b, 0);
|
|
68
|
+
let cursor = left.time;
|
|
69
|
+
for (const [i, slot] of leftSlots.entries()) {
|
|
70
|
+
const start = cursor;
|
|
71
|
+
const end = start + leftAvail * leftWeights[i] / leftTotalWeight;
|
|
72
|
+
result.push({ ...slot, audiofile: left.audiofile, start, end });
|
|
73
|
+
cursor = end;
|
|
54
74
|
}
|
|
55
75
|
}
|
|
56
76
|
if (n2 > 0) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
});
|
|
77
|
+
const rightSlots = slots.slice(n1);
|
|
78
|
+
const rightWeights = weights.slice(n1);
|
|
79
|
+
const rightTotalWeight = rightWeights.reduce((a, b) => a + b, 0);
|
|
80
|
+
let cursor = 0;
|
|
81
|
+
for (const [i, slot] of rightSlots.entries()) {
|
|
82
|
+
const start = cursor;
|
|
83
|
+
const end = start + rightAvail * rightWeights[i] / rightTotalWeight;
|
|
84
|
+
result.push({ ...slot, audiofile: right.audiofile, start, end });
|
|
85
|
+
cursor = end;
|
|
65
86
|
}
|
|
66
87
|
}
|
|
67
88
|
return result;
|
|
68
89
|
}
|
|
69
|
-
function interpolateSentenceRanges(sentenceRanges, chapterSentenceCounts, audioFileDurations) {
|
|
90
|
+
function interpolateSentenceRanges(sentenceRanges, chapterSentenceCounts, audioFileDurations, sentenceLengths = {}) {
|
|
70
91
|
if (sentenceRanges.length === 0) return [];
|
|
71
92
|
const result = [];
|
|
72
93
|
const first = sentenceRanges[0];
|
|
@@ -77,7 +98,15 @@ function interpolateSentenceRanges(sentenceRanges, chapterSentenceCounts, audioF
|
|
|
77
98
|
}));
|
|
78
99
|
const left = { time: 0, audiofile: first.audiofile };
|
|
79
100
|
const right = { time: first.start, audiofile: first.audiofile };
|
|
80
|
-
result.push(
|
|
101
|
+
result.push(
|
|
102
|
+
...buildGapRanges(
|
|
103
|
+
slots,
|
|
104
|
+
left,
|
|
105
|
+
right,
|
|
106
|
+
audioFileDurations,
|
|
107
|
+
sentenceLengths
|
|
108
|
+
)
|
|
109
|
+
);
|
|
81
110
|
}
|
|
82
111
|
result.push(first);
|
|
83
112
|
for (let idx = 1; idx < sentenceRanges.length; idx++) {
|
|
@@ -100,7 +129,15 @@ function interpolateSentenceRanges(sentenceRanges, chapterSentenceCounts, audioF
|
|
|
100
129
|
}
|
|
101
130
|
}
|
|
102
131
|
if (gapSlots.length > 0) {
|
|
103
|
-
result.push(
|
|
132
|
+
result.push(
|
|
133
|
+
...buildGapRanges(
|
|
134
|
+
gapSlots,
|
|
135
|
+
left,
|
|
136
|
+
right,
|
|
137
|
+
audioFileDurations,
|
|
138
|
+
sentenceLengths
|
|
139
|
+
)
|
|
140
|
+
);
|
|
104
141
|
}
|
|
105
142
|
result.push(curr);
|
|
106
143
|
}
|
|
@@ -114,11 +151,20 @@ function interpolateSentenceRanges(sentenceRanges, chapterSentenceCounts, audioF
|
|
|
114
151
|
const fileEnd = audioFileDurations[last.audiofile] ?? last.end;
|
|
115
152
|
const left = { time: last.end, audiofile: last.audiofile };
|
|
116
153
|
const right = { time: fileEnd, audiofile: last.audiofile };
|
|
117
|
-
result.push(
|
|
154
|
+
result.push(
|
|
155
|
+
...buildGapRanges(
|
|
156
|
+
slots,
|
|
157
|
+
left,
|
|
158
|
+
right,
|
|
159
|
+
audioFileDurations,
|
|
160
|
+
sentenceLengths
|
|
161
|
+
)
|
|
162
|
+
);
|
|
118
163
|
}
|
|
119
164
|
return result;
|
|
120
165
|
}
|
|
121
166
|
// Annotate the CommonJS export names for ESM import in node:
|
|
122
167
|
0 && (module.exports = {
|
|
123
|
-
interpolateSentenceRanges
|
|
168
|
+
interpolateSentenceRanges,
|
|
169
|
+
slotKey
|
|
124
170
|
});
|
|
@@ -3,6 +3,19 @@ import '@storyteller-platform/ghost-story';
|
|
|
3
3
|
import '@echogarden/text-segmentation';
|
|
4
4
|
import '@storyteller-platform/transliteration';
|
|
5
5
|
|
|
6
|
+
/** A "slot" is a sentence that needs to be synthesised. */
|
|
7
|
+
type Slot = {
|
|
8
|
+
chapterId: string;
|
|
9
|
+
id: number;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Maps a slot to the character length of its sentence text, used to weight
|
|
13
|
+
* how much of a gap's time it should occupy. Keyed by `${chapterId}\0${id}`.
|
|
14
|
+
* Slots missing from this map (or with a non-positive length) fall back to
|
|
15
|
+
* a weight of 1, i.e. even division, same as before this map existed.
|
|
16
|
+
*/
|
|
17
|
+
type SentenceLengths = Record<string, number>;
|
|
18
|
+
declare function slotKey(slot: Slot): string;
|
|
6
19
|
/**
|
|
7
20
|
* Given a sequence of sentence ranges from an entire book,
|
|
8
21
|
* ordered by occurrence in audio, interpolates sentence ranges
|
|
@@ -18,6 +31,6 @@ import '@storyteller-platform/transliteration';
|
|
|
18
31
|
* e.g. chapter001#325 -> chapter002#0, where
|
|
19
32
|
* chapterSentenceCounts["chapter001"] === 330
|
|
20
33
|
*/
|
|
21
|
-
declare function interpolateSentenceRanges(sentenceRanges: SentenceRange[], chapterSentenceCounts: Record<string, number>, audioFileDurations: Record<string, number
|
|
34
|
+
declare function interpolateSentenceRanges(sentenceRanges: SentenceRange[], chapterSentenceCounts: Record<string, number>, audioFileDurations: Record<string, number>, sentenceLengths?: SentenceLengths): SentenceRange[];
|
|
22
35
|
|
|
23
|
-
export { interpolateSentenceRanges };
|
|
36
|
+
export { type SentenceLengths, interpolateSentenceRanges, slotKey };
|
|
@@ -3,6 +3,19 @@ import '@storyteller-platform/ghost-story';
|
|
|
3
3
|
import '@echogarden/text-segmentation';
|
|
4
4
|
import '@storyteller-platform/transliteration';
|
|
5
5
|
|
|
6
|
+
/** A "slot" is a sentence that needs to be synthesised. */
|
|
7
|
+
type Slot = {
|
|
8
|
+
chapterId: string;
|
|
9
|
+
id: number;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Maps a slot to the character length of its sentence text, used to weight
|
|
13
|
+
* how much of a gap's time it should occupy. Keyed by `${chapterId}\0${id}`.
|
|
14
|
+
* Slots missing from this map (or with a non-positive length) fall back to
|
|
15
|
+
* a weight of 1, i.e. even division, same as before this map existed.
|
|
16
|
+
*/
|
|
17
|
+
type SentenceLengths = Record<string, number>;
|
|
18
|
+
declare function slotKey(slot: Slot): string;
|
|
6
19
|
/**
|
|
7
20
|
* Given a sequence of sentence ranges from an entire book,
|
|
8
21
|
* ordered by occurrence in audio, interpolates sentence ranges
|
|
@@ -18,6 +31,6 @@ import '@storyteller-platform/transliteration';
|
|
|
18
31
|
* e.g. chapter001#325 -> chapter002#0, where
|
|
19
32
|
* chapterSentenceCounts["chapter001"] === 330
|
|
20
33
|
*/
|
|
21
|
-
declare function interpolateSentenceRanges(sentenceRanges: SentenceRange[], chapterSentenceCounts: Record<string, number>, audioFileDurations: Record<string, number
|
|
34
|
+
declare function interpolateSentenceRanges(sentenceRanges: SentenceRange[], chapterSentenceCounts: Record<string, number>, audioFileDurations: Record<string, number>, sentenceLengths?: SentenceLengths): SentenceRange[];
|
|
22
35
|
|
|
23
|
-
export { interpolateSentenceRanges };
|
|
36
|
+
export { type SentenceLengths, interpolateSentenceRanges, slotKey };
|
|
@@ -1,50 +1,70 @@
|
|
|
1
1
|
import "../chunk-BIEQXUOY.js";
|
|
2
|
-
function
|
|
2
|
+
function slotKey(slot) {
|
|
3
|
+
return `${slot.chapterId}\0${slot.id}`;
|
|
4
|
+
}
|
|
5
|
+
function slotWeight(slot, sentenceLengths) {
|
|
6
|
+
const length = sentenceLengths[slotKey(slot)];
|
|
7
|
+
return length && length > 0 ? length : 1;
|
|
8
|
+
}
|
|
9
|
+
function buildGapRanges(slots, left, right, audioFileDurations, sentenceLengths) {
|
|
3
10
|
const n = slots.length;
|
|
4
11
|
if (n === 0) return [];
|
|
12
|
+
const weights = slots.map((slot) => slotWeight(slot, sentenceLengths));
|
|
5
13
|
if (left.audiofile === right.audiofile) {
|
|
6
14
|
const span = right.time - left.time;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
15
|
+
const totalWeight2 = weights.reduce((a, b) => a + b, 0);
|
|
16
|
+
const result2 = [];
|
|
17
|
+
let cursor = left.time;
|
|
18
|
+
for (const [i, slot] of slots.entries()) {
|
|
19
|
+
const start = cursor;
|
|
20
|
+
const end = start + span * weights[i] / totalWeight2;
|
|
21
|
+
result2.push({ ...slot, audiofile: left.audiofile, start, end });
|
|
22
|
+
cursor = end;
|
|
23
|
+
}
|
|
24
|
+
return result2;
|
|
13
25
|
}
|
|
14
26
|
const leftDuration = audioFileDurations[left.audiofile] ?? left.time;
|
|
15
27
|
const leftAvail = leftDuration - left.time;
|
|
16
28
|
const rightAvail = right.time;
|
|
17
29
|
const total = leftAvail + rightAvail;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
n1 =
|
|
21
|
-
|
|
30
|
+
const totalWeight = weights.reduce((a, b) => a + b, 0);
|
|
31
|
+
const leftWeightShare = total > 0 ? totalWeight * (leftAvail / total) : totalWeight;
|
|
32
|
+
let n1 = 0;
|
|
33
|
+
let accumulatedWeight = 0;
|
|
34
|
+
while (n1 < n && // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
35
|
+
accumulatedWeight + weights[n1] / 2 <= leftWeightShare) {
|
|
36
|
+
accumulatedWeight += weights[n1];
|
|
37
|
+
n1++;
|
|
38
|
+
}
|
|
39
|
+
const n2 = n - n1;
|
|
22
40
|
const result = [];
|
|
23
41
|
if (n1 > 0) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
});
|
|
42
|
+
const leftSlots = slots.slice(0, n1);
|
|
43
|
+
const leftWeights = weights.slice(0, n1);
|
|
44
|
+
const leftTotalWeight = leftWeights.reduce((a, b) => a + b, 0);
|
|
45
|
+
let cursor = left.time;
|
|
46
|
+
for (const [i, slot] of leftSlots.entries()) {
|
|
47
|
+
const start = cursor;
|
|
48
|
+
const end = start + leftAvail * leftWeights[i] / leftTotalWeight;
|
|
49
|
+
result.push({ ...slot, audiofile: left.audiofile, start, end });
|
|
50
|
+
cursor = end;
|
|
32
51
|
}
|
|
33
52
|
}
|
|
34
53
|
if (n2 > 0) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
});
|
|
54
|
+
const rightSlots = slots.slice(n1);
|
|
55
|
+
const rightWeights = weights.slice(n1);
|
|
56
|
+
const rightTotalWeight = rightWeights.reduce((a, b) => a + b, 0);
|
|
57
|
+
let cursor = 0;
|
|
58
|
+
for (const [i, slot] of rightSlots.entries()) {
|
|
59
|
+
const start = cursor;
|
|
60
|
+
const end = start + rightAvail * rightWeights[i] / rightTotalWeight;
|
|
61
|
+
result.push({ ...slot, audiofile: right.audiofile, start, end });
|
|
62
|
+
cursor = end;
|
|
43
63
|
}
|
|
44
64
|
}
|
|
45
65
|
return result;
|
|
46
66
|
}
|
|
47
|
-
function interpolateSentenceRanges(sentenceRanges, chapterSentenceCounts, audioFileDurations) {
|
|
67
|
+
function interpolateSentenceRanges(sentenceRanges, chapterSentenceCounts, audioFileDurations, sentenceLengths = {}) {
|
|
48
68
|
if (sentenceRanges.length === 0) return [];
|
|
49
69
|
const result = [];
|
|
50
70
|
const first = sentenceRanges[0];
|
|
@@ -55,7 +75,15 @@ function interpolateSentenceRanges(sentenceRanges, chapterSentenceCounts, audioF
|
|
|
55
75
|
}));
|
|
56
76
|
const left = { time: 0, audiofile: first.audiofile };
|
|
57
77
|
const right = { time: first.start, audiofile: first.audiofile };
|
|
58
|
-
result.push(
|
|
78
|
+
result.push(
|
|
79
|
+
...buildGapRanges(
|
|
80
|
+
slots,
|
|
81
|
+
left,
|
|
82
|
+
right,
|
|
83
|
+
audioFileDurations,
|
|
84
|
+
sentenceLengths
|
|
85
|
+
)
|
|
86
|
+
);
|
|
59
87
|
}
|
|
60
88
|
result.push(first);
|
|
61
89
|
for (let idx = 1; idx < sentenceRanges.length; idx++) {
|
|
@@ -78,7 +106,15 @@ function interpolateSentenceRanges(sentenceRanges, chapterSentenceCounts, audioF
|
|
|
78
106
|
}
|
|
79
107
|
}
|
|
80
108
|
if (gapSlots.length > 0) {
|
|
81
|
-
result.push(
|
|
109
|
+
result.push(
|
|
110
|
+
...buildGapRanges(
|
|
111
|
+
gapSlots,
|
|
112
|
+
left,
|
|
113
|
+
right,
|
|
114
|
+
audioFileDurations,
|
|
115
|
+
sentenceLengths
|
|
116
|
+
)
|
|
117
|
+
);
|
|
82
118
|
}
|
|
83
119
|
result.push(curr);
|
|
84
120
|
}
|
|
@@ -92,10 +128,19 @@ function interpolateSentenceRanges(sentenceRanges, chapterSentenceCounts, audioF
|
|
|
92
128
|
const fileEnd = audioFileDurations[last.audiofile] ?? last.end;
|
|
93
129
|
const left = { time: last.end, audiofile: last.audiofile };
|
|
94
130
|
const right = { time: fileEnd, audiofile: last.audiofile };
|
|
95
|
-
result.push(
|
|
131
|
+
result.push(
|
|
132
|
+
...buildGapRanges(
|
|
133
|
+
slots,
|
|
134
|
+
left,
|
|
135
|
+
right,
|
|
136
|
+
audioFileDurations,
|
|
137
|
+
sentenceLengths
|
|
138
|
+
)
|
|
139
|
+
);
|
|
96
140
|
}
|
|
97
141
|
return result;
|
|
98
142
|
}
|
|
99
143
|
export {
|
|
100
|
-
interpolateSentenceRanges
|
|
144
|
+
interpolateSentenceRanges,
|
|
145
|
+
slotKey
|
|
101
146
|
};
|
package/package.json
CHANGED