Initial commit

This commit is contained in:
2018-09-22 10:44:38 +08:00
commit eacb95c18a
723 changed files with 100993 additions and 0 deletions
+63
View File
@@ -0,0 +1,63 @@
# Cordova Text-to-Speech Plugin
## Platforms
iOS 7+
Windows Phone 8
Android 4.0.3+ (API Level 15+)
## Installation
```sh
cordova plugin add cordova-plugin-tts
```
## Usage
```javascript
// basic usage
TTS
.speak('hello, world!', function () {
alert('success');
}, function (reason) {
alert(reason);
});
// or with more options
TTS
.speak({
text: 'hello, world!',
locale: 'en-GB',
rate: 0.75
}, function () {
alert('success');
}, function (reason) {
alert(reason);
});
```
**Tips:** `speak` an empty string to interrupt.
## API Definitions
The `onfulfilled` callback will be called when the speech finishes,
and the `onrejected` callback (Windows Phone only) will be called when an error occurs.
If the API is invoked when it's still speaking, the previous speaking will be canceled immediately,
but the `onfulfilled` callback of the previous speaking will be called when it stops.
```typescript
declare module TTS {
interface IOptions {
/** text to speak */
text: string;
/** a string like 'en-US', 'zh-CN', etc */
locale?: string;
/** speed rate, 0 ~ 1 */
rate?: number;
}
function speak(options: IOptions, onfulfilled: () => void, onrejected: (reason) => void): void;
function speak(text: string, onfulfilled: () => void, onrejected: (reason) => void): void;
}
```
+32
View File
@@ -0,0 +1,32 @@
{
"name": "cordova-plugin-tts",
"version": "0.2.3",
"description": "Cordova Text-to-Speech Plugin",
"cordova": {
"id": "cordova-plugin-tts",
"platforms": [
"ios",
"wp8",
"android"
]
},
"repository": {
"type": "git",
"url": "git+https://github.com/vilic/cordova-plugin-tts.git"
},
"keywords": [
"cordova",
"tts",
"text-to-speech",
"ecosystem:cordova",
"cordova-ios",
"cordova-wp8",
"cordova-android"
],
"author": "VILIC VANE",
"license": "MIT",
"bugs": {
"url": "https://github.com/vilic/cordova-plugin-tts/issues"
},
"homepage": "https://github.com/vilic/cordova-plugin-tts#readme"
}
+58
View File
@@ -0,0 +1,58 @@
<?xml version='1.0' encoding='utf-8'?>
<plugin
xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="cordova-plugin-tts"
version="0.2.3">
<name>TTS</name>
<description>Cordova Text-to-Speech Plugin</description>
<author>VILIC VANE</author>
<license>MIT</license>
<keywords>cordova,tts,text-to-speech</keywords>
<repo>https://github.com/vilic/cordova-plugin-tts.git</repo>
<issue>https://github.com/vilic/cordova-plugin-tts/issues</issue>
<js-module src="www/tts.js" name="tts">
<clobbers target="TTS" />
</js-module>
<!-- ios -->
<platform name="ios">
<config-file target="config.xml" parent="/*">
<feature name="TTS">
<param name="ios-package" value="CDVTTS"/>
</feature>
</config-file>
<header-file src="src/ios/CDVTTS.h" />
<source-file src="src/ios/CDVTTS.m" />
</platform>
<!-- windows phone 8 -->
<platform name="wp8">
<config-file target="config.xml" parent="/*">
<feature name="TTS">
<param name="wp-package" value="TTS"/>
</feature>
</config-file>
<config-file target="Properties/WMAppManifest.xml" parent="/*/App/Capabilities">
<Capability Name="ID_CAP_SPEECH_RECOGNITION" />
</config-file>
<source-file src="src/wp/TTS.cs" />
</platform>
<!-- android -->
<platform name="android">
<config-file target="config.xml" parent="/*">
<feature name="TTS">
<param name="android-package" value="com.wordsbaking.cordova.tts.TTS" />
<param name="onload" value="true" />
</feature>
</config-file>
<source-file src="src/android/TTS.java" target-dir="src/com/wordsbaking/cordova/tts" />
</platform>
</plugin>
@@ -0,0 +1,144 @@
package com.wordsbaking.cordova.tts;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaInterface;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.speech.tts.UtteranceProgressListener;
import java.util.HashMap;
import java.util.Locale;
/*
Cordova Text-to-Speech Plugin
https://github.com/vilic/cordova-plugin-tts
by VILIC VANE
https://github.com/vilic
MIT License
*/
public class TTS extends CordovaPlugin implements OnInitListener {
public static final String ERR_INVALID_OPTIONS = "ERR_INVALID_OPTIONS";
public static final String ERR_NOT_INITIALIZED = "ERR_NOT_INITIALIZED";
public static final String ERR_ERROR_INITIALIZING = "ERR_ERROR_INITIALIZING";
public static final String ERR_UNKNOWN = "ERR_UNKNOWN";
boolean ttsInitialized = false;
TextToSpeech tts = null;
@Override
public void initialize(CordovaInterface cordova, final CordovaWebView webView) {
tts = new TextToSpeech(cordova.getActivity().getApplicationContext(), this);
tts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
@Override
public void onStart(String s) {
// do nothing
}
@Override
public void onDone(String callbackId) {
if (!callbackId.equals("")) {
CallbackContext context = new CallbackContext(callbackId, webView);
context.success();
}
}
@Override
public void onError(String callbackId) {
if (!callbackId.equals("")) {
CallbackContext context = new CallbackContext(callbackId, webView);
context.error(ERR_UNKNOWN);
}
}
});
}
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext)
throws JSONException {
if (action.equals("speak")) {
speak(args, callbackContext);
} else {
return false;
}
return true;
}
@Override
public void onInit(int status) {
if (status != TextToSpeech.SUCCESS) {
tts = null;
} else {
// warm up the tts engine with an empty string
HashMap<String, String> ttsParams = new HashMap<String, String>();
ttsParams.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "");
tts.setLanguage(new Locale("en", "US"));
tts.speak("", TextToSpeech.QUEUE_FLUSH, ttsParams);
ttsInitialized = true;
}
}
private void speak(JSONArray args, CallbackContext callbackContext)
throws JSONException, NullPointerException {
JSONObject params = args.getJSONObject(0);
if (params == null) {
callbackContext.error(ERR_INVALID_OPTIONS);
return;
}
String text;
String locale;
double rate;
if (params.isNull("text")) {
callbackContext.error(ERR_INVALID_OPTIONS);
return;
} else {
text = params.getString("text");
}
if (params.isNull("locale")) {
locale = "en-US";
} else {
locale = params.getString("locale");
}
if (params.isNull("rate")) {
rate = 1.0;
} else {
rate = params.getDouble("rate");
}
if (tts == null) {
callbackContext.error(ERR_ERROR_INITIALIZING);
return;
}
if (!ttsInitialized) {
callbackContext.error(ERR_NOT_INITIALIZED);
return;
}
HashMap<String, String> ttsParams = new HashMap<String, String>();
ttsParams.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, callbackContext.getCallbackId());
String[] localeArgs = locale.split("-");
tts.setLanguage(new Locale(localeArgs[0], localeArgs[1]));
tts.setSpeechRate((float) rate);
tts.speak(text, TextToSpeech.QUEUE_FLUSH, ttsParams);
}
}
@@ -0,0 +1,21 @@
/*
Cordova Text-to-Speech Plugin
https://github.com/vilic/cordova-plugin-tts
by VILIC VANE
https://github.com/vilic
MIT License
*/
#import <Cordova/CDV.h>
#import <AVFoundation/AVFoundation.h>
@interface CDVTTS : CDVPlugin <AVSpeechSynthesizerDelegate> {
AVSpeechSynthesizer* synthesizer;
NSString* lastCallbackId;
NSString* callbackId;
}
- (void)speak:(CDVInvokedUrlCommand*)command;
@end
@@ -0,0 +1,72 @@
/*
Cordova Text-to-Speech Plugin
https://github.com/vilic/cordova-plugin-tts
by VILIC VANE
https://github.com/vilic
MIT License
*/
#import <Cordova/CDV.h>
#import "CDVTTS.h"
@implementation CDVTTS
- (void)pluginInitialize {
synthesizer = [AVSpeechSynthesizer new];
synthesizer.delegate = self;
}
- (void)speechSynthesizer:(AVSpeechSynthesizer*)synthesizer didFinishSpeechUtterance:(AVSpeechUtterance*)utterance {
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
if (lastCallbackId) {
[self.commandDelegate sendPluginResult:result callbackId:lastCallbackId];
lastCallbackId = nil;
} else {
[self.commandDelegate sendPluginResult:result callbackId:callbackId];
callbackId = nil;
}
[[AVAudioSession sharedInstance] setActive:NO withOptions:0 error:nil];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryAmbient
withOptions: 0 error: nil];
[[AVAudioSession sharedInstance] setActive:YES withOptions: 0 error:nil];
}
- (void)speak:(CDVInvokedUrlCommand*)command {
[[AVAudioSession sharedInstance] setActive:NO withOptions:0 error:nil];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback
withOptions:AVAudioSessionCategoryOptionDuckOthers error:nil];
if (callbackId) {
lastCallbackId = callbackId;
}
callbackId = command.callbackId;
[synthesizer stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];
NSDictionary* options = [command.arguments objectAtIndex:0];
NSString* text = [options objectForKey:@"text"];
NSString* locale = [options objectForKey:@"locale"];
double rate = [[options objectForKey:@"rate"] doubleValue];
if (!locale || (id)locale == [NSNull null]) {
locale = @"en-US";
}
if (!rate) {
rate = 1.0;
}
AVSpeechUtterance* utterance = [[AVSpeechUtterance new] initWithString:text];
utterance.voice = [AVSpeechSynthesisVoice voiceWithLanguage:locale];
// Rate expression adjusted manually for a closer match to other platform.
utterance.rate = (AVSpeechUtteranceMinimumSpeechRate * 1.5 + AVSpeechUtteranceDefaultSpeechRate) / 2.5 * rate * rate;
utterance.pitchMultiplier = 1.2;
[synthesizer speakUtterance:utterance];
}
@end
+78
View File
@@ -0,0 +1,78 @@
/*
Cordova Text-to-Speech Plugin
https://github.com/vilic/cordova-plugin-tts
by VILIC VANE
https://github.com/vilic
MIT License
*/
using System;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Threading.Tasks;
using Windows.Phone.Speech.Synthesis;
using WPCordovaClassLib.Cordova;
using WPCordovaClassLib.Cordova.Commands;
using WPCordovaClassLib.Cordova.JSON;
namespace Cordova.Extension.Commands {
[DataContract]
class Options {
[DataMember]
public string text;
[DataMember]
public string locale;
[DataMember]
public double? rate;
}
class TTS : BaseCommand {
SpeechSynthesizer synth = new SpeechSynthesizer();
string lastCallbackId;
public async void speak(string argsJSON) {
if (lastCallbackId != null) {
DispatchCommandResult(new PluginResult(PluginResult.Status.OK), lastCallbackId);
lastCallbackId = null;
synth.CancelAll();
}
var args = JsonHelper.Deserialize<string[]>(argsJSON);
var options = JsonHelper.Deserialize<Options>(args[0]);
lastCallbackId = args[1];
var locale = options.locale != null ? options.locale : "en-US";
var rate = options.rate != null ? options.rate : 1.0;
var ssml =
@"<?xml version=""1.0""?>
<speak version=""1.0""
xmlns=""http://www.w3.org/2001/10/synthesis""
xml:lang=""" + locale + @""">
<prosody pitch=""x-high"" rate=""" + rate + @""">" + xmlEncode(options.text) + @"</prosody>
</speak>";
try {
await synth.SpeakSsmlAsync(ssml);
lastCallbackId = null;
DispatchCommandResult(new PluginResult(PluginResult.Status.OK));
} catch (OperationCanceledException) {
// do nothing
} catch (Exception e) {
Debug.WriteLine(e.Message);
lastCallbackId = null;
DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message));
}
}
string xmlEncode(string text) {
return text
.Replace("&", "&amp;")
.Replace("<", "&lt;")
.Replace(">", "&gt;");
}
}
}
+28
View File
@@ -0,0 +1,28 @@
/*
Cordova Text-to-Speech Plugin
https://github.com/vilic/cordova-plugin-tts
by VILIC VANE
https://github.com/vilic
MIT License
*/
exports.speak = function (text, onfulfilled, onrejected) {
var options = {};
if (typeof text == 'string') {
options.text = text;
} else {
options = text;
}
cordova
.exec(function () {
onfulfilled();
}, function (reason) {
onrejected(reason);
}, 'TTS', 'speak', [options]);
};