@creativeorange/azure-text-to-speech 3.0.1 → 3.0.2
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/TextToSpeech.d.ts +17 -9
- package/dist/co-azure-tts.es.js +257 -191
- package/dist/co-azure-tts.umd.js +7 -11
- package/package.json +1 -1
package/dist/co-azure-tts.es.js
CHANGED
|
@@ -8738,6 +8738,24 @@ class SpeechToText {
|
|
|
8738
8738
|
);
|
|
8739
8739
|
}
|
|
8740
8740
|
}
|
|
8741
|
+
const PUNCTUATION_MARKS = [
|
|
8742
|
+
".",
|
|
8743
|
+
",",
|
|
8744
|
+
"!",
|
|
8745
|
+
"?",
|
|
8746
|
+
"*",
|
|
8747
|
+
"(",
|
|
8748
|
+
")",
|
|
8749
|
+
"&",
|
|
8750
|
+
"\\",
|
|
8751
|
+
"/",
|
|
8752
|
+
"^",
|
|
8753
|
+
"[",
|
|
8754
|
+
"]",
|
|
8755
|
+
"<",
|
|
8756
|
+
">",
|
|
8757
|
+
":"
|
|
8758
|
+
];
|
|
8741
8759
|
class TextToSpeech {
|
|
8742
8760
|
constructor(options) {
|
|
8743
8761
|
__publicField(this, "region", "");
|
|
@@ -8753,8 +8771,6 @@ class TextToSpeech {
|
|
|
8753
8771
|
__publicField(this, "player");
|
|
8754
8772
|
__publicField(this, "synthesizer");
|
|
8755
8773
|
__publicField(this, "previousWordBoundary");
|
|
8756
|
-
__publicField(this, "interval");
|
|
8757
|
-
__publicField(this, "wordEncounters", []);
|
|
8758
8774
|
__publicField(this, "originalHighlightDivInnerHTML", "");
|
|
8759
8775
|
__publicField(this, "currentWord", "");
|
|
8760
8776
|
__publicField(this, "currentOffset", 0);
|
|
@@ -8768,6 +8784,8 @@ class TextToSpeech {
|
|
|
8768
8784
|
__publicField(this, "playbackSegments", []);
|
|
8769
8785
|
__publicField(this, "authorizationManager");
|
|
8770
8786
|
__publicField(this, "stopPromise");
|
|
8787
|
+
__publicField(this, "playbackSessionId", 0);
|
|
8788
|
+
__publicField(this, "highlightInterval");
|
|
8771
8789
|
var _a, _b, _c;
|
|
8772
8790
|
if (!options || typeof options.voice !== "string" || options.voice.trim() === "") {
|
|
8773
8791
|
throw new Error("A voice is required.");
|
|
@@ -8843,9 +8861,8 @@ class TextToSpeech {
|
|
|
8843
8861
|
}
|
|
8844
8862
|
async handleIdModifier(node, attr) {
|
|
8845
8863
|
node.addEventListener("click", async (_) => {
|
|
8846
|
-
var _a, _b, _c
|
|
8864
|
+
var _a, _b, _c;
|
|
8847
8865
|
await this.stopPlayer();
|
|
8848
|
-
await this.createInterval();
|
|
8849
8866
|
const referenceDiv = document.getElementById(attr.value);
|
|
8850
8867
|
this.clickedNode = referenceDiv;
|
|
8851
8868
|
if (!referenceDiv) {
|
|
@@ -8856,51 +8873,30 @@ class TextToSpeech {
|
|
|
8856
8873
|
} else {
|
|
8857
8874
|
this.textToRead = (_c = (_b = referenceDiv.innerText) != null ? _b : referenceDiv.textContent) != null ? _c : "";
|
|
8858
8875
|
}
|
|
8859
|
-
|
|
8860
|
-
const highlightTarget = (_e = (_d = referenceDiv.attributes.getNamedItem("co-tts.highlight")) == null ? void 0 : _d.value) != null ? _e : "";
|
|
8861
|
-
if (highlightTarget !== "") {
|
|
8862
|
-
const newReferenceDiv = document.getElementById(highlightTarget);
|
|
8863
|
-
this.highlightDiv = newReferenceDiv;
|
|
8864
|
-
this.originalHighlightDivInnerHTML = (_f = newReferenceDiv == null ? void 0 : newReferenceDiv.innerHTML) != null ? _f : "";
|
|
8865
|
-
} else {
|
|
8866
|
-
this.highlightDiv = referenceDiv;
|
|
8867
|
-
this.originalHighlightDivInnerHTML = referenceDiv.innerHTML;
|
|
8868
|
-
}
|
|
8869
|
-
}
|
|
8876
|
+
this.setHighlightTargetFromNode(referenceDiv);
|
|
8870
8877
|
await this.startSynthesizer(node, attr);
|
|
8871
8878
|
});
|
|
8872
8879
|
}
|
|
8873
8880
|
async handleAjaxModifier(node, attr) {
|
|
8874
8881
|
node.addEventListener("click", async (_) => {
|
|
8875
8882
|
await this.stopPlayer();
|
|
8876
|
-
await this.createInterval();
|
|
8877
8883
|
this.clickedNode = node;
|
|
8878
8884
|
const response = await fetch(attr.value, {
|
|
8879
8885
|
method: `GET`
|
|
8880
8886
|
});
|
|
8881
8887
|
this.textToRead = await response.text();
|
|
8888
|
+
this.setHighlightTargetFromNode(node);
|
|
8882
8889
|
await this.startSynthesizer(node, attr);
|
|
8883
8890
|
});
|
|
8884
8891
|
}
|
|
8885
8892
|
async handleDefault(node, attr) {
|
|
8886
8893
|
node.addEventListener("click", async (_) => {
|
|
8887
|
-
var _a, _b
|
|
8894
|
+
var _a, _b;
|
|
8888
8895
|
await this.stopPlayer();
|
|
8889
|
-
await this.createInterval();
|
|
8890
8896
|
this.clickedNode = node;
|
|
8891
|
-
|
|
8892
|
-
const highlightTarget = (_b = (_a = node.attributes.getNamedItem("co-tts.highlight")) == null ? void 0 : _a.value) != null ? _b : "";
|
|
8893
|
-
if (highlightTarget !== "") {
|
|
8894
|
-
const newReferenceDiv = document.getElementById(highlightTarget);
|
|
8895
|
-
this.highlightDiv = newReferenceDiv;
|
|
8896
|
-
this.originalHighlightDivInnerHTML = (_c = newReferenceDiv == null ? void 0 : newReferenceDiv.innerHTML) != null ? _c : "";
|
|
8897
|
-
} else {
|
|
8898
|
-
this.highlightDiv = node;
|
|
8899
|
-
this.originalHighlightDivInnerHTML = node.innerHTML;
|
|
8900
|
-
}
|
|
8901
|
-
}
|
|
8897
|
+
this.setHighlightTargetFromNode(node);
|
|
8902
8898
|
if (attr.value === "") {
|
|
8903
|
-
this.textToRead = (
|
|
8899
|
+
this.textToRead = (_b = (_a = node.innerText) != null ? _a : node.textContent) != null ? _b : "";
|
|
8904
8900
|
} else {
|
|
8905
8901
|
this.textToRead = attr.value;
|
|
8906
8902
|
}
|
|
@@ -8908,26 +8904,12 @@ class TextToSpeech {
|
|
|
8908
8904
|
});
|
|
8909
8905
|
}
|
|
8910
8906
|
async handleWithoutClick(node, attr) {
|
|
8911
|
-
var _a, _b
|
|
8907
|
+
var _a, _b;
|
|
8912
8908
|
await this.stopPlayer();
|
|
8913
|
-
await this.createInterval();
|
|
8914
8909
|
this.clickedNode = node;
|
|
8915
|
-
|
|
8916
|
-
if (((_a = node.attributes.getNamedItem("co-tts.highlight")) == null ? void 0 : _a.value) !== "") {
|
|
8917
|
-
const newReferenceDiv = document.getElementById(
|
|
8918
|
-
node.attributes.getNamedItem("co-tts.highlight").value
|
|
8919
|
-
);
|
|
8920
|
-
this.highlightDiv = newReferenceDiv;
|
|
8921
|
-
if (newReferenceDiv !== null) {
|
|
8922
|
-
this.originalHighlightDivInnerHTML = newReferenceDiv.innerHTML;
|
|
8923
|
-
}
|
|
8924
|
-
} else {
|
|
8925
|
-
this.highlightDiv = node;
|
|
8926
|
-
this.originalHighlightDivInnerHTML = node.innerHTML;
|
|
8927
|
-
}
|
|
8928
|
-
}
|
|
8910
|
+
this.setHighlightTargetFromNode(node);
|
|
8929
8911
|
if (attr.value === "") {
|
|
8930
|
-
this.textToRead = (
|
|
8912
|
+
this.textToRead = (_b = (_a = node.innerText) != null ? _a : node.textContent) != null ? _b : "";
|
|
8931
8913
|
} else {
|
|
8932
8914
|
this.textToRead = attr.value;
|
|
8933
8915
|
}
|
|
@@ -8944,7 +8926,7 @@ class TextToSpeech {
|
|
|
8944
8926
|
if (!this.player || typeof this.player.pause !== "function") {
|
|
8945
8927
|
return;
|
|
8946
8928
|
}
|
|
8947
|
-
|
|
8929
|
+
this.stopHighlightingInterval();
|
|
8948
8930
|
await this.player.pause();
|
|
8949
8931
|
document.dispatchEvent(new CustomEvent("COAzureTTSPausedPlaying", {}));
|
|
8950
8932
|
});
|
|
@@ -8954,7 +8936,9 @@ class TextToSpeech {
|
|
|
8954
8936
|
if (!this.player) {
|
|
8955
8937
|
return;
|
|
8956
8938
|
}
|
|
8957
|
-
|
|
8939
|
+
if (this.shouldHighlight()) {
|
|
8940
|
+
this.startHighlightingInterval(this.playbackSessionId);
|
|
8941
|
+
}
|
|
8958
8942
|
if (typeof this.player.resume === "function") {
|
|
8959
8943
|
await this.player.resume();
|
|
8960
8944
|
} else if (typeof this.player.play === "function") {
|
|
@@ -8975,8 +8959,9 @@ class TextToSpeech {
|
|
|
8975
8959
|
return this.stopPromise;
|
|
8976
8960
|
}
|
|
8977
8961
|
async performStopPlayer() {
|
|
8978
|
-
|
|
8979
|
-
|
|
8962
|
+
this.invalidatePlaybackSession();
|
|
8963
|
+
this.stopHighlightingInterval();
|
|
8964
|
+
if (this.highlightDiv) {
|
|
8980
8965
|
this.highlightDiv.innerHTML = this.originalHighlightDivInnerHTML;
|
|
8981
8966
|
}
|
|
8982
8967
|
this.resetPlaybackSegments();
|
|
@@ -8985,10 +8970,12 @@ class TextToSpeech {
|
|
|
8985
8970
|
const synthesizer = this.synthesizer;
|
|
8986
8971
|
this.textToRead = "";
|
|
8987
8972
|
this.currentWord = "";
|
|
8973
|
+
this.currentOffset = 0;
|
|
8974
|
+
this.wordBoundaryOffset = 0;
|
|
8988
8975
|
this.originalHighlightDivInnerHTML = "";
|
|
8989
8976
|
this.wordBoundryList = [];
|
|
8990
|
-
this.wordEncounters = [];
|
|
8991
8977
|
this.playbackSegments = [];
|
|
8978
|
+
this.previousWordBoundary = void 0;
|
|
8992
8979
|
this.highlightDiv = void 0;
|
|
8993
8980
|
this.prevTextOffset = 0;
|
|
8994
8981
|
this.playbackTextOffsetBase = void 0;
|
|
@@ -9028,10 +9015,18 @@ class TextToSpeech {
|
|
|
9028
9015
|
async startSynthesizer(_node, _attr) {
|
|
9029
9016
|
try {
|
|
9030
9017
|
this.speechConfig = await this.createSpeechConfig();
|
|
9031
|
-
|
|
9032
|
-
this.
|
|
9033
|
-
|
|
9034
|
-
|
|
9018
|
+
const sessionId = this.createPlaybackSession();
|
|
9019
|
+
this.resetHighlightState();
|
|
9020
|
+
const player = new SpeakerAudioDestination();
|
|
9021
|
+
const audioConfig = AudioConfig.fromSpeakerOutput(player);
|
|
9022
|
+
const synthesizer = new SpeechSynthesizer(this.speechConfig, audioConfig);
|
|
9023
|
+
this.player = player;
|
|
9024
|
+
this.audioConfig = audioConfig;
|
|
9025
|
+
this.synthesizer = synthesizer;
|
|
9026
|
+
synthesizer.wordBoundary = (_s, e) => {
|
|
9027
|
+
if (!this.isActivePlaybackSession(sessionId)) {
|
|
9028
|
+
return;
|
|
9029
|
+
}
|
|
9035
9030
|
this.wordBoundryList.push(e);
|
|
9036
9031
|
};
|
|
9037
9032
|
const playbackChain = this.collectPlaybackChain(this.clickedNode);
|
|
@@ -9041,8 +9036,11 @@ class TextToSpeech {
|
|
|
9041
9036
|
} else {
|
|
9042
9037
|
this.playbackSegments = [];
|
|
9043
9038
|
}
|
|
9044
|
-
|
|
9039
|
+
player.onAudioEnd = async () => {
|
|
9045
9040
|
var _a;
|
|
9041
|
+
if (!this.isActivePlaybackSession(sessionId)) {
|
|
9042
|
+
return;
|
|
9043
|
+
}
|
|
9046
9044
|
const clickedNode = this.clickedNode;
|
|
9047
9045
|
const wasChainedPlayback = this.playbackSegments.length > 0;
|
|
9048
9046
|
const nextNodeId = ((_a = clickedNode == null ? void 0 : clickedNode.hasAttribute) == null ? void 0 : _a.call(clickedNode, "co-tts.next")) ? clickedNode.getAttribute("co-tts.next") : null;
|
|
@@ -9066,23 +9064,39 @@ class TextToSpeech {
|
|
|
9066
9064
|
document.dispatchEvent(new CustomEvent("COAzureTTSFinishedPlaying", {}));
|
|
9067
9065
|
}
|
|
9068
9066
|
};
|
|
9069
|
-
|
|
9067
|
+
player.onAudioStart = async () => {
|
|
9068
|
+
if (!this.isActivePlaybackSession(sessionId)) {
|
|
9069
|
+
return;
|
|
9070
|
+
}
|
|
9070
9071
|
document.dispatchEvent(new CustomEvent("COAzureTTSStartedPlaying", {}));
|
|
9071
9072
|
};
|
|
9073
|
+
if (this.shouldHighlight()) {
|
|
9074
|
+
this.startHighlightingInterval(sessionId);
|
|
9075
|
+
}
|
|
9072
9076
|
if (!isChainedPlayback) {
|
|
9073
9077
|
void this.prefetchNextNode(this.clickedNode);
|
|
9074
9078
|
}
|
|
9075
|
-
this.
|
|
9076
|
-
|
|
9079
|
+
const ssml = this.buildSSML(this.textToRead);
|
|
9080
|
+
synthesizer.speakSsmlAsync(
|
|
9081
|
+
ssml,
|
|
9077
9082
|
() => {
|
|
9078
|
-
this.
|
|
9083
|
+
this.closeResource(synthesizer);
|
|
9084
|
+
if (this.isActivePlaybackSession(sessionId) && this.synthesizer === synthesizer) {
|
|
9085
|
+
this.synthesizer = void 0;
|
|
9086
|
+
}
|
|
9079
9087
|
},
|
|
9080
9088
|
(error) => {
|
|
9089
|
+
this.closeResource(synthesizer);
|
|
9090
|
+
if (!this.isActivePlaybackSession(sessionId)) {
|
|
9091
|
+
return;
|
|
9092
|
+
}
|
|
9093
|
+
if (this.synthesizer === synthesizer) {
|
|
9094
|
+
this.synthesizer = void 0;
|
|
9095
|
+
}
|
|
9081
9096
|
if (isLikelyAuthorizationError(error)) {
|
|
9082
9097
|
this.authorizationManager.clearAuthorization();
|
|
9083
9098
|
}
|
|
9084
9099
|
this.dispatchError(error, "SYNTHESIS_ERROR");
|
|
9085
|
-
this.closeSynthesizer();
|
|
9086
9100
|
void this.stopPlayer();
|
|
9087
9101
|
}
|
|
9088
9102
|
);
|
|
@@ -9129,23 +9143,16 @@ class TextToSpeech {
|
|
|
9129
9143
|
this.textToRead = chain.map((segment) => segment.text).join(" ");
|
|
9130
9144
|
this.highlightDiv = void 0;
|
|
9131
9145
|
this.originalHighlightDivInnerHTML = "";
|
|
9132
|
-
this.
|
|
9133
|
-
this.previousWordBoundary = void 0;
|
|
9134
|
-
this.prevTextOffset = 0;
|
|
9135
|
-
this.playbackTextOffsetBase = void 0;
|
|
9136
|
-
this.currentWord = "";
|
|
9137
|
-
this.currentOffset = 0;
|
|
9138
|
-
this.wordBoundaryOffset = 0;
|
|
9146
|
+
this.resetHighlightState();
|
|
9139
9147
|
}
|
|
9140
9148
|
getHighlightDivForNode(node) {
|
|
9141
|
-
var _a;
|
|
9142
|
-
if (!node.hasAttribute("co-tts.highlight")) {
|
|
9149
|
+
var _a, _b, _c, _d;
|
|
9150
|
+
if (!((_a = node == null ? void 0 : node.hasAttribute) == null ? void 0 : _a.call(node, "co-tts.highlight"))) {
|
|
9143
9151
|
return void 0;
|
|
9144
9152
|
}
|
|
9145
|
-
|
|
9146
|
-
|
|
9147
|
-
|
|
9148
|
-
);
|
|
9153
|
+
const highlightTarget = (_c = (_b = node.attributes.getNamedItem("co-tts.highlight")) == null ? void 0 : _b.value) != null ? _c : "";
|
|
9154
|
+
if (highlightTarget !== "") {
|
|
9155
|
+
return (_d = document.getElementById(highlightTarget)) != null ? _d : void 0;
|
|
9149
9156
|
}
|
|
9150
9157
|
return node;
|
|
9151
9158
|
}
|
|
@@ -9158,16 +9165,14 @@ class TextToSpeech {
|
|
|
9158
9165
|
}
|
|
9159
9166
|
updateChainedHighlight(wordBoundary) {
|
|
9160
9167
|
var _a, _b;
|
|
9161
|
-
if (~
|
|
9168
|
+
if (~PUNCTUATION_MARKS.indexOf(wordBoundary.text)) {
|
|
9162
9169
|
wordBoundary = (_a = this.previousWordBoundary) != null ? _a : void 0;
|
|
9163
9170
|
}
|
|
9164
9171
|
if (!wordBoundary) {
|
|
9165
9172
|
this.resetPlaybackSegments();
|
|
9166
9173
|
return;
|
|
9167
9174
|
}
|
|
9168
|
-
|
|
9169
|
-
this.playbackTextOffsetBase = wordBoundary.textOffset;
|
|
9170
|
-
}
|
|
9175
|
+
this.ensurePlaybackTextOffsetBase();
|
|
9171
9176
|
const normalizedTextOffset = Math.max(
|
|
9172
9177
|
0,
|
|
9173
9178
|
wordBoundary.textOffset - ((_b = this.playbackTextOffsetBase) != null ? _b : 0)
|
|
@@ -9179,21 +9184,12 @@ class TextToSpeech {
|
|
|
9179
9184
|
return;
|
|
9180
9185
|
}
|
|
9181
9186
|
const relativeTextOffset = normalizedTextOffset - segment.start;
|
|
9182
|
-
|
|
9187
|
+
this.highlightTextRange(
|
|
9188
|
+
segment.highlightDiv,
|
|
9183
9189
|
segment.originalHighlightDivInnerHTML,
|
|
9184
|
-
|
|
9185
|
-
|
|
9190
|
+
relativeTextOffset,
|
|
9191
|
+
wordBoundary.wordLength
|
|
9186
9192
|
);
|
|
9187
|
-
if (currentOffset === Number.MAX_SAFE_INTEGER) {
|
|
9188
|
-
this.previousWordBoundary = wordBoundary;
|
|
9189
|
-
return;
|
|
9190
|
-
}
|
|
9191
|
-
const startOfString = segment.originalHighlightDivInnerHTML.substring(0, currentOffset);
|
|
9192
|
-
const endOffset = currentOffset + wordBoundary.wordLength;
|
|
9193
|
-
const endOfString = segment.originalHighlightDivInnerHTML.substring(endOffset);
|
|
9194
|
-
segment.highlightDiv.innerHTML = `
|
|
9195
|
-
${startOfString}<mark class='co-tts-highlight'>${wordBoundary.text}</mark>${endOfString}
|
|
9196
|
-
`;
|
|
9197
9193
|
this.previousWordBoundary = wordBoundary;
|
|
9198
9194
|
}
|
|
9199
9195
|
getNodeText(node, attr) {
|
|
@@ -9300,7 +9296,7 @@ class TextToSpeech {
|
|
|
9300
9296
|
this.prefetchPromises.set(key, prefetchPromise);
|
|
9301
9297
|
}
|
|
9302
9298
|
async playPrefetchedNode(node) {
|
|
9303
|
-
var _a, _b
|
|
9299
|
+
var _a, _b;
|
|
9304
9300
|
const attr = (_a = node.attributes.getNamedItem("co-tts.text")) != null ? _a : node.attributes.getNamedItem("co-tts");
|
|
9305
9301
|
const text = this.getNodeText(node, attr);
|
|
9306
9302
|
const key = this.getPrefetchKey(node, text);
|
|
@@ -9309,39 +9305,28 @@ class TextToSpeech {
|
|
|
9309
9305
|
return false;
|
|
9310
9306
|
}
|
|
9311
9307
|
this.prefetchedAudio.delete(key);
|
|
9308
|
+
const sessionId = this.createPlaybackSession();
|
|
9309
|
+
this.resetHighlightState();
|
|
9312
9310
|
this.clickedNode = node;
|
|
9313
9311
|
this.textToRead = prefetch.text;
|
|
9314
9312
|
this.wordBoundryList = prefetch.wordBoundryList;
|
|
9315
|
-
this.
|
|
9316
|
-
this.
|
|
9317
|
-
this.prevTextOffset = 0;
|
|
9318
|
-
this.currentWord = "";
|
|
9319
|
-
this.currentOffset = 0;
|
|
9320
|
-
this.wordBoundaryOffset = 0;
|
|
9321
|
-
if (node.hasAttribute("co-tts.highlight")) {
|
|
9322
|
-
if (((_c = node.attributes.getNamedItem("co-tts.highlight")) == null ? void 0 : _c.value) !== "") {
|
|
9323
|
-
const newReferenceDiv = document.getElementById(
|
|
9324
|
-
node.attributes.getNamedItem("co-tts.highlight").value
|
|
9325
|
-
);
|
|
9326
|
-
this.highlightDiv = newReferenceDiv;
|
|
9327
|
-
if (newReferenceDiv !== null) {
|
|
9328
|
-
this.originalHighlightDivInnerHTML = newReferenceDiv.innerHTML;
|
|
9329
|
-
}
|
|
9330
|
-
} else {
|
|
9331
|
-
this.highlightDiv = node;
|
|
9332
|
-
this.originalHighlightDivInnerHTML = node.innerHTML;
|
|
9333
|
-
}
|
|
9334
|
-
}
|
|
9335
|
-
await this.createInterval();
|
|
9313
|
+
this.playbackSegments = [];
|
|
9314
|
+
this.setHighlightTargetFromNode(node);
|
|
9336
9315
|
try {
|
|
9337
9316
|
const audio = new Audio(prefetch.url);
|
|
9338
9317
|
this.activePrefetchedAudioUrl = prefetch.url;
|
|
9339
9318
|
this.player = audio;
|
|
9340
9319
|
audio.addEventListener("play", () => {
|
|
9320
|
+
if (!this.isActivePlaybackSession(sessionId)) {
|
|
9321
|
+
return;
|
|
9322
|
+
}
|
|
9341
9323
|
document.dispatchEvent(new CustomEvent("COAzureTTSStartedPlaying", {}));
|
|
9342
9324
|
}, { once: true });
|
|
9343
9325
|
audio.addEventListener("ended", async () => {
|
|
9344
9326
|
var _a2;
|
|
9327
|
+
if (!this.isActivePlaybackSession(sessionId)) {
|
|
9328
|
+
return;
|
|
9329
|
+
}
|
|
9345
9330
|
const clickedNode = this.clickedNode;
|
|
9346
9331
|
const nextNodeId = ((_a2 = clickedNode == null ? void 0 : clickedNode.hasAttribute) == null ? void 0 : _a2.call(clickedNode, "co-tts.next")) ? clickedNode.getAttribute("co-tts.next") : null;
|
|
9347
9332
|
await this.stopPlayer();
|
|
@@ -9361,101 +9346,186 @@ class TextToSpeech {
|
|
|
9361
9346
|
}
|
|
9362
9347
|
}, { once: true });
|
|
9363
9348
|
audio.addEventListener("error", () => {
|
|
9349
|
+
if (!this.isActivePlaybackSession(sessionId)) {
|
|
9350
|
+
return;
|
|
9351
|
+
}
|
|
9364
9352
|
this.dispatchError(
|
|
9365
9353
|
new Error("Prefetched audio resource closed unexpectedly."),
|
|
9366
9354
|
"AUDIO_RESOURCE_ERROR"
|
|
9367
9355
|
);
|
|
9368
9356
|
void this.stopPlayer();
|
|
9369
9357
|
}, { once: true });
|
|
9358
|
+
if (this.shouldHighlight()) {
|
|
9359
|
+
this.startHighlightingInterval(sessionId);
|
|
9360
|
+
}
|
|
9370
9361
|
void this.prefetchNextNode(node);
|
|
9371
9362
|
await audio.play();
|
|
9372
9363
|
return true;
|
|
9373
9364
|
} catch (error) {
|
|
9365
|
+
this.stopHighlightingInterval();
|
|
9374
9366
|
this.dispatchError(error, "AUDIO_RESOURCE_ERROR");
|
|
9375
9367
|
await this.stopPlayer();
|
|
9376
9368
|
return false;
|
|
9377
9369
|
}
|
|
9378
9370
|
}
|
|
9379
|
-
|
|
9380
|
-
|
|
9371
|
+
createPlaybackSession() {
|
|
9372
|
+
this.playbackSessionId += 1;
|
|
9373
|
+
return this.playbackSessionId;
|
|
9381
9374
|
}
|
|
9382
|
-
|
|
9383
|
-
|
|
9384
|
-
|
|
9385
|
-
|
|
9386
|
-
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
|
|
9392
|
-
|
|
9393
|
-
|
|
9394
|
-
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
|
|
9398
|
-
|
|
9399
|
-
|
|
9400
|
-
|
|
9401
|
-
wordBoundary = (_a = this.previousWordBoundary) != null ? _a : void 0;
|
|
9402
|
-
}
|
|
9403
|
-
if (wordBoundary === void 0 || this.prevTextOffset > wordBoundary.prevTextOffset) {
|
|
9404
|
-
this.highlightDiv.innerHTML = this.originalHighlightDivInnerHTML;
|
|
9405
|
-
} else {
|
|
9406
|
-
if (!this.wordEncounters[wordBoundary.text]) {
|
|
9407
|
-
this.wordEncounters[wordBoundary.text] = 0;
|
|
9408
|
-
}
|
|
9409
|
-
this.prevTextOffset = wordBoundary.prevTextOffset;
|
|
9410
|
-
if (this.currentWord !== wordBoundary.text || this.wordBoundaryOffset !== wordBoundary.textOffset) {
|
|
9411
|
-
this.currentOffset = this.getPosition(
|
|
9412
|
-
this.originalHighlightDivInnerHTML,
|
|
9413
|
-
wordBoundary.text,
|
|
9414
|
-
wordBoundary.textOffset
|
|
9415
|
-
);
|
|
9416
|
-
this.wordEncounters[wordBoundary.text] = this.currentOffset + wordBoundary.wordLength;
|
|
9417
|
-
this.currentWord = wordBoundary.text;
|
|
9418
|
-
this.wordBoundaryOffset = wordBoundary.textOffset;
|
|
9419
|
-
}
|
|
9420
|
-
if (this.currentOffset === Number.MAX_SAFE_INTEGER) {
|
|
9421
|
-
this.highlightDiv.innerHTML = this.originalHighlightDivInnerHTML;
|
|
9422
|
-
} else {
|
|
9423
|
-
this.previousWordBoundary = wordBoundary;
|
|
9424
|
-
const startOfString = this.originalHighlightDivInnerHTML.substring(0, this.currentOffset);
|
|
9425
|
-
const endOffset = this.currentOffset + wordBoundary.wordLength;
|
|
9426
|
-
const endOfString = this.originalHighlightDivInnerHTML.substring(endOffset);
|
|
9427
|
-
this.highlightDiv.innerHTML = `
|
|
9428
|
-
${startOfString}<mark class='co-tts-highlight'>${wordBoundary.text}</mark>${endOfString}
|
|
9429
|
-
`;
|
|
9430
|
-
}
|
|
9431
|
-
}
|
|
9432
|
-
} else if (this.playbackSegments.length > 0) {
|
|
9433
|
-
this.resetPlaybackSegments();
|
|
9434
|
-
} else {
|
|
9435
|
-
this.highlightDiv.innerHTML = this.originalHighlightDivInnerHTML;
|
|
9436
|
-
}
|
|
9375
|
+
isActivePlaybackSession(sessionId) {
|
|
9376
|
+
return sessionId === this.playbackSessionId;
|
|
9377
|
+
}
|
|
9378
|
+
invalidatePlaybackSession() {
|
|
9379
|
+
this.playbackSessionId += 1;
|
|
9380
|
+
}
|
|
9381
|
+
stopHighlightingInterval() {
|
|
9382
|
+
if (!this.highlightInterval) {
|
|
9383
|
+
return;
|
|
9384
|
+
}
|
|
9385
|
+
clearInterval(this.highlightInterval);
|
|
9386
|
+
this.highlightInterval = void 0;
|
|
9387
|
+
}
|
|
9388
|
+
startHighlightingInterval(sessionId) {
|
|
9389
|
+
this.stopHighlightingInterval();
|
|
9390
|
+
this.highlightInterval = setInterval(() => {
|
|
9391
|
+
if (!this.isActivePlaybackSession(sessionId)) {
|
|
9392
|
+
this.stopHighlightingInterval();
|
|
9393
|
+
return;
|
|
9437
9394
|
}
|
|
9395
|
+
this.updateHighlightForCurrentTime(sessionId);
|
|
9438
9396
|
}, 50);
|
|
9439
9397
|
}
|
|
9440
|
-
|
|
9441
|
-
|
|
9442
|
-
|
|
9443
|
-
|
|
9444
|
-
|
|
9445
|
-
|
|
9446
|
-
|
|
9447
|
-
|
|
9448
|
-
|
|
9449
|
-
|
|
9450
|
-
|
|
9451
|
-
|
|
9452
|
-
|
|
9398
|
+
updateHighlightForCurrentTime(sessionId) {
|
|
9399
|
+
var _a, _b;
|
|
9400
|
+
if (!this.isActivePlaybackSession(sessionId) || this.player === void 0) {
|
|
9401
|
+
return;
|
|
9402
|
+
}
|
|
9403
|
+
if (!this.shouldHighlight()) {
|
|
9404
|
+
return;
|
|
9405
|
+
}
|
|
9406
|
+
const currentTime = this.player.currentTime;
|
|
9407
|
+
let wordBoundary;
|
|
9408
|
+
for (const e of this.wordBoundryList) {
|
|
9409
|
+
if (currentTime * 1e3 > e.audioOffset / 1e4) {
|
|
9410
|
+
wordBoundary = e;
|
|
9411
|
+
} else {
|
|
9412
|
+
break;
|
|
9453
9413
|
}
|
|
9454
|
-
|
|
9455
|
-
|
|
9414
|
+
}
|
|
9415
|
+
if (wordBoundary === void 0) {
|
|
9416
|
+
this.resetCurrentHighlight();
|
|
9417
|
+
return;
|
|
9418
|
+
}
|
|
9419
|
+
if (this.playbackSegments.length > 0) {
|
|
9420
|
+
this.updateChainedHighlight(wordBoundary);
|
|
9421
|
+
return;
|
|
9422
|
+
}
|
|
9423
|
+
if (~PUNCTUATION_MARKS.indexOf(wordBoundary.text)) {
|
|
9424
|
+
wordBoundary = (_a = this.previousWordBoundary) != null ? _a : void 0;
|
|
9425
|
+
}
|
|
9426
|
+
if (wordBoundary === void 0 || this.prevTextOffset > wordBoundary.textOffset) {
|
|
9427
|
+
this.resetCurrentHighlight();
|
|
9428
|
+
return;
|
|
9429
|
+
}
|
|
9430
|
+
this.prevTextOffset = wordBoundary.textOffset;
|
|
9431
|
+
this.ensurePlaybackTextOffsetBase();
|
|
9432
|
+
const normalizedTextOffset = Math.max(
|
|
9433
|
+
0,
|
|
9434
|
+
wordBoundary.textOffset - ((_b = this.playbackTextOffsetBase) != null ? _b : 0)
|
|
9435
|
+
);
|
|
9436
|
+
this.highlightTextRange(
|
|
9437
|
+
this.highlightDiv,
|
|
9438
|
+
this.originalHighlightDivInnerHTML,
|
|
9439
|
+
normalizedTextOffset,
|
|
9440
|
+
wordBoundary.wordLength
|
|
9441
|
+
);
|
|
9442
|
+
this.previousWordBoundary = wordBoundary;
|
|
9443
|
+
this.currentWord = wordBoundary.text;
|
|
9444
|
+
this.wordBoundaryOffset = wordBoundary.textOffset;
|
|
9445
|
+
}
|
|
9446
|
+
highlightTextRange(target, originalHtml, textOffset, wordLength) {
|
|
9447
|
+
if (!target || wordLength <= 0) {
|
|
9448
|
+
return;
|
|
9449
|
+
}
|
|
9450
|
+
target.innerHTML = originalHtml;
|
|
9451
|
+
const walker = document.createTreeWalker(
|
|
9452
|
+
target,
|
|
9453
|
+
NodeFilter.SHOW_TEXT
|
|
9454
|
+
);
|
|
9455
|
+
let currentOffset = 0;
|
|
9456
|
+
let startNode;
|
|
9457
|
+
let endNode;
|
|
9458
|
+
let startOffset = 0;
|
|
9459
|
+
let endOffset = 0;
|
|
9460
|
+
const requestedEnd = textOffset + wordLength;
|
|
9461
|
+
while (walker.nextNode()) {
|
|
9462
|
+
const node = walker.currentNode;
|
|
9463
|
+
const nodeLength = node.data.length;
|
|
9464
|
+
const nodeStart = currentOffset;
|
|
9465
|
+
const nodeEnd = currentOffset + nodeLength;
|
|
9466
|
+
if (!startNode && textOffset >= nodeStart && textOffset < nodeEnd) {
|
|
9467
|
+
startNode = node;
|
|
9468
|
+
startOffset = textOffset - nodeStart;
|
|
9469
|
+
}
|
|
9470
|
+
if (requestedEnd > nodeStart && requestedEnd <= nodeEnd) {
|
|
9471
|
+
endNode = node;
|
|
9472
|
+
endOffset = requestedEnd - nodeStart;
|
|
9473
|
+
break;
|
|
9456
9474
|
}
|
|
9475
|
+
currentOffset = nodeEnd;
|
|
9476
|
+
}
|
|
9477
|
+
if (!startNode || !endNode) {
|
|
9478
|
+
return;
|
|
9479
|
+
}
|
|
9480
|
+
const range = document.createRange();
|
|
9481
|
+
try {
|
|
9482
|
+
range.setStart(startNode, startOffset);
|
|
9483
|
+
range.setEnd(endNode, endOffset);
|
|
9484
|
+
const mark = document.createElement("mark");
|
|
9485
|
+
mark.className = "co-tts-highlight";
|
|
9486
|
+
mark.appendChild(range.extractContents());
|
|
9487
|
+
range.insertNode(mark);
|
|
9488
|
+
} catch {
|
|
9489
|
+
target.innerHTML = originalHtml;
|
|
9490
|
+
}
|
|
9491
|
+
}
|
|
9492
|
+
setHighlightTargetFromNode(node) {
|
|
9493
|
+
var _a;
|
|
9494
|
+
const highlightDiv = this.getHighlightDivForNode(node);
|
|
9495
|
+
this.highlightDiv = highlightDiv;
|
|
9496
|
+
this.originalHighlightDivInnerHTML = (_a = highlightDiv == null ? void 0 : highlightDiv.innerHTML) != null ? _a : "";
|
|
9497
|
+
}
|
|
9498
|
+
shouldHighlight() {
|
|
9499
|
+
if (this.highlightDiv) {
|
|
9500
|
+
return true;
|
|
9501
|
+
}
|
|
9502
|
+
return this.playbackSegments.some((segment) => Boolean(segment.highlightDiv));
|
|
9503
|
+
}
|
|
9504
|
+
resetHighlightState() {
|
|
9505
|
+
this.prevTextOffset = 0;
|
|
9506
|
+
this.previousWordBoundary = void 0;
|
|
9507
|
+
this.currentWord = "";
|
|
9508
|
+
this.currentOffset = 0;
|
|
9509
|
+
this.wordBoundaryOffset = 0;
|
|
9510
|
+
this.playbackTextOffsetBase = void 0;
|
|
9511
|
+
}
|
|
9512
|
+
ensurePlaybackTextOffsetBase() {
|
|
9513
|
+
if (this.playbackTextOffsetBase !== void 0 || this.wordBoundryList.length === 0) {
|
|
9514
|
+
return;
|
|
9515
|
+
}
|
|
9516
|
+
this.playbackTextOffsetBase = this.wordBoundryList.reduce(
|
|
9517
|
+
(minimum, boundary) => Math.min(minimum, boundary.textOffset),
|
|
9518
|
+
this.wordBoundryList[0].textOffset
|
|
9519
|
+
);
|
|
9520
|
+
}
|
|
9521
|
+
resetCurrentHighlight() {
|
|
9522
|
+
if (this.playbackSegments.length > 0) {
|
|
9523
|
+
this.resetPlaybackSegments();
|
|
9524
|
+
return;
|
|
9525
|
+
}
|
|
9526
|
+
if (this.highlightDiv) {
|
|
9527
|
+
this.highlightDiv.innerHTML = this.originalHighlightDivInnerHTML;
|
|
9457
9528
|
}
|
|
9458
|
-
return string.indexOf(subString);
|
|
9459
9529
|
}
|
|
9460
9530
|
buildSSML(text) {
|
|
9461
9531
|
let ssml = `<speak xmlns="http://www.w3.org/2001/10/synthesis"
|
|
@@ -9477,10 +9547,6 @@ class TextToSpeech {
|
|
|
9477
9547
|
p.textContent = input;
|
|
9478
9548
|
return p.innerHTML;
|
|
9479
9549
|
}
|
|
9480
|
-
closeSynthesizer() {
|
|
9481
|
-
this.closeResource(this.synthesizer);
|
|
9482
|
-
this.synthesizer = void 0;
|
|
9483
|
-
}
|
|
9484
9550
|
closeResource(resource) {
|
|
9485
9551
|
if (!resource || typeof resource.close !== "function") {
|
|
9486
9552
|
return;
|