src/azurechat/features/chat/chat-ui/chat-speech/use-text-to-speech.ts (63 lines of code) (raw):
import { useGlobalMessageContext } from "@/features/global-message/global-message-context";
import {
AudioConfig,
ResultReason,
SpeakerAudioDestination,
SpeechConfig,
SpeechSynthesizer,
} from "microsoft-cognitiveservices-speech-sdk";
import { useRef, useState } from "react";
import { GetSpeechToken } from "./speech-service";
export interface TextToSpeechProps {
stopPlaying: () => void;
textToSpeech: (textToSpeak: string) => void;
isPlaying: boolean;
}
export const useTextToSpeech = (): TextToSpeechProps => {
const [isPlaying, setIsPlaying] = useState(false);
const playerRef = useRef<SpeakerAudioDestination>();
const { showError } = useGlobalMessageContext();
const stopPlaying = () => {
setIsPlaying(false);
if (playerRef.current) {
playerRef.current.pause();
}
};
const textToSpeech = async (textToSpeak: string) => {
if (isPlaying) {
stopPlaying();
}
const tokenObj = await GetSpeechToken();
if (tokenObj.error) {
showError(tokenObj.errorMessage);
return;
}
const speechConfig = SpeechConfig.fromAuthorizationToken(
tokenObj.token,
tokenObj.region
);
playerRef.current = new SpeakerAudioDestination();
var audioConfig = AudioConfig.fromSpeakerOutput(playerRef.current);
let synthesizer = new SpeechSynthesizer(speechConfig, audioConfig);
playerRef.current.onAudioEnd = () => {
setIsPlaying(false);
};
synthesizer.speakTextAsync(
textToSpeak,
(result) => {
if (result.reason === ResultReason.SynthesizingAudioCompleted) {
setIsPlaying(true);
} else {
showError(result.errorDetails);
setIsPlaying(false);
}
synthesizer.close();
},
function (err) {
console.log("err - " + err);
synthesizer.close();
}
);
};
return { stopPlaying, textToSpeech, isPlaying };
};