Change voice in Action - actions-on-google

How do I change the voice during my response in "Actions on Google"? Is there an SSML code to temporarily change the voice, for example, from male to female, while reading a quotation?

You actually can change the voice bye adding a voice tag inside the speak tag. You can try something like this:
<speak><voice gender="female">Hello I'm Mary</voice><break time="2s"/><voice gender="male">Hey I'm John</voice><speak>

You can't change the voice at the moment, however you can use Speech Synthesis Markup Language (SSML), to have more customizable (=audio) response.
For more on how to use SSML with Action On Google: https://medium.com/google-developers/ssml-for-actions-on-google-946117f97fd1
I hope it helps.

Best Solution for that.
const request = {
// The text to synthesize
input: {
ssml:`<speak version="1.1" xmlns="http://www.w3.org/2001/10/synthesis"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/2001/10/synthesis
http://www.w3.org/TR/speech-synthesis11/synthesis.xsd"
xml:lang="en-US">
<voice gender="female" languages="en-US" required="languages gender variant">It Maria and this is my female voice,</voice>
<!-- processor-specific voice selection -->
<voice name="Mike" required="name">Its Mike and its my male voice</voice>
</speak>`
},
// The language code and SSML Voice Gender
voice: { languageCode: 'en-US', ssmlGender: 'NEUTRAL' },
// The audio encoding type
audioConfig: { audioEncoding: 'MP3' },
};
That's work for me like a charm

Related

Different voices in Text to Speech iOS app

I have a Text to Speech App and all is good, but I was looking for a voice.
In Settings/Accessibility/Voice Over/Speech/Voice there is a list of voices. I wanted to select one of those, for example "Susan (Enhanced)". How would I go about doing that?
I am new to Text to Speech and AVSpeechSynthesizer so I was hoping for some advice how to select that voice?
When I try it in General/Settings it sounds good, but when I select, what I thought was that voice it in my App, it sounds different. This happens with all of the voices I tried.
Here is the code I used to speak the text:
for voice in AVSpeechSynthesisVoice.speechVoices()
{
print("\(voice.name)")
if voice.name == "Susan (Enhanced)" {
self.voiceToUse = voice
}
}
let textToSpeak = self.tvTextToSpeak.text
if (!textToSpeak!.isEmpty)
{
let speechSynthesizer = AVSpeechSynthesizer()
let speechUtterance: AVSpeechUtterance = AVSpeechUtterance(string: textToSpeak!)
speechUtterance.voice = self.voiceToUse
speechSynthesizer.speak(speechUtterance)
}
So if I use the same text as the example in the iOS settings it sounds different in my App, why?
Is it something I need to do?
Are those voices special?
Does it have to do with the utterance, I have not set that.
Thanks for any clarification.

Bug at merging Simple Responses from multiple webhook requests

When calling the webhook multiple times in one scene and sending simple responses there is a bug at merging the simple responses.
prompt from the first webhook call
{
"override": false,
"firstSimple": {
"speech": "<speak><audio src=\"https://www.example.com/audio/file1.mp3\"></speak>",
"text": "Text 1"
}
}
prompt from the second webhook call
{
"override": false,
"firstSimple": {
"speech": "<speak><audio src=\"https://www.example.com/audio/file2.mp3\"></audio> <audio src=\"https://www.example.com/audio/file3.mp3\"></audio></speak>",
"text": " Text 2"
}
}
merged prompt in the response send to the user
{
"firstSimple": {
"speech": "<speak><speak><audio src=\"https://www.example.com/audio/file1.mp3\"></speak> <audio src=\"https://www.example.com/audio/file2.mp3\"/> <audio src=\"https://www.example.com/audio/file3.mp3\"/></speak>",
"text": "Text 1 Text2"
}
}
So with the two speak tags the SSML is invalide and is not spoken out.
Sometimes the speech object is completely missing.
I already created an Github issue for that.
So found out that the merging Bug is related to invalid SSML. Unfortunately there is no error message from Google for SSML errors.
And as a workaround for the problem that the speech object is completely missing I changed conv.add(new Simple('Text')) to conv.prompt.firstSimple = new Simple('Text') or conv.prompt.lastSimple = new Simple('Text').

Flutter open whatsapp with text message

I want to open whatsapp from my Flutter application and send a specific text string. I'll select who I send it to when I'm in whatsapp.
After making some research I came up with this:
_launchWhatsapp() async {
const url = "https://wa.me/?text=Hey buddy, try this super cool new app!";
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
Which works ok ish, however there are two problems:
As soon as I make the text string into multi words it fails. So if I change it to:
_launchWhatsapp() async {
const url = "https://wa.me/?text=Hey buddy, try this super cool new app!";
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
Then the Could not launch $url is thrown.
I have whatsapp already installed on my phone, but it doesn't go directly to the app, instead it gives me a webpage first and the option to open the app.
Here is the webpage that I see:
Any help on resolving either of these issues would be greatly appreciated.
Thanks
Carson
P.s. I'm using the Url_launcher package to do this.
From the official Whatsapp FAQ, you can see that using "Universal links are the preferred method of linking to a WhatsApp account".
So in your code, the url string should be:
const url = "https://wa.me/?text=YourTextHere";
If the user has Whatsapp installed in his phone, this link will open it directly. That should solve the problem of opening a webpage first.
For the problem of not being able to send multi-word messages, that's because you need to encode your message as a URL. Thats stated in the documentation aswell:
URL-encodedtext is the URL-encoded pre-filled message.
So, in order to url-encode your message in Dart, you can do it as follows:
const url = "https://wa.me/?text=Your Message here";
var encoded = Uri.encodeFull(url);
As seen in the Dart Language tour.
Please note that in your example-code you have put an extra set of single quotes around the text-message, which you shouldn't.
Edit:
Another option also presented in the Whatsapp FAQ is to directly use the Whatsapp Scheme. If you want to try that, you can use the following url:
const url = "whatsapp://send?text=Hello World!"
Please also note that if you are testing in iOS9 or greater, the Apple Documentation states:
Important
If your app is linked on or after iOS 9.0, you must declare the URL schemes you pass to this method by adding the LSApplicationQueriesSchemes key to your app's Info.plist file. This method always returns false for undeclared schemes, whether or not an appropriate app is installed. To learn more about the key, see LSApplicationQueriesSchemes.
So you need to add the following keys to your info.plist, in case you are using the custom whatsapp scheme:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>whatsapp</string>
</array>
till date: 27-06-2022
using package: https://pub.dev/packages/url_launcher
dependencies - url_launcher: ^6.1.2
TextButton(
onPressed: () {
_launchWhatsapp();
},
)
_launchWhatsapp() async {
var whatsapp = "+91XXXXXXXXXX";
var whatsappAndroid =Uri.parse("whatsapp://send?phone=$whatsapp&text=hello");
if (await canLaunchUrl(whatsappAndroid)) {
await launchUrl(whatsappAndroid);
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text("WhatsApp is not installed on the device"),
),
);
}
}
Here is new update way...
whatsapp() async{
var contact = "+880123232333";
var androidUrl = "whatsapp://send?phone=$contact&text=Hi, I need some help";
var iosUrl = "https://wa.me/$contact?text=${Uri.parse('Hi, I need some help')}";
try{
if(Platform.isIOS){
await launchUrl(Uri.parse(iosUrl));
}
else{
await launchUrl(Uri.parse(androidUrl));
}
} on Exception{
EasyLoading.showError('WhatsApp is not installed.');
}
}
and call whatsapp function in onpress or ontap function
For using the wa.me domain, make sure to use this format...
https://wa.me/123?text=Your Message here
This will send to the phone number 123. Otherwise, you will get an error message (see? https://wa.me/?text=YourMessageHere ). Or, if you don't want to include the phone number, try this...
https://api.whatsapp.com/send?text=Hello there!
Remember, wa.me requires a phone number, whereas api.whatsapp.com does not. Hope this helps!
I know it is too late for answering this, but for those who want the same functionality, the current way is to do it like this:
launchUrl(Uri.parse('https://wa.me/$countryCode$contactNo?text=Hi'),
mode: LaunchMode.externalApplication);
if you will use URL Launcher then the whatsapp link will be open on web browser. So you need to set parameter - not to open on safari browser. The complete code you can find on this flutter tutorial.
But for your case use below code.
await launch(whatappURL, forceSafariVC: false);
Today i am adding solution its working fine on my desktop and phone
Add 91 if your country code is +91
Remember not add any http or https prefix otherwise wont work.
whatsapp://send?phone=9112345678&text=Hello%20World!

Asking for Confirmation overriding previous responses in Google Actions

The Problem
I have a Google Actions SDK project and I am using the nodejs client library for building fulfillment. I am facing some problem trying to use the Confirmation Helper intent. It is overriding previous responses given before it. Let me give you a simplified example of the problem:
First, Action says, "Hi, hope you are having a great day"
Then, Action asks for a Confirmation, "Do you want today's weather report?"
But in the simulator, all I hear is the second question. I am targeting a Voice Only situation, so I really need all the responses. Interestingly, I can see all the responses in the AUDIO tab of simulator. How can I hear both of these phrases?
I am copy/pasting the response JSON as shown in the RESPONSE tab.
{
"expectUserResponse": true,
"expectedInputs": [
{
"possibleIntents": [
{
"intent": "actions.intent.CONFIRMATION",
"inputValueData": {
"#type": "type.googleapis.com/google.actions.v2.ConfirmationValueSpec",
"dialogSpec": {
"requestConfirmationText": "Do you want today's weather report?"
}
}
}
],
"inputPrompt": {
"richInitialPrompt": {
"items": [
{
"simpleResponse": {
"textToSpeech": "Hope you are doing well!"
}
}
]
}
}
}
],
"conversationToken": ""
}
How can I fix this situation. Thanks!
This is intentional behavior as using one of the intents like Confirmation will be the only response, and other responses will be ignored.
There are two potential ways to get around this.
Combine all of your responses to be in the Confirmation
Create your own Yes/No intent and use simple responses for everything.

SoundManager 2 and iPhone

The following code works in my desktop browser but not in Safari on my iPhone, it does display the alert() but doensn't play the audio. What am I doing wrong?
soundManager.url = '/assets/backend/swf/';
soundManager.preferFlash = false;
soundManager.useHTML5Audio = true;
soundManager.onready(function(){
function playSong(){
soundManager.createSound({
id: 'song_<?=$song->ID?>',
url: '/backend/song/play/<?=$song->ID?>',
type: 'audio/mp3'
}).play();
}
$('#play').click(function(){
alert('playSong()');
playSong();
});
});
From what I've seen, iPhone doesn't like "auto-played" sounds, and they require the sound to be played from user interaction.
In your case, the iOS browser must not like the fact that you're creating the sound AND THEN playing it back immediately.
Give this variant a try and see if it works for you:
soundManager.url = '/assets/backend/swf/';
soundManager.preferFlash = false;
soundManager.useHTML5Audio = true;
soundManager.onready(function(){
// Create the sounds here (don't call play)
soundManager.createSound({
id: 'song_<?=$song->ID?>', // It is not cool to put PHP here, read below!
url: '/backend/song/play/<?=$song->ID?>',
type: 'audio/mp3'
});
$('#play').click(function(){
var soundId = 'song_<?= $song->ID ?>';
soundManager.play(soundId);
});
});
As a side note: I'd advise you AGAINST mixing JS and PHP in that way. Check this SoundManager2 example on how to "augment" a regular MP3 link like this:
Click here to play blabla
into something that plays an MP3 onclick:
SoundManager2 documentation
Regards and good luck!