-
-
Notifications
You must be signed in to change notification settings - Fork 268
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
304 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import { useEffect, useRef, useState } from "react"; | ||
import { notification } from "antd"; | ||
import { useMutation } from "@tanstack/react-query"; | ||
import axios from "axios"; | ||
import { getUrl } from "../utils/getUrl"; | ||
|
||
type VoiceOptions = { | ||
id: string; | ||
}; | ||
|
||
export const useVoice = () => { | ||
const audioRef = useRef<HTMLAudioElement | null>(null); | ||
const [isPlaying, setIsPlaying] = useState(false); | ||
|
||
const onSubmit = async (values: { id: string }) => { | ||
const response = await axios.post(`${getUrl().split("?")[0]}/tts`, values, { | ||
responseType: "arraybuffer", | ||
}); | ||
return response.data; | ||
}; | ||
|
||
const { mutateAsync: generateAudio, isLoading } = useMutation(onSubmit); | ||
|
||
const speak = async (args: VoiceOptions) => { | ||
try { | ||
const data = await generateAudio({ | ||
id: args.id, | ||
}); | ||
|
||
const blob = new Blob([data], { type: "audio/mpeg" }); | ||
const url = window.URL.createObjectURL(blob); | ||
audioRef.current = new Audio(url); | ||
|
||
audioRef.current.onended = () => { | ||
setIsPlaying(false); | ||
}; | ||
|
||
audioRef.current.play(); | ||
setIsPlaying(true); | ||
} catch (error) { | ||
console.log(error); | ||
|
||
notification.error({ | ||
message: "Error", | ||
description: "Something went wrong while trying to play the audio", | ||
}); | ||
} | ||
}; | ||
|
||
const cancel = () => { | ||
if (audioRef.current) { | ||
audioRef.current.pause(); | ||
audioRef.current.currentTime = 0; | ||
setIsPlaying(false); | ||
} | ||
}; | ||
|
||
useEffect(() => { | ||
return () => { | ||
cancel(); | ||
}; | ||
}, []); | ||
|
||
return { | ||
speak, | ||
cancel, | ||
isPlaying, | ||
loading: isLoading, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,5 +13,6 @@ export type BotStyle = { | |
text_color?: string; | ||
}; | ||
first_message: string; | ||
tts: boolean; | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export * from "./post.handler" | ||
export * from "./get.handler" | ||
export * from "./api.handler" | ||
export * from "./api.handler" | ||
export * from "./voice.handler" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import { FastifyReply, FastifyRequest } from "fastify"; | ||
import { ChatTTSRequest } from "./types"; | ||
import { | ||
isElevenLabAPIKeyPresent, | ||
isElevenLabAPIValid, | ||
isOpenAIAPIKeyPresent, | ||
textToSpeech, | ||
textToSpeechOpenAI, | ||
} from "../../utils/voice"; | ||
|
||
export const chatTTSHandler = async ( | ||
request: FastifyRequest<ChatTTSRequest>, | ||
reply: FastifyReply | ||
) => { | ||
const bot_id = request.params.id; | ||
const prisma = request.server.prisma; | ||
const chat_id = request.body.id; | ||
|
||
const isBotExist = await prisma.bot.findFirst({ | ||
where: { | ||
publicId: bot_id, | ||
}, | ||
}); | ||
|
||
if (!isBotExist) { | ||
return reply.status(404).send({ | ||
message: "Bot not found", | ||
}); | ||
} | ||
|
||
let text = ""; | ||
|
||
const botAppearance = await prisma.botAppearance.findFirst({ | ||
where: { | ||
bot_id: isBotExist.id, | ||
}, | ||
}); | ||
|
||
if (!botAppearance) { | ||
return reply.status(404).send({ | ||
message: "Bot configuration not found", | ||
}); | ||
} | ||
|
||
if (chat_id === "first-message") { | ||
text = botAppearance?.first_message! || ""; | ||
} else { | ||
const chat = await prisma.botWebHistory.findFirst({ | ||
where: { | ||
id: chat_id, | ||
}, | ||
}); | ||
|
||
if (!chat) { | ||
return reply.status(404).send({ | ||
message: "Chat not found", | ||
}); | ||
} | ||
|
||
text = chat.bot!; | ||
} | ||
|
||
if (!botAppearance.tts) { | ||
return reply.status(404).send({ | ||
message: "TTS not enabled for this bot", | ||
}); | ||
} | ||
if (botAppearance?.tts_provider === "eleven_labs") { | ||
if (!isElevenLabAPIKeyPresent()) { | ||
return reply.status(400).send({ | ||
message: "Eleven Labs API key not present", | ||
}); | ||
} | ||
const is11LabAPIVValid = await isElevenLabAPIValid(); | ||
if (!is11LabAPIVValid) { | ||
return reply.status(400).send({ | ||
message: "Eleven Labs API key not valid", | ||
}); | ||
} | ||
const buffer = await textToSpeech(text, botAppearance.tts_voice!); | ||
return reply.status(200).send(buffer); | ||
} else if (botAppearance.tts_provider === "openai") { | ||
const isOpenAIKeyPresent = isOpenAIAPIKeyPresent(); | ||
if (!isOpenAIKeyPresent) { | ||
return reply.status(400).send({ | ||
message: "OpenAI API key not present", | ||
}); | ||
} | ||
const buffer = await textToSpeechOpenAI( | ||
text, | ||
botAppearance.tts_voice!, | ||
botAppearance.tts_model! | ||
); | ||
return reply.status(200).send(buffer); | ||
} else { | ||
return reply.status(404).send({ | ||
message: "TTS provider not found", | ||
}); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.