-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update API key button onClick parameter
Add TTSOutputNode component Add AudioPlayer component Refactor SttOutputNode component
- Loading branch information
Showing
8 changed files
with
211 additions
and
85 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { useEffect, useRef } from "react"; | ||
import PropTypes from "prop-types"; | ||
|
||
const AudioPlayer = ({ file }) => { | ||
const audioRef = useRef(null); | ||
|
||
useEffect(() => { | ||
if (audioRef.current) { | ||
audioRef.current.load(); | ||
} | ||
}, [file]); | ||
|
||
return ( | ||
<div className="flex items-center justify-center w-full"> | ||
<audio ref={audioRef} controls className="w-full h-10"> | ||
<source src={file?.data} type="audio/mp3" /> | ||
</audio> | ||
</div> | ||
); | ||
}; | ||
|
||
AudioPlayer.propTypes = { | ||
file: PropTypes.shape({ | ||
data: PropTypes.string, | ||
}), | ||
}; | ||
|
||
export default AudioPlayer; |
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,114 @@ | ||
import { useState, useCallback, useRef, useEffect, useMemo } from "react"; | ||
import { storeManager, useConfigStore, useFileStore } from "../../store"; | ||
import { Handle, Position } from "reactflow"; | ||
import Container from "../Common/container"; | ||
import PropTypes from "prop-types"; | ||
import { uploadAudio } from "../../api/stt"; | ||
import Dropdown from "../Common/dropdown"; | ||
import { responseFormatSTT, languages } from "../../store/constants"; | ||
import Loading from "../Common/loading"; | ||
import Tooltip from "../Common/tooltip"; | ||
import AudioPlayer from "../Common/audioPlayer"; | ||
import "highlight.js/styles/github-dark.css"; | ||
|
||
function TTSOutputNode({ id }) { | ||
const containerRef = useRef(null); | ||
const [loading, setLoading] = useState(false); | ||
const [regenerate, setRegenerate] = useState(false); | ||
const [audio, setAudio] = useState(null); | ||
|
||
const store = storeManager.getSelectedStore(); | ||
const { findParentNodeByType, findChildNodeByType } = store( | ||
({ findParentNodeByType, findChildNodeByType }) => ({ | ||
findParentNodeByType, | ||
findChildNodeByType, | ||
}) | ||
); | ||
|
||
const text = useMemo(() => { | ||
const parent = findParentNodeByType(id, "tts"); | ||
if (parent) { | ||
return parent.data.text; | ||
} | ||
return ""; | ||
}, [findParentNodeByType, id]); | ||
|
||
const childNode = useMemo(() => { | ||
const child = findChildNodeByType(id, "tts"); | ||
if (child) { | ||
return child; | ||
} | ||
return null; | ||
}, [findChildNodeByType, id]); | ||
|
||
const { TTSModel, openAIInstance, voice, language, speed } = useConfigStore( | ||
({ TTSModel, openAIInstance, voice, language, speed }) => ({ | ||
TTSModel, | ||
openAIInstance, | ||
voice, | ||
language, | ||
speed, | ||
}) | ||
); | ||
|
||
const sendText = useCallback(async () => { | ||
setLoading(true); | ||
if (openAIInstance && text.trim().length > 0 && !audio) { | ||
setRegenerate(false); | ||
const mp3 = await openAIInstance.audio.speech.create({ | ||
model: TTSModel, | ||
input: text, | ||
voice, | ||
speed, | ||
language, | ||
}); | ||
const blob = new Blob([await mp3.arrayBuffer()], { type: "audio/mp3" }); | ||
const audioUrl = URL.createObjectURL(blob); | ||
setAudio({ data: audioUrl }); | ||
} | ||
setLoading(false); | ||
}, [openAIInstance, text, audio, TTSModel, voice, speed, language]); | ||
|
||
useEffect(() => { | ||
// this is to stop the request if this is a reloading of the page | ||
// as everything runs again when the page reloads and if there is a lot of audios | ||
// it will take make a lot of requests to the api | ||
if (childNode?.data?.text?.trim().length > 0) { | ||
setLoading(false); | ||
setRegenerate(true); | ||
return; | ||
} | ||
sendText(); | ||
}, []); | ||
|
||
return ( | ||
<Container | ||
innerRef={containerRef} | ||
title="Output" | ||
className="w-[500px] min-h-[150px] overflow-y-scroll flex items-center justify-center overflow-hidden pb-10 relative" | ||
id={id} | ||
> | ||
<div className="flex flex-col items-center justify-center w-full"> | ||
<Handle type="source" position={Position.Bottom} /> | ||
<Handle type="target" position={Position.Top} /> | ||
{loading && <Loading />} | ||
{audio && <AudioPlayer file={audio} />} | ||
{regenerate && ( | ||
<button className="p-2 border border-gray-300 rounded-md duration-200 ease-in-out" onClick={sendText}> | ||
Regenerate | ||
</button> | ||
)} | ||
</div> | ||
</Container> | ||
); | ||
} | ||
|
||
TTSOutputNode.propTypes = { | ||
id: PropTypes.string, | ||
data: PropTypes.shape({ | ||
text: PropTypes.string, | ||
id: PropTypes.string, | ||
}), | ||
}; | ||
|
||
export default TTSOutputNode; |
Oops, something went wrong.