06 August 2020

Text To Speech (TTS) and Audio file with NativeScript

In my game - My first game (game for children), that created with NativeScript, I use audio and speak services.


The NativeScript is platform that use to develop an android (or IOS) app with angular and TypeScript.

Here is the class the use for Audio and Speak with NativeScript.

The speak if Text To Speech (TTS) from google.

The audio is mp3 file

import { TNSTextToSpeechSpeakOptions } from "nativescript-texttospeech";
import { TNSPlayerAudioPlayerOptions } from "nativescript-audio-player";
import * as timer from "tns-core-modules/timer";
import { Injectable } from "@angular/core";
import * as firebase from "nativescript-plugin-firebase";
@Injectable({
  providedIn: "root",
})
export class AudioAndSpeak {
  public audioTrackDurationany;
  public remainingDurationany// used to show the remaining time of the audio track
  private TTS = new TNSTextToSpeech();
  private _playerTNSPlayer;
  public isSpeakingboolean = false;
  constructor() {
    this._player = new TNSPlayer();
    this._player.debug = false;
  }
  public async speak(textstringlocal : string) {
    let isSpeaking = true;
    let  speakRate = 0.8;
    let speakOptionsSpeakOptions = {
      text: text,
      speakRate: speakRate,
      queue: true,
      locale : local,
      finishedCallback: async () => {
        isSpeaking = false;
      },
    };
    this.TTS.speak(speakOptions).then(() => console.log("End Speak"));
    return isSpeaking;
  }
  public async playSound(filePathstringfilePath2?: stringvolume? :number) {
    try {
      if(!volume)
      {
        volume = 1;
      }
      this._player.volume = volume;
      this.isSpeaking = true;
      const playerOptionsAudioPlayerOptions = {
        audioFile: filePath,
        loop: false,        
        completeCallback: async () => {
       
          await this._player.dispose();
          this.isSpeaking = false;          
         // player disposed
          if (filePath2) {
            this.playSound(filePath2);
          }
        },
        errorCallback: (errorObject=> {
          console.log('errorCallback')
          console.log(JSON.stringify(errorObject));
          this.isSpeaking = false;
        },
        infoCallback: (args=> {
          console.log(JSON.stringify(args));
        },
      };
      await this._player.playFromFile(playerOptions).catch((error=> {
        firebase.crashlytics.sendCrashLog('AudioAndSpeak -> playSound playFromFile :' + error);
        console.log(error);
        this.isSpeaking = false;
      });
 
      this.audioTrackDuration = await this._player.getAudioTrackDuration();
      // start audio duration tracking
      this._startDurationTracking(this.audioTrackDurationvolume);
    } catch (e) {
      console.error("AudioAndSpeak -> playSound"e);
      firebase.crashlytics.sendCrashLog('AudioAndSpeak -> playSound :' + e);
    }
  }
  private async _startDurationTracking(durationvolume) {
    if (this._player && this._player.isAudioPlaying()) {
      this._player.volume = volume;
      const timerId = timer.setInterval(() => {
        this.remainingDuration = duration - this._player.currentTime;
      }, 500);
    }
  }
}


You need yo add the service on the contractor

import { AudioAndSpeak } from "../../shared/AudioAndSpeak";

 constructor(
    ...
    private audioAndSpeakAudioAndSpeak,
    ...
  ) {...}

to call audio file

 this.audioAndSpeak.playSound(audioFilePath);

to call speak

this.audioAndSpeak.speak'TEXT' , "en-GB" );

Thanks,
Roi Kolbinger