Spaces:
Sleeping
Sleeping
Update helpers/tts.js
Browse files- helpers/tts.js +69 -50
helpers/tts.js
CHANGED
@@ -12,8 +12,8 @@ let SSML = `<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml
|
|
12 |
</speak>`;
|
13 |
|
14 |
|
15 |
-
const key = process.env
|
16 |
-
const region = process.env
|
17 |
|
18 |
// Check if variables are loaded
|
19 |
if (!key || !region) {
|
@@ -33,53 +33,72 @@ if (!key || !region) {
|
|
33 |
* @param {*} text text to convert to audio/speech
|
34 |
* @param {*} filename optional - best for long text - temp file for converted speech/audio
|
35 |
*/
|
36 |
-
const textToSpeech = async (text, voice)
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
};
|
85 |
|
|
|
|
12 |
</speak>`;
|
13 |
|
14 |
|
15 |
+
const key = process.env.AZURE_KEY;
|
16 |
+
const region = process.env.AZURE_REGION;
|
17 |
|
18 |
// Check if variables are loaded
|
19 |
if (!key || !region) {
|
|
|
33 |
* @param {*} text text to convert to audio/speech
|
34 |
* @param {*} filename optional - best for long text - temp file for converted speech/audio
|
35 |
*/
|
36 |
+
const textToSpeech = async (text, voice)=> {
|
37 |
+
|
38 |
+
// convert callback function to promise
|
39 |
+
return new Promise((resolve, reject) => {
|
40 |
+
|
41 |
+
|
42 |
+
let ssml = SSML.replace("__TEXT__", text);
|
43 |
+
|
44 |
+
|
45 |
+
const speechConfig = sdk.SpeechConfig.fromSubscription(key, region);
|
46 |
+
speechConfig.speechSynthesisOutputFormat = 5; // mp3
|
47 |
+
|
48 |
+
let audioConfig = null;
|
49 |
+
|
50 |
+
// if (filename) {
|
51 |
+
let randomString = Math.random().toString(36).slice(2, 7);
|
52 |
+
let filename = `./public/speech-${randomString}.mp3`;
|
53 |
+
audioConfig = sdk.AudioConfig.fromAudioFileOutput(filename);
|
54 |
+
// }
|
55 |
+
|
56 |
+
let blendData = [];
|
57 |
+
let timeStep = 1/60;
|
58 |
+
let timeStamp = 0;
|
59 |
+
|
60 |
+
const synthesizer = new sdk.SpeechSynthesizer(speechConfig, audioConfig);
|
61 |
+
|
62 |
+
// Subscribes to viseme received event
|
63 |
+
synthesizer.visemeReceived = function (s, e) {
|
64 |
+
|
65 |
+
// `Animation` is an xml string for SVG or a json string for blend shapes
|
66 |
+
var animation = JSON.parse(e.animation);
|
67 |
+
|
68 |
+
_.each(animation.BlendShapes, blendArray => {
|
69 |
+
|
70 |
+
let blend = {};
|
71 |
+
_.each(blendShapeNames, (shapeName, i) => {
|
72 |
+
blend[shapeName] = blendArray[i];
|
73 |
+
});
|
74 |
+
|
75 |
+
blendData.push({
|
76 |
+
time: timeStamp,
|
77 |
+
blendshapes: blend
|
78 |
+
});
|
79 |
+
|
80 |
+
console.log(`Timestamp: ${timeStamp.toFixed(3)}s`);
|
81 |
+
console.log(JSON.stringify(blend, null, 2));
|
82 |
+
|
83 |
+
timeStamp += timeStep;
|
84 |
+
});
|
85 |
+
|
86 |
+
}
|
87 |
+
|
88 |
+
|
89 |
+
synthesizer.speakSsmlAsync(
|
90 |
+
ssml,
|
91 |
+
result => {
|
92 |
+
|
93 |
+
synthesizer.close();
|
94 |
+
resolve({blendData, filename: `/speech-${randomString}.mp3`});
|
95 |
+
|
96 |
+
},
|
97 |
+
error => {
|
98 |
+
synthesizer.close();
|
99 |
+
reject(error);
|
100 |
+
});
|
101 |
+
});
|
102 |
};
|
103 |
|
104 |
+
module.exports = textToSpeech;
|