-
Notifications
You must be signed in to change notification settings - Fork 1
/
fakeyou.js
146 lines (129 loc) · 3.88 KB
/
fakeyou.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
"use strict";
const { randomUUID } = require("crypto");
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
const { fakeYouToken } = 'SAPI:FTK789_6096133E1D79D6FB'
/*
Name: fetchPatiently(String url, Object params): Object
Description: Wrapper for node-fetch which retries upon 408 and 502 error codes
Returns: HTTP response
*/
async function fetchPatiently(url, params) {
let response = await fetch(url, params);
while (response.status === 408 || response.status === 502) {
// Wait three seconds between each new request
await new Promise(res => setTimeout(res, 3000));
response = await fetch(url, params);
}
return response;
}
/*
Name: poll(String token): String
Description: Polls until a speech request is complete
Returns: URL on success, error string on failure
*/
function poll(token) {
console.log('polling')
return new Promise(async(resolve, reject) => {
// Wait one second between each poll request
await new Promise(res => setTimeout(res, 1000));
// Retrieve status of current speech request
console.log('current state fetching...')
const response = await fetchPatiently(`https://api.fakeyou.com/tts/job/${token}`, {
method: "GET",
headers: {
"Authorization": fakeYouToken,
"Accept": "application/json"
}
}).catch(error => {
reject(`HTTP error! ${error.name}`);
console.error(error);
});
if (!response.ok) return;
const json = await response.json().catch(error => {
reject("Failed to parse poll JSON!");
console.error(error);
});
if (!json) return;
if (!json.success) {
reject(`Failed polling! ${json.error_reason}`);
console.error(json);
return;
}
switch (json.state.status) {
case "pending": {
console.log('pending...')
}
case "started":{
console.log('started...')
}
case "attempt_failed": {
console.log('not done')
// Continue polling until success
await poll(token).then(resolve).catch(reject);
return;
}
case "complete_success": {
console.log('done')
// Success, return audio URL
console.log('link ready')
resolve(`https://storage.googleapis.com/vocodes-public${json.state.maybe_public_bucket_wav_audio_path}`);
return;
}
case "complete_failure":{
console.log('failed permenantly')
}
case "dead":{
console.log('dead now')
}
default: {
console.log('failed')
// Failure, stop polling
reject(`Failed polling! ${json.state.status}`);
console.error(json);
return;
}
}
});
}
/*
Name: requestSpeech(String voice, String message): String
Description: Requests speech and polls until job is complete
Returns: URL on success, error string on failure
*/
module.exports.requestSpeech = (voice, message) => {
console.log('requesting...')
return new Promise(async(resolve, reject) => {
// Request generation of speech
const response = await fetchPatiently("https://api.fakeyou.com/tts/inference", {
method: "POST",
body: JSON.stringify({
tts_model_token: voice,
uuid_idempotency_token: randomUUID(),
inference_text: message
}),
headers: {
"Authorization": fakeYouToken,
"Accept": "application/json",
"Content-Type": "application/json"
}
}).catch(error => {
reject(`HTTP error! ${error.name}`);
console.error(error);
});
if (!response.ok) return;
const json = await response.json().catch(error => {
reject("Failed to parse request JSON!");
console.error(error);
});
if (!json) return;
if (!json.success) {
reject(`Failed voice request! ${json.error_reason}`);
console.error(json);
return;
}
console.log('poll fetching for final token')
// Poll until request has been fulfilled
await poll(json.inference_job_token).then(resolve).catch(reject);
console.log('done')
});
};