cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - Have a PTC product question you need answered fast? Chances are someone has asked it before. Learn about the community search. X

Voice Selection on HoloLens 2

Aouellets
9-Granite

Voice Selection on HoloLens 2

I'm using the synthesize speech functionality on the HoloLens 2 to read text programatically. 

 

Is there a way to change the voice from the default robotic sounding voice to Cortana or some other voice?

 

Using the code below:

 

function SayText(text) {
$timeout(function(){
$scope.app.speech.synthesizeSpeech( {'text': text });
}, 1500 )
}

5 REPLIES 5

Hi @Aouellets ,

you can use on the HoloLens different languages as e.g. described in :

https://developers.google.com/web/updates/2014/01/Web-apps-that-talk-Introduction-to-the-Speech-Synthesis-API

So for example the following code will work in Studio in a HoloLens 2 project:

$scope.app.my_speak = function (msg_txt)
{
 // if preview mode  
  if(twx.app.isPreview() == true){
   //some time on chrome is the voice code not initilized therefor
//also a snackbarmessage
  twx.app.fn.addSnackbarMessage('msg_txt:'+msg_txt, 'voice-response')
 }  

 //  in Chrome is this sometimes not correct initilized
//msg.voice = voices[2]; // Note: some voices don't support altering params


  //sometimes this will not initilized need to click again 
// issue is only in preview mode -> on HOLOLENS is working fine
 speechSynthesis.getVoices().forEach(function(voice) {
  console.log(voice.name, voice.default ? voice.default :'');   
  var time_delay=2000*idx++; //time delay 2 secs per item
   var msg = new SpeechSynthesisUtterance();
    msg.onend = function(e) {console.log('Finished in ' + e.elapsedTime + ' seconds.');};
  	msg.voice = voice;
	msg.voiceURI = 'native';
	msg.volume = 1; // 0 to 1
	msg.rate = 1; // 0.1 to 10
	msg.pitch = 0.8; //0 to 2
	msg.text = msg_txt;
	msg.lang = 'en-US';
    $timeout( function(my_msg) {
                //set the label tho the current spoken voice name
               $scope.setWidgetProp('3DLabel-1','text','status: '+ my_msg.voice.name );
               $scope.$applyAsync();
               window.speechSynthesis.speak(my_msg);},time_delay,false,msg);              
                          
 });
 //second call  
 var voices = window.speechSynthesis.getVoices()
 var msg1 = new SpeechSynthesisUtterance();
 msg1.voice = voices[2];//Microsoft Zira Desktop - English (United States) 
 msg1.text="another speech test after "+voices.length*2+" seconds"
  
  $timeout(function(my_msg) {
     console.warn(msg1.text);
     $scope.app.speech.synthesizeSpeech(my_msg);
      $scope.setWidgetProp('3DLabel-1','text','status: none');
     $scope.$applyAsync();
                      },voices.length*3000,false,msg1); // interval to delay = number of voices * 3 secs  
}
//function for a click button
$scope.app.button1Click=function()
{
console.warn($scope);
$scope.app.my_speak("You clicked the sunflower button");
}

so when I tested it, it printed the message in all possible voices and also displayed   info about the spoken language name

I attached the demo project where I tested it.

Hi Roland, 

 

Thanks for the help. 

 

I'm attempting a simple implementation in studio, but it seems something about how I'm assigning the voice to the variable isn't allowing studio to build the project.

 

See the code below:

 


speechSynthesis.getVoices().forEach(function(voice) {
console.log(voice.name, voice.default ? voice.default :'');
});

var instruction = new SpeechSynthesisUtterance('Hello, my name is Daniel') ;

instruction.voice = 'Daniel';

 

$scope.Test = function() {

$scope.app.speech.synthesizeSpeech({'text': instruction})


}

Hi @Aouellets ,

looked on your code and I think it could not work . Problem is : voice is an object and could not  be wrapped to a string - I believe it prints such error message into  the chrome console when we try to execute your code. The predefined voices are coming form system and their properties are read only. I think you can only use the voices which are available.  You can   change some attributes like volume, pitch etc.  voice.name and voiceUrl are read only so far I see  in:

https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesisVoice/voiceURI

https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesisVoice/name

https://developer.mozilla.org/en-US/docs/Web/API/SpeechSynthesisVoice

Another points that on the different platforms we have different predefined voices.

For example  there is difference between chrome preview and on the HoloLens2

I think the correct way is to select one of the available voices on your devices 

You can check in a loop all voices and select one.  For example, one voices which could be used is  English UK George.

This voice is not available e.g. in Chrome so there we can take a voice containing the string ' English Male'

The  following code will work on both - HoloLens 2 and chrome calling depending on the env one of the available voice:

$scope.app.TestC = function() {


  var msg_text="this is my message!"
  var languageNameContains='English Male' // this is vor preview mode /chrome
  if(twx.app.isPreview() != true) languageNameContains='George' // for the HL 2 I want to have George as speaker
  
window.speechSynthesis.getVoices().forEach(function(voice) {
  
  if(voice.name.indexOf(languageNameContains)!=-1) { //only this voice will be used
  
 var utterThis = new SpeechSynthesisUtterance(msg_text); // will also set the message text
  utterThis.voice = voice;
  utterThis.onend = function(e) {console.log('Finished in ' + e.elapsedTime + ' seconds.');};
  utterThis.volume = 1; // 0 to 1
  utterThis.rate = 1; // 0.1 to 10
  utterThis.pitch = 0.8; //0 to 2
  utterThis.text = msg_text + " spoken with voice " + voice.name; //another option to set the msg text
 $scope.app.speech.synthesizeSpeech(utterThis);
 
}else return;
  
return;}) // finish voice funciton
  
} //finsi app.TestC()

 

The  mentioned code will work on both - HoloLens 2 and chrome calling depending on the env one of the available voice.

To call this code use the 2 button "app.TestC".  You can call the Flower button to see all availble voices on The HoloLens 2, so you can later choose one voice which you want to use for the messages

2021-03-10_17-37-15.gif

I attached also the test project.

Hello, 

 

Using this implementation, I was able to get the instructions in my own code to work using 'George' / English Male. 

 

However, when I attempt to use say Alice or English female, the voice goes to default. The same happens with David, Susan, etc. 

 

Am I only able to select from voices in the default language of the device?

 

Code Below:

 

 

var instruction = '';

$scope.$on('newStep', function(evt, arg) {
instruction = arg


step = $scope.app.view.Home.wdg['model-1'].currentStep
console.log( 'Current Step Is : ' + step)


$scope.app.view.Home.wdg["3DImage-2"].src="app/resources/Uploaded/" + File_Name + step + ".png" ;

});

 

/*
$scope.SayStep = function () {

$scope.app.speech.synthesizeSpeech({'text': instruction});


}

*/

 

$scope.$on('stepstarted', function () {

/// var msg_text="this is my message!" This is replaced by the 'instruction' var

var languageNameContains='English Female' // this is vor preview mode /chrome

if(twx.app.isPreview() != true) languageNameContains= ' Alice ' // for the HL 2 I want to have Alice as speaker

window.speechSynthesis.getVoices().forEach(function(voice) {

if(voice.name.indexOf(languageNameContains)!=-1) { //only this voice will be used

var utterThis = new SpeechSynthesisUtterance(instruction); // will also set the message text
utterThis.voice = voice;
utterThis.onend = function(e) {console.log('Finished in ' + e.elapsedTime + ' seconds.');};
utterThis.volume = 1; // 0 to 1
utterThis.rate = 1; // 0.1 to 10
utterThis.pitch = 0.8; //0 to 2
// utterThis.text = instruction + " spoken with voice " + voice.name; //another option to set the msg text

$scope.app.speech.synthesizeSpeech(utterThis);

}else return;

return;}) // finish voice funciton

})

So far, I remember the voice list is different for the different devices. Possibly on the different devices(OS platforms) you will get different list of voices. So for example on IOS , HoloLens and chrome we have different voices for specifc devices /target platform -.  Therefore If you could not find a list with the voices supported thre -   you need to test it on particular devices where you can simple get   the list and display the list of voice names , let say first in a list or text widget so you can decide which language you want to use (on HoloLens you can display the list in an Image as dynamic generated SVG some thing as described in  https://community.ptc.com/t5/Vuforia-Studio/Display-SVG-as-3D-Image-on-Hololens/m-p/591168 and https://community.ptc.com/t5/Vuforia-Studio/Is-it-possible-to-create-Proportional-Chart-or-Progress-Gauge-in/m-p/626967#M6714)

Top Tags