diff --git a/app/components/chat.tsx b/app/components/chat.tsx index 3d519dee7..eb2848f08 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -1227,16 +1227,19 @@ function _Chat() { }); } setSpeechStatus(true); - ttsPlayer - .play(audioBuffer, () => { + try { + await ttsPlayer.play(audioBuffer, () => { setSpeechStatus(false); - }) - .catch((e) => { - console.error("[OpenAI Speech]", e); - showToast(prettyObject(e)); - setSpeechStatus(false); - }) - .finally(() => setSpeechLoading(false)); + }); + const audioFile = new Blob([audioBuffer], { type: "audio/wav" }); + const url = uploadAudio(audioFile); + } catch (e) { + console.error("[OpenAI Speech]", e); + showToast(prettyObject(e)); + setSpeechStatus(false); + } finally { + setSpeechLoading(false); + } } } @@ -1505,6 +1508,53 @@ function _Chat() { setAttachImages(images); } + async function uploadAudio(file: Blob) { + const audioUrl: string = await uploadImageRemote(file); + console.log("audioUrl: ", audioUrl); + //const images: string[] = []; + //images.push(...attachImages); + + //images.push( + // ...(await new Promise((res, rej) => { + // const fileInput = document.createElement("input"); + // fileInput.type = "file"; + // fileInput.accept = + // "image/png, image/jpeg, image/webp, image/heic, image/heif"; + // fileInput.multiple = true; + // fileInput.onchange = (event: any) => { + // setUploading(true); + // const files = event.target.files; + // const imagesData: string[] = []; + // for (let i = 0; i < files.length; i++) { + // const file = event.target.files[i]; + // uploadImageRemote(file) + // .then((dataUrl) => { + // imagesData.push(dataUrl); + // if ( + // imagesData.length === 3 || + // imagesData.length === files.length + // ) { + // setUploading(false); + // res(imagesData); + // } + // }) + // .catch((e) => { + // setUploading(false); + // rej(e); + // }); + // } + // }; + // fileInput.click(); + // })), + //); + + //const imagesLength = images.length; + //if (imagesLength > 3) { + // images.splice(3, imagesLength - 3); + //} + //setAttachImages(images); + } + // 快捷键 shortcut keys const [showShortcutKeyModal, setShowShortcutKeyModal] = useState(false); diff --git a/app/icons/play.svg b/app/icons/play.svg new file mode 100644 index 000000000..64e3efca4 --- /dev/null +++ b/app/icons/play.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/icons/stop.svg b/app/icons/stop.svg new file mode 100644 index 000000000..9037b3390 --- /dev/null +++ b/app/icons/stop.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/utils.ts b/app/utils.ts index 6b2f65952..b6cb6f6d9 100644 --- a/app/utils.ts +++ b/app/utils.ts @@ -250,6 +250,19 @@ export function getMessageImages(message: RequestMessage): string[] { return urls; } +//export function getMessageAudio(message: RequestMessage): string[] { +// if (typeof message.content === "string") { +// return []; +// } +// const urls: string[] = []; +// for (const c of message.content) { +// if (c.type === "image_url") { +// urls.push(c.image_url?.url ?? ""); +// } +// } +// return urls; +//} + export function isVisionModel(model: string) { // Note: This is a better way using the TypeScript feature instead of `&&` or `||` (ts v5.5.0-dev.20240314 I've been using)