Apps script and Google Text to Speech API

1,708 views
Skip to first unread message

Vo Tu Duc

unread,
Jun 27, 2019, 5:02:03 AM6/27/19
to Google Apps Script Community
I'm trying to use Google Apps script in order to generate/create a audio file. 

There isn't a guide document for this on Google Text-to-Speech API guide page.

Below are my code: 


function textToSpeech() {

var body = {
       'input':{
    'text':'I\'ve added the event to your calendar. helo world. my name is Duc. I am form viet nam'
  },
  'voice':{
    'languageCode':'en-US',
    'name':'en-US-Wavenet-D',
    'ssmlGender':'FEMALE'
    
  },
  'audioConfig':{
    'audioEncoding':'MP3', //LINEAR16
    "pitch": 0,
    "speakingRate": 1
  }
   };
var payload = JSON.stringify(body);
var options = { 
                                     "method" : "POST",
                                     "muteHttpExceptions": true,
                                     "contentType": "application/json; charset=utf-8",
                                     "payload" : payload,
                                     "headers": {Authorization: 'Bearer ' + goa.getToken() }
   
                                    };

 var response = UrlFetchApp.fetch ( endPoint, options  );
 var datajson = JSON.parse(response); // based64 audio


Could anyone can help me to understand how to create a audio file?

Thank you for your time to read this topic and I'm appology for my english.

Best,


Martin Hawksey

unread,
Jun 27, 2019, 5:39:48 AM6/27/19
to Google Apps Script Community
I've not done anything explicitly with the Google Text-to-Speech API but have saved .mp3 data in Apps Script in this post https://mashe.hawksey.info/2018/03/recording-mp3-audio-in-google-add-ons-google-apps-script-to-google-drive/

The bit you might be most interested in is the server side code:

// handles saving the audio file to drive
function invokeSave(dataURI, filename){
 var blob = dataURItoBlob(dataURI, filename);
 var file = DriveApp.createFile(blob);
 return file.getUrl();
}
function dataURItoBlob(dataURI, filename) {
 // convert base64/URLEncoded data component to raw binary data held in a string
 var byteString;
 if (dataURI.split(',')[0].indexOf('base64') >= 0){
   byteString = Utilities.base64Decode(dataURI.split(',')[1]);
 } else {
   byteString = decodeURI(dataURI.split(',')[1]);
 }
 // separate out the mime component
 var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
 return Utilities.newBlob(byteString, mimeString, filename);
}

 In your code it might work by calling:

invokeSave(datajson, 'YOUR FILE NAME');

but it might need tweaking depending on the returned datajson

Vo Tu Duc

unread,
Jun 27, 2019, 5:53:18 AM6/27/19
to google-apps-sc...@googlegroups.com

Hi Martin Hawksey,


Really. Are you here! I'm a fan of your blog/website :) . I've learn a lot of thing from you. Thank you for all.

Regard to the solution, let me try it. I will come back with topic very soon.

Have a nice day to you.

Best,
Đức



 



Duc2.png

     VÕ TỰ ĐỨC

title.png

CEO

email.png

sa...@vansango.co

phone.png

088.888.3458

web.png

www.vansango.co

Facebook.png

facebook.com/vansango.co


shop.png

Sàn gỗ Tự nhiên | Sàn gỗ Ngoài trời | Sàn gỗ Công nghiệp | Cầu Thang | Nội thất Thú Cưng



--
You received this message because you are subscribed to the Google Groups "Google Apps Script Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-apps-script-c...@googlegroups.com.
Visit this group at https://groups.google.com/group/google-apps-script-community.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-apps-script-community/02cfa9e0-f0fd-48ff-ab17-f47d90f247f3%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Martin Hawksey

unread,
Jun 27, 2019, 6:28:33 AM6/27/19
to Google Apps Script Community
This is the only place to be :)

If you get stuck if you drop the raw response somewhere I can access I might be able to see if any tweaking is required to the code
To unsubscribe from this group and stop receiving emails from it, send an email to google-apps-script-community+unsub...@googlegroups.com.

Vo Tu Duc

unread,
Jun 27, 2019, 6:41:43 AM6/27/19
to google-apps-sc...@googlegroups.com

Hi Martin Hawksey,


The attached file is the raw response. 

var response = UrlFetchApp.fetch ( endPoint, options  );
var datajson = JSON.parse(response); // based64 audio


I've tried to add some line of code below. The new file is created. But it was not a audio file. 

Honestly, I don't know what next should I do...just trying to read the code you have mentioned...

var folderID = "XXXXYYYY"; /// my folder ID on Google Drive.
var driveFolder = DriveApp.getFolderById(folderID);
var filename = "name_of_newfile";
var filecontent = {
mimeType
: 'application/json; charset=utf-8',
content
: datajson, //datajson
};
 

var file = driveFolder.createFile(filename, datajson);


Could you please take a look and give me an advise?

Thank you for allllll.

Best,

Đức
58.txt

Martin Hawksey

unread,
Jun 27, 2019, 7:23:33 AM6/27/19
to Google Apps Script Community
Hi Đức,

actually the response is a lot easier to save to Drive than I thought. If the 58.txt file is datajson then you can do: 

  var folderID = "XXXXYYYY"; /// my folder ID on Google Drive.
  var driveFolder = DriveApp.getFolderById(folderID);
    var filename = "name_of_newfile";

  var byteString = Utilities.base64Decode(datajson);
  var blob = Utilities.newBlob(byteString, "audio/mp3", filename );
  var file = driveFolder.createFile(blob);

Vo Tu Duc

unread,
Jun 27, 2019, 9:10:21 AM6/27/19
to Google Apps Script Community
Hi Martin Hawksey, 

Yeah, it's work. 

Thank you so much for your time and advice.

Best,
Đức

Vo Tu Duc

unread,
Jun 28, 2019, 6:35:18 AM6/28/19
to Google Apps Script Community
Hi Martin Hawksey, 

Is it possbile to create a video file and save it to G Drive like a way we've created a MP3 file?

Best,
Đức

On Thursday, June 27, 2019 at 6:23:33 PM UTC+7, Martin Hawksey wrote:

Martin Hawksey

unread,
Jul 2, 2019, 10:52:50 PM7/2/19
to google-apps-sc...@googlegroups.com
Not personally done anything with video files but know it's possible to do stuff in the browser to generate them (example WebRTC experiment). The challenge I'd anticipate is handling the file sizes these generate and adding them to Google Drive. A challenge but not impossible and if it was me I'd be looking at resumable uploads which members of the community have documented in particular Tanaike's Resumable Upload for Web Apps using Google Apps Script

Kak Dheny

unread,
Aug 10, 2023, 7:59:45 AM8/10/23
to Google Apps Script Community
can you tell me about change text to voice with google script?
thankyou

Bruce Mcpherson

unread,
Aug 10, 2023, 10:21:54 AM8/10/23
to google-apps-sc...@googlegroups.com
You can use my bmApiCentral library. - I haven't got round to writing an article on this class yet, but there's an example below.  

There are lots of setup options - see code for whatthey are
 
If you want to use goa, then just make goa.getToken the tokenService.

You'll need to enable the drv and texttospeech apis and set the drive and cloudplatform scopes. I'll be writing up an article shortly with detail on all this.

function testSpeech () {
Exports.Deps.init({
tokenService: ScriptApp.getOAuthToken,
fetch: UrlFetchApp.fetch
})
// get the apiKey
const apiKey = PropertiesService.getScriptProperties().getProperty("apiKey")

// get a speech instance
const speech = Exports.newSpeech({
apiKey,
noisy: true
})

// get the result as an mp3 blob
const {mp3} = speech.synthesize ({text:'hello'})

// set the name to whatever
mp3.setName ('hellosppeechfile.mp3')

// get a drv instance
const drv = Exports.newDrv ({
apiKey
})

// get a folder to write it to by its path
const folder = drv.getFolder({ path: 'my audio conversions', createIfMissing: true })

// upload the mp3 to drive
const upload = drv.upload ({ blob: mp3, parentId: folder.id })


}

You'll need an exports.gs with this stuff in it

var Exports = {

get libExports() {
return bmApiCentral.Exports
},


get Deps() {
return this.libExports.Deps
},


/**
* synth instance with validation
* @param {...*} args
* @return {Speech} a proxied instance of Fact with property checking enabled
*/
newSpeech(...args) {
return this.libExports.newSpeech(...args)
},



/**
* Drv instance with validation
* @param {...*} args
* @return {Drv} a proxied instance of Drv with property checking enabled
*/
newDrv(...args) {
return this.libExports.newDrv(...args)
}


}






--
You received this message because you are subscribed to the Google Groups "Google Apps Script Community" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-apps-script-c...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-apps-script-community/ba62b0d6-c0b3-462e-8071-11672ae4ae6bn%40googlegroups.com.

Kak Dheny

unread,
Aug 12, 2023, 9:37:59 AM8/12/23
to Google Apps Script Community

Thank you very much Bruce Mcpherson
I really wait for your article

I will try that script..  if I find an error, how can I contact you?

Bruce Mcpherson

unread,
Aug 12, 2023, 4:02:20 PM8/12/23
to google-apps-sc...@googlegroups.com

Kak Dheny

unread,
Aug 12, 2023, 6:37:43 PM8/12/23
to Google Apps Script Community
I'm sorry, I have tried and I found an error..  What should I do? Thankyou..

Error: { "error": { "code": 403, "message": "Request had insufficient authentication scopes.", "status": "PERMISSION_DENIED", "details": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "ACCESS_TOKEN_SCOPE_INSUFFICIENT", "metadata": { "service": "texttospeech.googleapis.com", "method": "google.cloud.texttospeech.v1.TextToSpeech.SynthesizeSpeech" } } ] } }
api/Fetch.gs:225
api/Speech.gs:183
api/Speech.gs:107
Kode.gs:17

Bruce Mcpherson

unread,
Aug 12, 2023, 7:04:50 PM8/12/23
to google-apps-sc...@googlegroups.com
Which scopes have you enabled?

Kak Dheny

unread,
Aug 12, 2023, 9:14:39 PM8/12/23
to Google Apps Script Community
I try  use your bmApiCentral library, then I run this script:

function testSpeech () {
Exports.Deps.init({
tokenService: ScriptApp.getOAuthToken,
fetch: UrlFetchApp.fetch
})
// get the apiKey
const apiKey = PropertiesService.getScriptProperties().getProperty("apiKey")

// get a speech instance
const speech = Exports.newSpeech({
apiKey,
noisy: true
})

// get the result as an mp3 blob
const {mp3} = speech.synthesize ({text:'hello'})

// set the name to whatever
mp3.setName ('hellosppeechfile.mp3')

// get a drv instance
const drv = Exports.newDrv ({
apiKey
})

// get a folder to write it to by its path
const folder = drv.getFolder({ path: 'my audio conversions', createIfMissing: true })

// upload the mp3 to drive
const upload = drv.upload ({ blob: mp3, parentId: folder.id })


}

// You'll need an exports.gs with this stuff in it

Bruce Mcpherson

unread,
Aug 13, 2023, 3:17:04 AM8/13/23
to google-apps-sc...@googlegroups.com
In your appsscript.json manifest file, which scopes did you set, and did you go through an authorization dialog?

Kak Dheny

unread,
Aug 13, 2023, 4:11:12 AM8/13/23
to Google Apps Script Community
appsscript.json.png
This is my appsscript.json
Yes, I go through an authorization dialog

Bruce Mcpherson

unread,
Aug 13, 2023, 6:43:53 AM8/13/23
to google-apps-sc...@googlegroups.com
Okay you don't have any oauth scopes in there - you need these (or if you use goa you'll need them set in your goa defiinition)


Mohd Yasser Arafat

unread,
Feb 2, 2024, 9:55:18 AMFeb 2
to Google Apps Script Community
can i try the script sir ? thx before

Bruce Mcpherson

unread,
Feb 2, 2024, 1:24:34 PMFeb 2
to google-apps-sc...@googlegroups.com
What does your manifest finger look like now? Have you added the correct scopes?
Reply all
Reply to author
Forward
0 new messages