Use the chrome.experimental.ttsEngine module to implement a text-to-speech (TTS) engine using an extension. If your extension registers using this API, it will receive events containing the intended utterance and other parameters when any extension or packaged app uses the experimental.tts module to generate speech. Your extension can then use any available web technology to synthesize and output the speech, and send events back to the calling function to report the status.

Give us feedback: If you have suggestions, especially changes that should be made before stabilizing the first version of this API, please send your ideas to the chromium-extensions group.

Overview

To enable this experimental API, visit chrome://flags and enable Experimental Extension APIs.

An extension can register itself as a speech engine. By doing so, it can intercept some or all calls to functions such as speak() and stop() and provide an alternate implementation. Extensions are free to use any available web technology to provide speech, including streaming audio from a server, HTML5 audio, Native Client, or Flash. An extension could even do something different with the utterances, like display closed captions in a pop-up window or send them as log messages to a remote server.

Manifest

To implement a TTS engine, an extension must first declare all voices it provides in the extension manifest, like this:

{
  "name": "My TTS Engine",
  "version": "1.0",
  "permissions": ["experimental"],
  "tts_engine": {
    "voices": [
      {
        "voice_name": "Alice",
        "lang": "en-US",
        "gender": "female",
        "event_types": ["start", "marker", "end"]
      },
      {
        "voice_name": "Pat",
        "lang": "en-US",
        "event_types": ["end"]
      }
    ]
  },
  "background_page": "background.html",
}

An extension can specify any number of voices.

The voice_name parameter is required. The name should be descriptive enough that it identifies the name of the voice and the engine used. In the unlikely event that two extensions register voices with the same name, a client can manually specify the extension id it wants to do the synthesis.

The gender parameter is optional. If your voice corresponds to a male or female voice, you can use this parameter to help clients choose the most appropriate voice for their application.

The lang parameter is optional, but highly recommended. Almost always, a voice can synthesize speech in just a single language. When an engine supports more than one language, it can easily register a separate voice for each language. Under rare circumstances where a single voice can handle more than one language, it's easiest to just list two separate voices and handle them using the same logic internally. However, if you want to create a voice that will handle utterances in any language, leave out the lang parameter from your extension's manifest.

Finally, the event_types parameter is required if the engine can send events to update the client on the progress of speech synthesis. At a minimum, supporting the 'end' event type to indicate when speech is finished is highly recommend, otherwise it's impossible for Chrome to schedule queued utterances.

If your TTS engine does not support the 'end' event type, Chrome will pass the enqueue option to onSpeak, so that your engine can implement its own queuing. However, this is discouraged because it means that users cannot queue utterances that get sent to different speech engines.

The possible event types you can send correspond to the event types that the speak() method receives:

The 'interrupted' and 'cancelled' events are not sent by the speech engine; they are generated automatically by Chrome.

The information about your extensions's voices from your manifest will be returned to any client that calls getVoices, assuming you've also registered speech event listeners as described below.

Handling Speech Events

To generate speech at the request of clients, your extension must register listeners for both onSpeak and onStop, like this:

var speakListener = function(utterance, options, sendTtsEvent) {
  sendTtsEvent({'event_type': 'start', 'charIndex': 0})

  // (start speaking)

  sendTtsEvent({'event_type': 'end', 'charIndex': utterance.length})
};

var stopListener = function() {
  // (stop all speech)
};

chrome.experimental.ttsEngine.onSpeak.addListener(speakListener);
chrome.experimental.ttsEngine.onStop.addListener(stopListener);

If an extension does not register listeners for both onSpeak and onStop, it will not intercept any speech calls, regardless of what is in the manifest.

The decision of whether or not to send a given speech request to an extension is based solely on whether the extension supports the given voice parameters in its manifest and has registered listeners for onSpeak and onStop. In other words, there's no way for an extension to receive a speech request and dynamically decide whether to handle it or not.