|
|
@@ -273,6 +273,39 @@ func OpenaiHandler(c *gin.Context, info *relaycommon.RelayInfo, resp *http.Respo
|
|
|
return &simpleResponse.Usage, nil
|
|
|
}
|
|
|
|
|
|
+func streamTTSResponse(c *gin.Context, resp *http.Response) {
|
|
|
+ c.Writer.WriteHeaderNow()
|
|
|
+
|
|
|
+ flusher, ok := c.Writer.(http.Flusher)
|
|
|
+ if !ok {
|
|
|
+ logger.LogWarn(c, "streaming not supported")
|
|
|
+ _, err := io.Copy(c.Writer, resp.Body)
|
|
|
+ if err != nil {
|
|
|
+ logger.LogWarn(c, err.Error())
|
|
|
+ }
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ buffer := make([]byte, 4096)
|
|
|
+ for {
|
|
|
+ n, err := resp.Body.Read(buffer)
|
|
|
+ //logger.LogInfo(c, fmt.Sprintf("streamTTSResponse read %d bytes", n))
|
|
|
+ if n > 0 {
|
|
|
+ if _, writeErr := c.Writer.Write(buffer[:n]); writeErr != nil {
|
|
|
+ logger.LogError(c, writeErr.Error())
|
|
|
+ break
|
|
|
+ }
|
|
|
+ flusher.Flush()
|
|
|
+ }
|
|
|
+ if err != nil {
|
|
|
+ if err != io.EOF {
|
|
|
+ logger.LogError(c, err.Error())
|
|
|
+ }
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
func OpenaiTTSHandler(c *gin.Context, resp *http.Response, info *relaycommon.RelayInfo) *dto.Usage {
|
|
|
// the status code has been judged before, if there is a body reading failure,
|
|
|
// it should be regarded as a non-recoverable error, so it should not return err for external retry.
|
|
|
@@ -288,10 +321,16 @@ func OpenaiTTSHandler(c *gin.Context, resp *http.Response, info *relaycommon.Rel
|
|
|
c.Writer.Header().Set(k, v[0])
|
|
|
}
|
|
|
c.Writer.WriteHeader(resp.StatusCode)
|
|
|
- c.Writer.WriteHeaderNow()
|
|
|
- _, err := io.Copy(c.Writer, resp.Body)
|
|
|
- if err != nil {
|
|
|
- logger.LogError(c, err.Error())
|
|
|
+
|
|
|
+ isStreaming := resp.ContentLength == -1 || resp.Header.Get("Content-Length") == ""
|
|
|
+ if isStreaming {
|
|
|
+ streamTTSResponse(c, resp)
|
|
|
+ } else {
|
|
|
+ c.Writer.WriteHeaderNow()
|
|
|
+ _, err := io.Copy(c.Writer, resp.Body)
|
|
|
+ if err != nil {
|
|
|
+ logger.LogError(c, err.Error())
|
|
|
+ }
|
|
|
}
|
|
|
return usage
|
|
|
}
|