diff --git a/api/handle_tts.go b/api/handle_tts.go
new file mode 100644
index 00000000..d14ff03d
--- /dev/null
+++ b/api/handle_tts.go
@@ -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)
+}
diff --git a/api/main.go b/api/main.go
index 45d8009e..4ed69a6f 100644
--- a/api/main.go
+++ b/api/main.go
@@ -147,7 +147,6 @@ func main() {
if err != nil {
log.Fatal(err)
}
-
ChatModelHandler := NewChatModelHandler(sqlc_q)
ChatModelHandler.Register(router)
@@ -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()
@@ -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)
diff --git a/api/middleware_authenticate.go b/api/middleware_authenticate.go
index dd1fd626..066b33de 100644
--- a/api/middleware_authenticate.go
+++ b/api/middleware_authenticate.go
@@ -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) {
diff --git a/web/src/locales/zh-CN.json b/web/src/locales/zh-CN.json
index 6916d188..008b618c 100644
--- a/web/src/locales/zh-CN.json
+++ b/web/src/locales/zh-CN.json
@@ -77,7 +77,8 @@
"sessionConfig": "会话设置",
"enable_debug": "启用",
"disable_debug": "关闭",
- "completionsCount": "结果数量: {contextCount}"
+ "completionsCount": "结果数量: {contextCount}",
+ "playAudio": "语音"
},
"chat_snapshot": {
"title": "对话集",
diff --git a/web/src/views/chat/components/AudioPlayer/index.vue b/web/src/views/chat/components/AudioPlayer/index.vue
new file mode 100644
index 00000000..c0cda715
--- /dev/null
+++ b/web/src/views/chat/components/AudioPlayer/index.vue
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/web/src/views/chat/components/Message/index.vue b/web/src/views/chat/components/Message/index.vue
index 3ea52af8..0dd34a90 100644
--- a/web/src/views/chat/components/Message/index.vue
+++ b/web/src/views/chat/components/Message/index.vue
@@ -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
@@ -119,6 +120,7 @@ function handleRegenerate() {
+
diff --git a/web/src/views/chat/index.vue b/web/src/views/chat/index.vue
index 0c4b8fd0..0afe6821 100644
--- a/web/src/views/chat/index.vue
+++ b/web/src/views/chat/index.vue
@@ -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" />
+