PageSourceSearch

https://curatti.com/wp-content/plugins/universal-voice-search/js/uvs.speech-handler.js?ver=1791068937

js curatti.com collected 2026-10-03 23:17:51 UTC 13,152 bytes, 352 lines download raw bytes

1// *****************************************************************************************************
2// *******              speak2web UNIVERSAL VOICE SEARCH                                     ***********
3// *******               Get your subscription at                                            ***********
4// *******                    https://speak2web.com/plugin#plans                             ***********
5// *******               Need support? https://speak2web.com/support                         ***********
6// *******               Licensed GPLv2+                                                     ***********
7//******************************************************************************************************
8
9// Cross browser 'trim()' funtion support
10if (typeof String.prototype.trim !== 'function') { String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); } }
11
12var respTimeOut = false;
13var errcnt = 0;
14let uvsHostName = typeof(uvsCurrentHostName) != 'undefined' ? uvsCurrentHostName : null;
15
16/**
17 * An audio player handler Object
18 *
19 */
20var uvsAudioPlayer = {
21    'htmlAudioElement': document.createElement('AUDIO'),
22    'lastFilePath': null,
23    'antiMuteButtonPlaybacks': [uvsSilenceSoundPath],
24    'isAntiMutePlayback': false,
25    'configure': function(filePath = null, playbackEndedCallback = null) {
26        try {
27            let pathOfFile = typeof filePath != 'undefined' && filePath ? filePath : null;
28
29            if (pathOfFile) {
30                let partialFilePath = !!uvsIsMuteSimon ? uvsSilenceSoundPath : pathOfFile;
31                this.htmlAudioElement.src = _uvsPath + partialFilePath;
32                this.htmlAudioElement.preload = 'auto';
33                this.lastFilePath = pathOfFile;
34
35                if (this.antiMuteButtonPlaybacks.indexOf(pathOfFile) !== -1) {
36                    this.isAntiMutePlayback = true;
37                } else {
38                    this.isAntiMutePlayback = false;
39                }
40            } else {
41                this.htmlAudioElement.src = '';
42                this.isAntiMutePlayback = false;
43            }
44
45            /**
46             * The play event occurs when the audio has been started or is no longer paused.
47             */
48            this.htmlAudioElement.onplay = function() {
49                // Do nothing for now
50            }.bind(this);
51
52            /**
53             * The ended event occurs when the audio has reached the end.
54             */
55            this.htmlAudioElement.onended = function() {
56                this.htmlAudioElement.src = ''
57                this.isAntiMutePlayback = false;
58
59                // Callback to be executed when video playback ends
60                if (pathOfFile && (typeof playbackEndedCallback === "function")) {
61                    playbackEndedCallback();
62                    playbackEndedCallback = null;
63                }
64            }.bind(this);
65
66            /**
67             * The error event occurs when an error occurred during the loading of an audio
68             */
69            this.htmlAudioElement.onerror = function() {
70                this.isAntiMutePlayback = false;
71            }.bind(this);
72
73            /**
74             * The playing event occurs when the audio is playing after having been paused or stopped for buffering.
75             */
76            this.htmlAudioElement.onplaying = function() {
77                // Do nothing for now
78            }.bind(this);
79        } catch (err) {
80            this.clear();
81            this.isAntiMutePlayback = false;
82        }
83    },
84    'play': function() {
85        try {
86            if (this.htmlAudioElement && !!this.htmlAudioElement.src) {
87                this.htmlAudioElement.play().catch(function(error){
88                    console.log('VDN Exception: Failed to play audio.');
89                });
90            }
91        } catch (err) {
92            this.clear();
93        }
94    },
95    'stop': function() {
96        try {
97            this.clear();
98        } catch (err) {
99            this.clear();
100        }
101    },
102    'clear': function() {
103        try {
104            if (this.htmlAudioElement) {
105                let duration = isNaN(this.htmlAudioElement.duration) ? 0 : this.htmlAudioElement.duration;
106                this.htmlAudioElement.currentTime = duration;
107            }
108
109            this.lastFilePath = null;
110        } catch (err) {
111            this.lastFilePath = null;
112            this.isAntiMutePlayback = false;
113        }
114    },
115    'isPlaying': function() {
116        let currentTime = isNaN(this.htmlAudioElement.currentTime) ? 0 : this.htmlAudioElement.currentTime;
117        let duration = isNaN(this.htmlAudioElement.duration) ? 0 : this.htmlAudioElement.duration;
118
119        return currentTime < duration;
120    }
121};
122
123function stt(blob, errorRecovery, cb) {    
124    if (errorRecovery == false) {
125        let i = Math.floor(Math.random() * 10); 
126        let resp = uvsAlternativeResponse['randomLib'];
127        
128        if (respTimeOut == false) {
129            // Play 'random' playback
130            uvsAudioPlayer.configure(resp[i]);
131            uvsAudioPlayer.play();
132
133            respTimeOut = true;
134            
135            setTimeout(function () {
136                respTimeOut = false;
137            }, 6000);
138        }
139    }
140   
141}
142
143/**
144 * Function to make asynch call to GCP server for STT
145 *
146 * @param String base64AudioStr  Base64 String representation of Audio Blob
147 * @retur Promise
148 *
149 */
150function uvsGcpStt(base64AudioStr) {
151    return new Promise(function(resolve, reject){
152        if (!(
153            !!uvsSttLanguageContext['gcp']['endPoint'] &&
154            !!uvsSttLanguageContext['gcp']['key'] &&
155            !!uvsSttLanguageContext['gcp']['langCode'] &&
156            typeof base64AudioStr != 'undefined' &&
157            !!base64AudioStr
158            ))
159        {
160            reject(null);
161            return;
162        }
163
164        if (errcnt == 0) {
165            let i = Math.floor(Math.random() * 10); 
166            let resp = uvsAlternativeResponse['randomLib'];
167
168            // Play 'random' playback
169            uvsAudioPlayer.configure(resp[i]);
170            uvsAudioPlayer.play();
171        }
172
173        let uvsXhr = new XMLHttpRequest();
174
175        uvsXhr.onreadystatechange = function () {
176            if (this.readyState == 4) { 
177                try {
178                    let res = JSON.parse(this.response);
179                    
180                    if (this.status === 200) {
181                        errcnt = 0;
182                        let results = typeof res != 'undefined' && res instanceof Object && 'results' in res ? res['results'] : [];
183                        let efficientResult = !!results && results.length > 0 && results[0] instanceof Object ? results[0] : {};
184                        let alternatives = 'alternatives' in efficientResult && !!efficientResult['alternatives'] ? efficientResult['alternatives'] : [];
185                        let alternativeObj = alternatives.length > 0 && alternatives[0] instanceof Object ? alternatives[0] : {};
186                        let transcript = 'transcript' in alternativeObj && !!alternativeObj['transcript'] ? alternativeObj['transcript'] : null;
187
188                        if (typeof transcript != 'undefined' && !!transcript) {
189                            resolve(transcript);
190                        } else {
191                            reject(null);
192                        }
193                    } else {
194                        // Handle response errors
195                        let error = 'error' in res ? res['error'] : {};
196                        let message = 'message' in error && !!error['message'] ? error['message'].toLowerCase() : '';
197
198                        if (errcnt < 1 && !!message && message.indexOf('api key') !== -1) {
199                            errcnt++;
200
201                            //$$$$$$$$$$$$$$$ FETCH NEW TOKEN MIGHT HAVE EXPIRED $$$$$$$$$$$$$$$$$$
202                            uvsRefreshVoiceServicesKeys().then(function(result) {
203                                uvsSttLanguageContext['gcp']['key'] = result;
204
205                                // Try to transcript again with updated key
206                                uvsGcpStt().then(function(res){
207                                    if (!!res) {
208                                        resolve(res);
209                                    } else {
210                                        errcnt = 0;
211                                        reject(null);
212                                    }
213                                }).catch(function(err){
214                                    errcnt = 0;
215                                    reject(null);
216                                })
217                            }).catch(function(error) {
218                                alert(error);
219                                errcnt = 0;
220                                reject(null);
221                            });
222                        } else {
223                            errcnt = 0;
224                            reject(null);
225                        }
226                    }
227                } catch(err) {
228                    reject(null);
229                }
230            }
231        }
232
233        // Handle parsing or transmission errors
234        uvsXhr.onerror = function(error) { reject(null); }
235        
236        uvsXhr.open("POST", uvsSttLanguageContext['gcp']['endPoint'] + uvsSttLanguageContext['gcp']['qs']['key'] + uvsSttLanguageContext['gcp']['key'], true); 
237        uvsXhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
238
239        let recognitionConfig = { 
240            'config': {
241                'encoding': 'ENCODING_UNSPECIFIED',
242                'languageCode': uvsSttLanguageContext['gcp']['langCode'],
243                'enableWordTimeOffsets': false,
244            },
245            'audio': {
246                'content': base64AudioStr
247            },
248        };
249
250        uvsXhr.send(JSON.stringify(recognitionConfig, null, true));
251    })
252}
253
254/**
255 * Function to log STT service call
256 *
257 * @param {uvsUpdateLastValue - int/Number} : 0 to not to update last value or 1 to update last value
258 */
259function uvsLogServiceCall(uvsUpdateLastValue = 0) {
260    try {
261        let uvsXhr = new XMLHttpRequest();
262
263        uvsXhr.onreadystatechange = function () {
264            if (this.readyState == 4 && this.status == 200) {
265                let res = JSON.parse(this.responseText);
266
267                // Update localized variables of service log 
268                uvsServiceLogs.updatedAt    = res.updatedAt || uvsServiceLogs.updatedAt;
269                uvsServiceLogs.currentValue = res.currentValue || uvsServiceLogs.currentValue;
270                uvsServiceLogs.lastValue    = res.lastValue || uvsServiceLogs.lastValue;
271            }
272        };
273
274        uvsXhr.open("POST", uvsAjaxObj.ajax_url , true); 
275        uvsXhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
276        uvsXhr.send("action=uvs_log_service_call&_ajax_nonce=" + uvsAjaxObj.nonce + "&updateLastValue=" + uvsUpdateLastValue);
277    } catch (err) {
278        // Do nothing for now
279    }
280}
281
282/**
283 * Function to get current host/domain full URL
284 *
285 */
286function uvsGetCurrentHostURL() {
287    var currentHostUrl = null;
288    try {
289        if (!(typeof(window.location) != 'undefined' 
290            && typeof(window.location.hostname) != 'undefined' 
291            && typeof(window.location.protocol) != 'undefined')) {
292            return uvsGetHostName();
293        }
294
295        var thisProtocol = window.location.protocol;
296        var thisHostname = window.location.hostname;
297
298        currentHostUrl = thisProtocol + '//' + thisHostname;
299    } catch (err) {
300        currentHostUrl = uvsGetHostName();
301        console.log('Something went wrong while discovering current domain.');
302    }
303
304    return currentHostUrl;
305}
306
307/**
308 * Function to get current host name from backend.
309 */
310function uvsGetHostName() {
311    return uvsHostName;
312}
313
314/**
315 * Function to obtain voice services token and keys
316 *
317 */
318function uvsRefreshVoiceServicesKeys() {   
319    return new Promise(function(resolve, reject){
320        let uvsXhr = new XMLHttpRequest();
321
322        uvsXhr.onreadystatechange = function () {
323            if (this.readyState == 4) { 
324                if (this.status === 200) {
325                    let res = JSON.parse(this.response);
326
327                    if (typeof res == 'undefined') reject(uvsErrorLibrary['outOfService']);
328
329                    if (!!uvsSttLanguageContext['gcp']['stt'] && 'gStt' in res && !!res['gStt']) {
330                        resolve(res['gStt']);
331                        return;
332                    }
333
334                    reject(uvsErrorLibrary['outOfService']);
335                } else {
336                    // Handle response errors
337                    reject(uvsErrorLibrary['outOfService']);
338                }
339            }
340        };
341
342        let queryString = "?action=uvs_refresh_access_keys&_ajax_nonce=" + uvsAjaxObj.keys_nonce;
343        uvsXhr.open("GET", uvsAjaxObj.ajax_url + queryString , true); 
344
345        // Handle parsing or transmission errors
346        uvsXhr.onerror = function(error) { reject(uvsErrorLibrary['outOfService']); }
347        
348        uvsXhr.send(null);
349    });
350}
351
352

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.