@creativeorange/azure-text-to-speech 1.0.0 → 1.1.0
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/.eslintrc.js +29 -0
- package/dist/co-azure-tts.es.js +104 -42
- package/dist/co-azure-tts.umd.js +5 -5
- package/package.json +9 -7
- package/src/main.ts +130 -56
- package/test.xml +9 -0
- package/vite.config.ts +6 -0
package/.eslintrc.js
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
module.exports = {
|
2
|
+
'env': {
|
3
|
+
'browser': true,
|
4
|
+
'es6': true
|
5
|
+
},
|
6
|
+
'extends': [
|
7
|
+
'eslint:recommended',
|
8
|
+
'plugin:@typescript-eslint/eslint-recommended',
|
9
|
+
'google'
|
10
|
+
],
|
11
|
+
'rules': {
|
12
|
+
'max-len': ['error', {'code': 125}],
|
13
|
+
'indent': ['error', 4],
|
14
|
+
'require-jsdoc': ['error', {
|
15
|
+
'require': {
|
16
|
+
'FunctionDeclaration': false,
|
17
|
+
'MethodDefinition': false,
|
18
|
+
'ClassDeclaration': false,
|
19
|
+
'ArrowFunctionExpression': false,
|
20
|
+
'FunctionExpression': false
|
21
|
+
}
|
22
|
+
}],
|
23
|
+
},
|
24
|
+
'parserOptions': {
|
25
|
+
'sourceType': 'module',
|
26
|
+
},
|
27
|
+
'parser': '@typescript-eslint/parser',
|
28
|
+
"ignorePatterns": ["**/*.html", "**/*.scss"],
|
29
|
+
}
|
package/dist/co-azure-tts.es.js
CHANGED
@@ -5842,7 +5842,7 @@ class RestMessageAdapter {
|
|
5842
5842
|
}
|
5843
5843
|
}
|
5844
5844
|
class TextToSpeech {
|
5845
|
-
constructor(key, region, voice
|
5845
|
+
constructor(key, region, voice) {
|
5846
5846
|
__publicField(this, "key");
|
5847
5847
|
__publicField(this, "region");
|
5848
5848
|
__publicField(this, "voice");
|
@@ -5855,45 +5855,25 @@ class TextToSpeech {
|
|
5855
5855
|
__publicField(this, "player");
|
5856
5856
|
__publicField(this, "synthesizer");
|
5857
5857
|
__publicField(this, "previousWordBoundary");
|
5858
|
+
__publicField(this, "interval");
|
5859
|
+
__publicField(this, "wordEncounters", []);
|
5860
|
+
__publicField(this, "originalHighlightDivInnerHTML", "");
|
5861
|
+
__publicField(this, "currentWord", "");
|
5862
|
+
__publicField(this, "currentOffset", 0);
|
5858
5863
|
this.key = key;
|
5859
5864
|
this.region = region;
|
5860
5865
|
this.voice = voice;
|
5861
5866
|
}
|
5862
5867
|
async start() {
|
5863
|
-
setInterval(() => {
|
5864
|
-
var _a;
|
5865
|
-
if (this.player !== void 0 && this.highlightDiv) {
|
5866
|
-
const currentTime = this.player.currentTime;
|
5867
|
-
let wordBoundary;
|
5868
|
-
for (const e of this.wordBoundryList) {
|
5869
|
-
if (currentTime * 1e3 > e.audioOffset / 1e4) {
|
5870
|
-
wordBoundary = e;
|
5871
|
-
} else {
|
5872
|
-
break;
|
5873
|
-
}
|
5874
|
-
}
|
5875
|
-
if (~[".", ",", "!", "?"].indexOf(wordBoundary.text)) {
|
5876
|
-
wordBoundary = (_a = this.previousWordBoundary) != null ? _a : void 0;
|
5877
|
-
}
|
5878
|
-
if (wordBoundary !== void 0) {
|
5879
|
-
this.previousWordBoundary = wordBoundary;
|
5880
|
-
this.highlightDiv.innerHTML = this.textToRead.substr(0, wordBoundary.textOffset) + "<span class='co-tts-highlight'>" + wordBoundary.text + "</span>" + this.textToRead.substr(wordBoundary.textOffset + wordBoundary.wordLength);
|
5881
|
-
} else {
|
5882
|
-
this.highlightDiv.innerHTML = this.textToRead;
|
5883
|
-
}
|
5884
|
-
}
|
5885
|
-
}, 50);
|
5886
5868
|
await this.registerBindings(document);
|
5887
5869
|
}
|
5888
|
-
async synthesis() {
|
5889
|
-
}
|
5890
5870
|
async registerBindings(node) {
|
5891
|
-
|
5871
|
+
const nodes = node.childNodes;
|
5892
5872
|
for (let i = 0; i < nodes.length; i++) {
|
5893
5873
|
if (!nodes[i]) {
|
5894
5874
|
continue;
|
5895
5875
|
}
|
5896
|
-
|
5876
|
+
const currentNode = nodes[i];
|
5897
5877
|
if (currentNode.attributes) {
|
5898
5878
|
if (currentNode.attributes.getNamedItem("co-tts.id")) {
|
5899
5879
|
await this.handleIdModifier(currentNode, currentNode.attributes.getNamedItem("co-tts.id"));
|
@@ -5918,18 +5898,20 @@ class TextToSpeech {
|
|
5918
5898
|
node.addEventListener("click", async (_) => {
|
5919
5899
|
var _a;
|
5920
5900
|
this.stopPlayer();
|
5901
|
+
await this.createInterval();
|
5921
5902
|
this.clickedNode = node;
|
5922
|
-
|
5903
|
+
const referenceDiv = document.getElementById(attr.value);
|
5923
5904
|
if (!referenceDiv) {
|
5924
5905
|
return;
|
5925
5906
|
}
|
5926
5907
|
if (referenceDiv.hasAttribute("co-tts.text") && referenceDiv.getAttribute("co-tts.text") !== "") {
|
5927
5908
|
this.textToRead = (_a = referenceDiv.getAttribute("co-tts.text")) != null ? _a : "";
|
5928
5909
|
} else {
|
5929
|
-
this.textToRead = referenceDiv.
|
5910
|
+
this.textToRead = referenceDiv.innerHTML;
|
5930
5911
|
}
|
5931
5912
|
if (referenceDiv.hasAttribute("co-tts.highlight")) {
|
5932
5913
|
this.highlightDiv = referenceDiv;
|
5914
|
+
this.originalHighlightDivInnerHTML = referenceDiv.innerHTML;
|
5933
5915
|
}
|
5934
5916
|
this.startSynthesizer(node, attr);
|
5935
5917
|
});
|
@@ -5937,8 +5919,9 @@ class TextToSpeech {
|
|
5937
5919
|
async handleAjaxModifier(node, attr) {
|
5938
5920
|
node.addEventListener("click", async (_) => {
|
5939
5921
|
this.stopPlayer();
|
5922
|
+
await this.createInterval();
|
5940
5923
|
this.clickedNode = node;
|
5941
|
-
|
5924
|
+
const response = await fetch(attr.value, {
|
5942
5925
|
method: `GET`
|
5943
5926
|
});
|
5944
5927
|
this.textToRead = await response.text();
|
@@ -5948,39 +5931,65 @@ class TextToSpeech {
|
|
5948
5931
|
async handleDefault(node, attr) {
|
5949
5932
|
node.addEventListener("click", async (_) => {
|
5950
5933
|
this.stopPlayer();
|
5934
|
+
await this.createInterval();
|
5951
5935
|
this.clickedNode = node;
|
5952
5936
|
if (node.hasAttribute("co-tts.highlight")) {
|
5953
5937
|
this.highlightDiv = node;
|
5938
|
+
this.originalHighlightDivInnerHTML = node.innerHTML;
|
5954
5939
|
}
|
5955
5940
|
if (attr.value === "") {
|
5956
|
-
this.textToRead = node.
|
5941
|
+
this.textToRead = node.innerHTML;
|
5957
5942
|
} else {
|
5958
5943
|
this.textToRead = attr.value;
|
5959
5944
|
}
|
5960
5945
|
this.startSynthesizer(node, attr);
|
5961
5946
|
});
|
5962
5947
|
}
|
5948
|
+
async handleWithoutClick(node, attr) {
|
5949
|
+
this.stopPlayer();
|
5950
|
+
await this.createInterval();
|
5951
|
+
this.clickedNode = node;
|
5952
|
+
if (node.hasAttribute("co-tts.highlight")) {
|
5953
|
+
this.highlightDiv = node;
|
5954
|
+
this.originalHighlightDivInnerHTML = node.innerHTML;
|
5955
|
+
}
|
5956
|
+
if (attr.value === "") {
|
5957
|
+
this.textToRead = node.innerHTML;
|
5958
|
+
} else {
|
5959
|
+
this.textToRead = attr.value;
|
5960
|
+
}
|
5961
|
+
this.startSynthesizer(node, attr);
|
5962
|
+
}
|
5963
5963
|
async handleStopModifier(node, attr) {
|
5964
5964
|
node.addEventListener("click", async (_) => {
|
5965
5965
|
await this.stopPlayer();
|
5966
|
+
document.dispatchEvent(new CustomEvent("COAzureTTSStoppedPlaying", {}));
|
5966
5967
|
});
|
5967
5968
|
}
|
5968
5969
|
async handlePauseModifier(node, attr) {
|
5969
5970
|
node.addEventListener("click", async (_) => {
|
5971
|
+
await this.clearInterval();
|
5970
5972
|
await this.player.pause();
|
5973
|
+
document.dispatchEvent(new CustomEvent("COAzureTTSPausedPlaying", {}));
|
5971
5974
|
});
|
5972
5975
|
}
|
5973
5976
|
async handleResumeModifier(node, attr) {
|
5974
5977
|
node.addEventListener("click", async (_) => {
|
5978
|
+
await this.createInterval();
|
5975
5979
|
await this.player.resume();
|
5980
|
+
document.dispatchEvent(new CustomEvent("COAzureTTSResumedPlaying", {}));
|
5976
5981
|
});
|
5977
5982
|
}
|
5978
5983
|
async stopPlayer() {
|
5984
|
+
await this.clearInterval();
|
5979
5985
|
if (this.highlightDiv !== void 0) {
|
5980
|
-
this.highlightDiv.innerHTML = this.
|
5986
|
+
this.highlightDiv.innerHTML = this.originalHighlightDivInnerHTML;
|
5981
5987
|
}
|
5982
5988
|
this.textToRead = "";
|
5989
|
+
this.currentWord = "";
|
5990
|
+
this.originalHighlightDivInnerHTML = "";
|
5983
5991
|
this.wordBoundryList = [];
|
5992
|
+
this.wordEncounters = [];
|
5984
5993
|
if (this.player !== void 0) {
|
5985
5994
|
this.player.pause();
|
5986
5995
|
}
|
@@ -5989,27 +5998,30 @@ class TextToSpeech {
|
|
5989
5998
|
}
|
5990
5999
|
async startSynthesizer(node, attr) {
|
5991
6000
|
this.speechConfig = SpeechConfig.fromSubscription(this.key, this.region);
|
5992
|
-
|
5993
|
-
|
5994
|
-
} else {
|
5995
|
-
this.speechConfig.speechSynthesisVoiceName = "Microsoft Server Speech Text to Speech Voice (nl-NL, MaartenNeural)";
|
5996
|
-
}
|
5997
|
-
this.speechConfig.speechSynthesisOutputFormat = 8;
|
6001
|
+
this.speechConfig.speechSynthesisVoiceName = `Microsoft Server Speech Text to Speech Voice (${this.voice})`;
|
6002
|
+
this.speechConfig.speechSynthesisOutputFormat = SpeechSynthesisOutputFormat.Audio24Khz160KBitRateMonoMp3;
|
5998
6003
|
this.player = new SpeakerAudioDestination();
|
5999
6004
|
this.audioConfig = AudioConfig.fromSpeakerOutput(this.player);
|
6000
6005
|
this.synthesizer = new SpeechSynthesizer(this.speechConfig, this.audioConfig);
|
6001
6006
|
this.synthesizer.wordBoundary = (s, e) => {
|
6002
6007
|
this.wordBoundryList.push(e);
|
6003
6008
|
};
|
6004
|
-
this.player.onAudioEnd = () => {
|
6009
|
+
this.player.onAudioEnd = async () => {
|
6005
6010
|
this.stopPlayer();
|
6006
6011
|
if (this.clickedNode.hasAttribute("co-tts.next")) {
|
6007
|
-
|
6008
|
-
if (nextNode) {
|
6012
|
+
const nextNode = document.getElementById(this.clickedNode.getAttribute("co-tts.next"));
|
6013
|
+
if (nextNode && nextNode.attributes.getNamedItem("co-tts.text")) {
|
6014
|
+
this.handleWithoutClick(nextNode, nextNode.attributes.getNamedItem("co-tts.text"));
|
6015
|
+
} else if (nextNode) {
|
6009
6016
|
nextNode.dispatchEvent(new Event("click"));
|
6010
6017
|
}
|
6018
|
+
} else {
|
6019
|
+
document.dispatchEvent(new CustomEvent("COAzureTTSFinishedPlaying", {}));
|
6011
6020
|
}
|
6012
6021
|
};
|
6022
|
+
this.player.onAudioStart = async () => {
|
6023
|
+
document.dispatchEvent(new CustomEvent("COAzureTTSStartedPlaying", {}));
|
6024
|
+
};
|
6013
6025
|
this.synthesizer.speakTextAsync(
|
6014
6026
|
this.textToRead,
|
6015
6027
|
() => {
|
@@ -6022,5 +6034,55 @@ class TextToSpeech {
|
|
6022
6034
|
}
|
6023
6035
|
);
|
6024
6036
|
}
|
6037
|
+
async clearInterval() {
|
6038
|
+
clearInterval(this.interval);
|
6039
|
+
}
|
6040
|
+
async createInterval() {
|
6041
|
+
this.interval = setInterval(() => {
|
6042
|
+
var _a;
|
6043
|
+
if (this.player !== void 0 && this.highlightDiv) {
|
6044
|
+
const currentTime = this.player.currentTime;
|
6045
|
+
let wordBoundary;
|
6046
|
+
for (const e of this.wordBoundryList) {
|
6047
|
+
if (currentTime * 1e3 > e.audioOffset / 1e4) {
|
6048
|
+
wordBoundary = e;
|
6049
|
+
} else {
|
6050
|
+
break;
|
6051
|
+
}
|
6052
|
+
}
|
6053
|
+
if (wordBoundary !== void 0) {
|
6054
|
+
if (~[".", ",", "!", "?"].indexOf(wordBoundary.text)) {
|
6055
|
+
wordBoundary = (_a = this.previousWordBoundary) != null ? _a : void 0;
|
6056
|
+
}
|
6057
|
+
if (wordBoundary === void 0) {
|
6058
|
+
this.highlightDiv.innerHTML = this.originalHighlightDivInnerHTML;
|
6059
|
+
} else {
|
6060
|
+
if (!this.wordEncounters[wordBoundary.text]) {
|
6061
|
+
this.wordEncounters[wordBoundary.text] = 0;
|
6062
|
+
}
|
6063
|
+
if (this.currentWord !== wordBoundary.text) {
|
6064
|
+
this.wordEncounters[wordBoundary.text]++;
|
6065
|
+
console.log(this.wordEncounters);
|
6066
|
+
this.currentOffset = this.getPosition(
|
6067
|
+
this.originalHighlightDivInnerHTML,
|
6068
|
+
wordBoundary.text,
|
6069
|
+
this.wordEncounters[wordBoundary.text]
|
6070
|
+
);
|
6071
|
+
this.currentWord = wordBoundary.text;
|
6072
|
+
}
|
6073
|
+
this.previousWordBoundary = wordBoundary;
|
6074
|
+
this.highlightDiv.innerHTML = this.originalHighlightDivInnerHTML.substring(0, this.currentOffset) + "<mark class='co-tts-highlight'>" + wordBoundary.text + "</mark>" + this.originalHighlightDivInnerHTML.substring(this.currentOffset + wordBoundary.wordLength);
|
6075
|
+
}
|
6076
|
+
} else {
|
6077
|
+
this.highlightDiv.innerHTML = this.originalHighlightDivInnerHTML;
|
6078
|
+
}
|
6079
|
+
}
|
6080
|
+
}, 50);
|
6081
|
+
}
|
6082
|
+
getPosition(string, subString, index) {
|
6083
|
+
const regex = new RegExp(`\\b${subString}\\b`, "g");
|
6084
|
+
console.log(string.split(regex, index).join(subString), regex, index);
|
6085
|
+
return string.split(regex, index).join(subString).length;
|
6086
|
+
}
|
6025
6087
|
}
|
6026
6088
|
export { TextToSpeech as default };
|