@creativeorange/azure-text-to-speech 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 };
|