go-whisper-api/api/openai.go
admin b5c083e06f
Some checks failed
CodeQL / Analyze (go) (push) Successful in 6m28s
Docker Image / build-docker (push) Failing after 13m26s
Lint and Testing / lint (push) Successful in 11m17s
Lint and Testing / test (push) Successful in 11m17s
Lint and Testing / golangci (push) Successful in 2m40s
first commit
2026-06-04 18:10:52 +07:00

122 lines
3.5 KiB
Go

package api
import (
"encoding/json"
"net/http"
"strings"
"time"
)
func (s *Server) handleOpenAITranscriptions(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
writeOpenAIError(w, http.StatusMethodNotAllowed, "method not allowed")
return
}
if err := r.ParseMultipartForm(128 << 20); err != nil {
writeOpenAIError(w, http.StatusBadRequest, err.Error())
return
}
modelID, err := s.models.Resolve(r.FormValue("model"), s.cfg.DefaultModel)
if err != nil {
writeOpenAIError(w, http.StatusBadRequest, err.Error())
return
}
modelPath, err := s.models.Path(modelID)
if err != nil {
writeOpenAIError(w, http.StatusBadRequest, err.Error())
return
}
audioPath, cleanup, err := s.saveUploadedOpenAI(r)
if err != nil {
writeOpenAIError(w, http.StatusBadRequest, err.Error())
return
}
defer cleanup()
stt := s.parseOpenAISTTOptions(r)
result, err := s.transcribe(r.Context(), modelPath, audioPath, stt)
if err != nil {
writeOpenAIError(w, http.StatusInternalServerError, err.Error())
return
}
switch strings.ToLower(strings.TrimSpace(r.FormValue("response_format"))) {
case "text":
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(result.Text))
default:
writeJSON(w, http.StatusOK, map[string]string{"text": result.Text})
}
}
func (s *Server) handleOpenAIModels(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
writeOpenAIError(w, http.StatusMethodNotAllowed, "method not allowed")
return
}
ids, err := s.models.List()
if err != nil {
writeOpenAIError(w, http.StatusInternalServerError, err.Error())
return
}
now := time.Now().Unix()
data := make([]map[string]any, 0, len(ids))
for _, id := range ids {
data = append(data, map[string]any{
"id": id,
"object": "model",
"created": now,
"owned_by": "go-whisper-api",
})
}
writeJSON(w, http.StatusOK, map[string]any{
"object": "list",
"data": data,
})
}
func (s *Server) parseOpenAISTTOptions(r *http.Request) sttOptions {
lang := strings.TrimSpace(r.FormValue("language"))
if lang == "" {
lang = s.cfg.Language
}
return sttOptions{
language: lang,
punctuate: s.punctCfg.ShouldApplyAPI(r, s.cfg.DefaultPunctuation),
}
}
func (s *Server) saveUploadedOpenAI(r *http.Request) (path string, cleanup func(), err error) {
if r.MultipartForm == nil {
if err := r.ParseMultipartForm(128 << 20); err != nil {
return "", nil, err
}
}
return saveUploadedRawFields(r, []string{"file", "audio", "wav"})
}
func writeOpenAIError(w http.ResponseWriter, code int, msg string) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(code)
_ = json.NewEncoder(w).Encode(map[string]any{
"error": map[string]any{
"message": msg,
"type": openAIErrorType(code),
},
})
}
func openAIErrorType(code int) string {
switch code {
case http.StatusBadRequest:
return "invalid_request_error"
case http.StatusUnauthorized:
return "authentication_error"
case http.StatusNotFound:
return "not_found_error"
default:
return "server_error"
}
}