@creativeorange/azure-text-to-speech 2.2.0 → 2.2.1

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.
@@ -8460,6 +8460,7 @@ class TextToSpeech {
8460
8460
  __publicField(this, "prefetchedAudio", /* @__PURE__ */ new Map());
8461
8461
  __publicField(this, "prefetchPromises", /* @__PURE__ */ new Map());
8462
8462
  __publicField(this, "activePrefetchedAudioUrl", "");
8463
+ __publicField(this, "playbackSegments", []);
8463
8464
  this.key = key;
8464
8465
  this.region = region;
8465
8466
  this.voice = voice;
@@ -8630,6 +8631,8 @@ class TextToSpeech {
8630
8631
  this.originalHighlightDivInnerHTML = "";
8631
8632
  this.wordBoundryList = [];
8632
8633
  this.wordEncounters = [];
8634
+ this.resetPlaybackSegments();
8635
+ this.playbackSegments = [];
8633
8636
  if (this.player !== void 0) {
8634
8637
  this.player.pause();
8635
8638
  }
@@ -8651,8 +8654,20 @@ class TextToSpeech {
8651
8654
  this.synthesizer.wordBoundary = (s, e) => {
8652
8655
  this.wordBoundryList.push(e);
8653
8656
  };
8657
+ const playbackChain = this.collectPlaybackChain(this.clickedNode);
8658
+ const isChainedPlayback = playbackChain.length > 1;
8659
+ if (isChainedPlayback) {
8660
+ this.preparePlaybackChain(playbackChain);
8661
+ } else {
8662
+ this.playbackSegments = [];
8663
+ }
8654
8664
  this.player.onAudioEnd = async () => {
8665
+ const wasChainedPlayback = this.playbackSegments.length > 0;
8655
8666
  this.stopPlayer();
8667
+ if (wasChainedPlayback) {
8668
+ document.dispatchEvent(new CustomEvent("COAzureTTSFinishedPlaying", {}));
8669
+ return;
8670
+ }
8656
8671
  if (this.clickedNode.hasAttribute("co-tts.next")) {
8657
8672
  const nextNode = document.getElementById(this.clickedNode.getAttribute("co-tts.next"));
8658
8673
  if (nextNode && await this.playPrefetchedNode(nextNode)) {
@@ -8670,7 +8685,9 @@ class TextToSpeech {
8670
8685
  this.player.onAudioStart = async () => {
8671
8686
  document.dispatchEvent(new CustomEvent("COAzureTTSStartedPlaying", {}));
8672
8687
  };
8673
- this.prefetchNextNode(this.clickedNode);
8688
+ if (!isChainedPlayback) {
8689
+ this.prefetchNextNode(this.clickedNode);
8690
+ }
8674
8691
  this.synthesizer.speakSsmlAsync(
8675
8692
  this.buildSSML(this.textToRead),
8676
8693
  () => {
@@ -8683,6 +8700,94 @@ class TextToSpeech {
8683
8700
  }
8684
8701
  );
8685
8702
  }
8703
+ collectPlaybackChain(node) {
8704
+ var _a, _b;
8705
+ const chain = [];
8706
+ const seenNodeIds = /* @__PURE__ */ new Set();
8707
+ let currentNode = node;
8708
+ let offset = 0;
8709
+ while (currentNode && !seenNodeIds.has(currentNode.id)) {
8710
+ seenNodeIds.add(currentNode.id);
8711
+ const attr = (_a = currentNode.attributes.getNamedItem("co-tts.text")) != null ? _a : currentNode.attributes.getNamedItem("co-tts");
8712
+ const text = this.getNodeText(currentNode, attr);
8713
+ if (text === "") {
8714
+ break;
8715
+ }
8716
+ const highlightDiv = this.getHighlightDivForNode(currentNode);
8717
+ chain.push({
8718
+ node: currentNode,
8719
+ text,
8720
+ start: offset,
8721
+ end: offset + text.length,
8722
+ highlightDiv,
8723
+ originalHighlightDivInnerHTML: (_b = highlightDiv == null ? void 0 : highlightDiv.innerHTML) != null ? _b : ""
8724
+ });
8725
+ offset += text.length + 2;
8726
+ if (!currentNode.hasAttribute("co-tts.next")) {
8727
+ break;
8728
+ }
8729
+ currentNode = document.getElementById(currentNode.getAttribute("co-tts.next"));
8730
+ }
8731
+ return chain;
8732
+ }
8733
+ preparePlaybackChain(chain) {
8734
+ this.playbackSegments = chain;
8735
+ this.textToRead = chain.map((segment) => segment.text).join(". ");
8736
+ this.highlightDiv = void 0;
8737
+ this.originalHighlightDivInnerHTML = "";
8738
+ this.wordEncounters = [];
8739
+ this.previousWordBoundary = void 0;
8740
+ this.prevTextOffset = 0;
8741
+ this.currentWord = "";
8742
+ this.currentOffset = 0;
8743
+ this.wordBoundaryOffset = 0;
8744
+ }
8745
+ getHighlightDivForNode(node) {
8746
+ var _a;
8747
+ if (!node.hasAttribute("co-tts.highlight")) {
8748
+ return void 0;
8749
+ }
8750
+ if (((_a = node.attributes.getNamedItem("co-tts.highlight")) == null ? void 0 : _a.value) !== "") {
8751
+ return document.getElementById(node.attributes.getNamedItem("co-tts.highlight").value);
8752
+ }
8753
+ return node;
8754
+ }
8755
+ resetPlaybackSegments() {
8756
+ this.playbackSegments.forEach((segment) => {
8757
+ if (segment.highlightDiv) {
8758
+ segment.highlightDiv.innerHTML = segment.originalHighlightDivInnerHTML;
8759
+ }
8760
+ });
8761
+ }
8762
+ updateChainedHighlight(wordBoundary) {
8763
+ var _a;
8764
+ if (~[".", ",", "!", "?", "*", "(", ")", "&", "\\", "/", "^", "[", "]", "<", ">", ":"].indexOf(wordBoundary.text)) {
8765
+ wordBoundary = (_a = this.previousWordBoundary) != null ? _a : void 0;
8766
+ }
8767
+ if (!wordBoundary) {
8768
+ this.resetPlaybackSegments();
8769
+ return;
8770
+ }
8771
+ const segment = this.playbackSegments.find((candidate) => wordBoundary.textOffset >= candidate.start && wordBoundary.textOffset < candidate.end);
8772
+ this.resetPlaybackSegments();
8773
+ if (!(segment == null ? void 0 : segment.highlightDiv)) {
8774
+ this.previousWordBoundary = wordBoundary;
8775
+ return;
8776
+ }
8777
+ const relativeTextOffset = wordBoundary.textOffset - segment.start;
8778
+ const currentOffset = this.getPosition(segment.originalHighlightDivInnerHTML, wordBoundary.text, relativeTextOffset);
8779
+ if (currentOffset === Number.MAX_SAFE_INTEGER) {
8780
+ this.previousWordBoundary = wordBoundary;
8781
+ return;
8782
+ }
8783
+ const startOfString = segment.originalHighlightDivInnerHTML.substring(0, currentOffset);
8784
+ const endOffset = currentOffset + wordBoundary.wordLength;
8785
+ const endOfString = segment.originalHighlightDivInnerHTML.substring(endOffset);
8786
+ segment.highlightDiv.innerHTML = `
8787
+ ${startOfString}<mark class='co-tts-highlight'>${wordBoundary.text}</mark>${endOfString}
8788
+ `;
8789
+ this.previousWordBoundary = wordBoundary;
8790
+ }
8686
8791
  getNodeText(node, attr) {
8687
8792
  var _a;
8688
8793
  if (attr && attr.value !== "") {
@@ -8844,6 +8949,10 @@ class TextToSpeech {
8844
8949
  }
8845
8950
  }
8846
8951
  if (wordBoundary !== void 0) {
8952
+ if (this.playbackSegments.length > 0) {
8953
+ this.updateChainedHighlight(wordBoundary);
8954
+ return;
8955
+ }
8847
8956
  if (~[".", ",", "!", "?", "*", "(", ")", "&", "\\", "/", "^", "[", "]", "<", ">", ":"].indexOf(wordBoundary.text)) {
8848
8957
  wordBoundary = (_a = this.previousWordBoundary) != null ? _a : void 0;
8849
8958
  }