Index: chrome/browser/resources/network_speech_synthesis/tts_extension.js |
diff --git a/chrome/browser/resources/network_speech_synthesis/tts_extension.js b/chrome/browser/resources/network_speech_synthesis/tts_extension.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..fb7b449e8d1714d86f31a58fad3c089dec72db88 |
--- /dev/null |
+++ b/chrome/browser/resources/network_speech_synthesis/tts_extension.js |
@@ -0,0 +1,106 @@ |
+// Copyright 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+/** |
+ * @fileoverview |
+ * This is a component extension that implements a speech engine |
+ * powered by Google's speech synthesis API. |
+ * |
+ * This is an "event page", so it's not loaded when the API isn't being used, |
+ * and doesn't waste resources. When a web page or web app makes a speech |
+ * request and the parameters match one of the voices in this extension's |
+ * manifest, it makes a request to Google's API using Chrome's private key |
+ * and plays the resulting speech using HTML5 audio. |
+ */ |
+ |
+/** |
+ * The main class for this extension. Adds listeners to |
+ * chrome.ttsEngine.onSpeak and chrome.ttsEngine.onStop and implements |
+ * them using Google's speech synthesis API. |
+ */ |
+function TtsExtension() { |
David Tseng
2013/10/17 20:43:49
Do you want to declare this function globally?
Per
dmazzoni
2013/10/18 16:23:19
I think this is the Chrome idiomatic style for dec
|
+} |
+ |
+TtsExtension.prototype = { |
David Tseng
2013/10/17 20:56:30
I personally don't mind this style of js, but let'
dmazzoni
2013/10/18 16:23:19
I don't have a strong preference, I was just tryin
|
+ speechServerUrl_: |
David Tseng
2013/10/17 20:43:49
@private, @const; SPEECH_SERVER_URL_
dmazzoni
2013/10/18 16:23:19
Done.
|
+ 'https://www.google.com/speech-api/v2/synthesize?enc=mpeg&client=chromium', |
+ |
+ currentUtterance_: null, |
+ |
+ audioElement_: null, |
David Tseng
2013/10/17 20:43:49
JS doc for all of these please.
dmazzoni
2013/10/18 16:23:19
Done.
|
+ |
+ run: function() { |
+ this.audioElement_ = document.createElement('audio'); |
+ document.body.appendChild(this.audioElement_); |
+ this.audioElement_.addEventListener('ended', (function() { |
+ this.onStop_(); |
+ }).bind(this), false); |
+ |
+ this.audioElement_.addEventListener('canplaythrough', (function() { |
+ if (this.currentUtterance_) { |
+ this.audioElement_.play(); |
+ this.currentUtterance_.callback({ |
+ 'type': 'start', |
+ 'charIndex': 0 |
+ }); |
+ } |
+ }).bind(this), false); |
+ |
+ chrome.ttsEngine.onSpeak.addListener(this.onSpeak_.bind(this)); |
+ chrome.ttsEngine.onStop.addListener(this.onStop_.bind(this)); |
+ }, |
+ |
+ onSpeak_: function(utterance, options, callback) { |
+ // Truncate the utterance if it's too long. |
David Tseng
2013/10/17 20:43:49
Why not just chunk the utterance? (and queue up ad
dmazzoni
2013/10/18 16:23:19
Both Chrome's tts extension api and the web speech
|
+ utterance = escape(utterance); |
+ if (utterance.length > 32768) |
+ utterance = utterance.substr(0, 32768); |
+ |
+ try { |
+ this.onStop_(); |
David Tseng
2013/10/17 20:43:49
Can we get this engine to respect queue mode? (per
dmazzoni
2013/10/18 16:23:19
The queue is managed by Chrome. A ttsEngine just n
|
+ this.currentUtterance_ = { |
+ utterance: utterance, |
+ options: options, |
+ callback: callback |
+ }; |
+ |
+ var url = this.speechServerUrl_; |
+ chrome.systemPrivate.getApiKey((function(key) { |
+ url += '&key=' + key; |
+ url += '&text=' + utterance; |
+ url += '&lang=' + options.lang.toLowerCase(); |
+ if (options.rate) { |
+ url += '&speed=' + (options.rate / 2.0); |
David Tseng
2013/10/17 20:43:49
Can you comment on the range expected?
dmazzoni
2013/10/18 16:23:19
Done.
|
+ } |
+ if (options.pitch) { |
+ url += '&pitch=' + (options.pitch / 2.0); |
David Tseng
2013/10/17 20:43:49
Ditto.
dmazzoni
2013/10/18 16:23:19
Done.
|
+ } |
+ if (options.volume) { |
+ url += '&vol=' + options.volume; |
David Tseng
2013/10/17 20:43:49
Couldn't we just handle volume directly in the pla
dmazzoni
2013/10/18 16:23:19
Sure, done. Actually I see one potential advantage
|
+ } |
+ this.audioElement_.src = url; |
+ }).bind(this)); |
+ } catch (err) { |
+ console.log(String(err)); |
David Tseng
2013/10/17 20:43:49
console.error
dmazzoni
2013/10/18 16:23:19
Done.
|
+ callback({ |
+ 'type': 'error', |
+ 'errorMessage': String(err) |
+ }); |
+ this.currentUtterance_ = null; |
+ } |
+ }, |
+ |
+ onStop_: function() { |
+ if (this.currentUtterance_) { |
+ this.audioElement_.pause(); |
+ this.currentUtterance_.callback({ |
+ 'type': 'end', |
+ 'charIndex': this.currentUtterance_.utterance.length |
+ }); |
+ } |
+ this.currentUtterance_ = null; |
+ } |
+}; |
+ |
+(new TtsExtension()).run(); |