Skip to content

Commit

Permalink
basic audio support (coqui) (#399)
Browse files Browse the repository at this point in the history
* basic audio support

* update

* update

* tts
  • Loading branch information
swuecho authored Dec 3, 2023
1 parent fd7b811 commit 3f0d7bd
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 2 deletions.
52 changes: 52 additions & 0 deletions api/handle_tts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package main

import (
"fmt"
"io"
"net/http"
"os"
)

func handleTTSRequest(w http.ResponseWriter, r *http.Request) {
// Create a new HTTP request with the same method, URL, and body as the original request
targetURL := r.URL
hostEnvVarName := "TTS_HOST"
portEnvVarName := "TTS_PORT"
realHost := fmt.Sprintf("http://%s:%s/api", os.Getenv(hostEnvVarName), os.Getenv(portEnvVarName))
fullURL := realHost + targetURL.String()
print(fullURL)
proxyReq, err := http.NewRequest(r.Method, fullURL, r.Body)
if err != nil {
http.Error(w, "Error creating proxy request", http.StatusInternalServerError)
return
}

// Copy the headers from the original request to the proxy request
for name, values := range r.Header {
for _, value := range values {
proxyReq.Header.Add(name, value)
}
}
var customTransport = http.DefaultTransport

// Send the proxy request using the custom transport
resp, err := customTransport.RoundTrip(proxyReq)
if err != nil {
http.Error(w, "Error sending proxy request", http.StatusInternalServerError)
return
}
defer resp.Body.Close()

// Copy the headers from the proxy response to the original response
for name, values := range resp.Header {
for _, value := range values {
w.Header().Add(name, value)
}
}

// Set the status code of the original response to the status code of the proxy response
w.WriteHeader(resp.StatusCode)

// Copy the body of the proxy response to the original response
io.Copy(w, resp.Body)
}
5 changes: 4 additions & 1 deletion api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ func main() {
if err != nil {
log.Fatal(err)
}

ChatModelHandler := NewChatModelHandler(sqlc_q)
ChatModelHandler.Register(router)

Expand Down Expand Up @@ -211,6 +210,8 @@ func main() {
user_model_privilege_handler := NewUserChatModelPrivilegeHandler(sqlc_q)
user_model_privilege_handler.Register(router)

router.HandleFunc("/tts", handleTTSRequest)

router.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error {
tpl, err1 := route.GetPathTemplate()
met, err2 := route.GetMethods()
Expand Down Expand Up @@ -239,8 +240,10 @@ func main() {
http.Redirect(w, r, "/static/", http.StatusMovedPermanently)
})


router.PathPrefix("/static/").Handler(http.StripPrefix("/static/", makeGzipHandler(cacheHandler)))


// fly.io
if os.Getenv("FLY_APP_NAME") != "" {
router.Use(UpdateLastRequestTime)
Expand Down
1 change: 1 addition & 0 deletions api/middleware_authenticate.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ func IsAuthorizedMiddleware(handler http.Handler) http.Handler {
"/": true,
"/login": true,
"/signup": true,
"/tts": true,
}
jwtSigningKey := []byte(jwtSecretAndAud.Secret)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
Expand Down
3 changes: 2 additions & 1 deletion web/src/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@
"sessionConfig": "会话设置",
"enable_debug": "启用",
"disable_debug": "关闭",
"completionsCount": "结果数量: {contextCount}"
"completionsCount": "结果数量: {contextCount}",
"playAudio": "语音"
},
"chat_snapshot": {
"title": "对话集",
Expand Down
57 changes: 57 additions & 0 deletions web/src/views/chat/components/AudioPlayer/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<script lang="ts" setup>
import { ref } from "vue";
import { HoverButton, SvgIcon } from '@/components/common'
interface Props {
text: string
}
const props = defineProps<Props>()
const source = ref('')
const soundPlayer = ref();
const isActive = ref(false);
// const speaker_id = ref('')
// const style_wav = ref('')
// const language_id = ref('')
// Add a method called 'playAudio' to handle sending the request to the backend.
async function playAudio() {
console.log(props.text)
if (isActive.value) {
isActive.value = false
} else {
let text = encodeURIComponent(props.text)
try {
// Perform the HTTP request to send the request to the backend.
const response = await fetch(`/api/tts?text=${text}`,
{ cache: 'no-cache' });
if (response.ok) {
// If the HTTP response is successful, parse the body into an object and play the sound.
const blob = await response.blob();
source.value = URL.createObjectURL(blob);
console.log(source.value);
isActive.value = true;
} else {
console.log("request failed")
}
} catch (error) {
console.log(error);
}
}
}
</script>


<template>
<HoverButton :tooltip="$t('chat.playAudio')" @click="playAudio">
<span class="text-xl text-[#4f555e] dark:text-white">
<SvgIcon icon="system-uicons:audio-wave" />
</span>
</HoverButton>
<audio ref="soundPlayer" id="audio" autoplay :src="source" v-if="isActive" controls></audio>
</template>

2 changes: 2 additions & 0 deletions web/src/views/chat/components/Message/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { copyText } from '@/utils/format'
import { useIconRender } from '@/hooks/useIconRender'
import { t } from '@/locales'
import { displayLocaleDate } from '@/utils/date'
import AudioPlayer from "../AudioPlayer/index.vue"
interface Props {
index: number
Expand Down Expand Up @@ -119,6 +120,7 @@ function handleRegenerate() {
</NDropdown>
</div>
</div>
<AudioPlayer :text="text || ''"></AudioPlayer>
</div>
</div>
</template>
1 change: 1 addition & 0 deletions web/src/views/chat/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,7 @@ function getDataFromResponseText(responseText: string): string {
:is-prompt="item.isPrompt" :is-pin="item.isPin" :loading="item.loading" :pining="pining" :index="index"
@regenerate="onRegenerate(index)" @delete="handleDelete(index)" @toggle-pin="handleTogglePin(index)"
@after-edit="handleAfterEdit" />

<!--
<div class="sticky bottom-0 left-0 flex justify-center">
<NButton v-if="loading" type="warning" @click="handleStop">
Expand Down

0 comments on commit 3f0d7bd

Please sign in to comment.