Add voice guidance
Voice guidance in the Maps SDK for TypeScript allows you to enhance navigation experiences with spoken instructions. This guide covers how to integrate custom playback using the onTextToSpeechInstruction callback with the browser's built-in Text-to-Speech capabilities.
The Maps SDK for TypeScript provides instruction playback through:
- External integration - delivery of TTS strings for use with the browser's
window.speechSynthesisAPI or other third-party solutions.
In the browser environment, the Maps SDK delivers text instructions through callbacks. You can use the browser's built-in window.speechSynthesis API to convert these text instructions into speech, as demonstrated in the examples below.
Basic Voice Guidance
To enable voice guidance in a browser application, you need to:
- Get TTS instruction strings from the SDK via the
onTextToSpeechInstructioncallback - Use the browser's
speechSynthesisAPI to speak the instructions
Here's a complete example of setting up voice guidance:
import { NavigationService, NavigationInstruction, Route, GemError, AlarmService, AlarmListener } from '@magiclane/maps-sdk';
// TTS engine using browser's speechSynthesis
class TTSEngine {
private synth: SpeechSynthesis;
private utter: SpeechSynthesisUtterance | null = null;
constructor() {
this.synth = window.speechSynthesis;
}
speakText(text: string) {
if (this.synth.speaking) {
this.synth.cancel();
}
this.utter = new SpeechSynthesisUtterance(text);
this.utter.rate = 0.75;
this.utter.pitch = 1.0;
this.utter.volume = 0.8;
this.synth.speak(this.utter);
}
stop() {
if (this.synth.speaking) {
this.synth.cancel();
}
}
}
// Create TTS engine instance
const ttsEngine = new TTSEngine();
// Start simulation with voice guidance
const navigationHandler = NavigationService.startSimulation(
route,
undefined,
{
onNavigationInstruction: (instruction: NavigationInstruction) => {
// Handle navigation instruction updates
},
onTextToSpeechInstruction: (textInstruction: string) => {
// Speak the instruction using browser's TTS
ttsEngine.speakText(textInstruction);
},
onDestinationReached: (landmark: any) => {
// Handle destination reached
},
onError: (error: GemError) => {
// Handle errors
}
}
);
You can customize the voice characteristics by modifying the SpeechSynthesisUtterance properties:
rate: Speed of speech (0.1 to 10, default 1)pitch: Voice pitch (0 to 2, default 1)volume: Volume level (0 to 1, default 1)lang: Language code (e.g., 'en-US', 'de-DE')voice: Select from available voices viawindow.speechSynthesis.getVoices()
Voice Language and Browser TTS
When using the browser's speechSynthesis API, you can control the language and voice selection:
// Get available voices
const voices = window.speechSynthesis.getVoices();
// Create TTS engine with custom language
class TTSEngine {
private synth: SpeechSynthesis;
private selectedVoice: SpeechSynthesisVoice | null = null;
constructor(languageCode?: string) {
this.synth = window.speechSynthesis;
if (languageCode) {
// Find voice matching the language code
const voices = this.synth.getVoices();
this.selectedVoice = voices.find(v => v.lang.startsWith(languageCode)) || null;
}
}
speakText(text: string) {
if (this.synth.speaking) {
this.synth.cancel();
}
const utterance = new SpeechSynthesisUtterance(text);
utterance.rate = 0.75;
utterance.pitch = 1.0;
utterance.volume = 0.8;
if (this.selectedVoice) {
utterance.voice = this.selectedVoice;
utterance.lang = this.selectedVoice.lang;
}
this.synth.speak(utterance);
}
}
// Create TTS engine for German
const germanTTS = new TTSEngine('de');
To change the language of the instructions provided through the onTextToSpeechInstruction callback, you can use SdkSettings.setTTSVoiceByLanguage to set the SDK's instruction language. The text will be generated in that language, and then you can use the browser's TTS with a matching voice.
Using Voice Guidance with Speed Alarms
You can combine voice guidance with alarm notifications for a more comprehensive navigation experience:
import { AlarmService, AlarmListener, NavigationService } from '@magiclane/maps-sdk';
const ttsEngine = new TTSEngine();
let alarmListener: any = null;
let alarmService: any = null;
// Create alarm listener for speed limit warnings
alarmListener = AlarmListener.create({
onSpeedLimit: async (speed: number, limit: number, insideCityArea: boolean) => {
const speedLimitConverted = Math.round(limit * 3.6); // Convert m/s to km/h
const speedWarning = `Current speed limit: ${speedLimitConverted}`;
ttsEngine.speakText(speedWarning);
}
});
// Create alarm service
alarmService = AlarmService.create(alarmListener);
// Start navigation with TTS instructions
const navigationHandler = NavigationService.startSimulation(
route,
undefined,
{
onNavigationInstruction: (instruction: NavigationInstruction) => {
// Handle navigation updates
},
onTextToSpeechInstruction: (textInstruction: string) => {
ttsEngine.speakText(textInstruction);
},
onDestinationReached: (landmark: any) => {
// Clean up
alarmService = null;
},
onError: (error: GemError) => {
// Handle error
}
}
);
Changing SDK Language for Instructions
To change the language of text instructions provided by the SDK:
import { SdkSettings, Language, GemError } from '@magiclane/maps-sdk';
// Get the desired language
const lang: Language | null = SdkSettings.getBestLanguageMatch("de", { regionCode: "DEU" });
if (lang) {
// Set the SDK to use German for instructions
const error: GemError = SdkSettings.setTTSVoiceByLanguage(lang);
if (error === GemError.success) {
console.log("Instruction language set to German");
// Now create a matching German TTS voice
const germanTTS = new TTSEngine('de-DE');
}
}
The SDK language (SdkSettings.language) controls UI text, while the TTS language controls spoken instructions. You can set them independently based on your needs.
Available Browser Voices
You can list and select from available voices in the browser:
// Wait for voices to load
window.speechSynthesis.onvoiceschanged = () => {
const voices = window.speechSynthesis.getVoices();
console.log('Available voices:');
voices.forEach((voice, index) => {
console.log(`${index}: ${voice.name} (${voice.lang})`);
});
// Filter for English voices
const englishVoices = voices.filter(v => v.lang.startsWith('en'));
console.log('English voices:', englishVoices.map(v => v.name));
};
The SoundPlayingService class and its features (built-in voice playback, human voices, voice management) are not available in the browser environment. Voice guidance in browsers must be implemented using the onTextToSpeechInstruction callback with window.speechSynthesis or other web-based TTS solutions.