Files
wehub-resource-sync 1b8708893a
Security Scan / tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:12:26 +08:00

92 lines
2.7 KiB
Go

package openai
import (
"io"
"net/http"
"os"
"path"
"path/filepath"
"github.com/labstack/echo/v4"
"github.com/mudler/LocalAI/core/backend"
"github.com/mudler/LocalAI/core/config"
"github.com/mudler/LocalAI/core/http/middleware"
"github.com/mudler/LocalAI/core/schema"
model "github.com/mudler/LocalAI/pkg/model"
"github.com/mudler/xlog"
)
// SoundClassificationEndpoint runs an audio-tagging / sound-event
// classification model (e.g. ced) over an uploaded clip and returns the
// scored AudioSet tags in score-descending order. It mirrors the
// transcription path: multipart audio upload -> temp file -> backend call.
//
// @Summary Classify sound events in audio (audio tagging).
// @Tags audio
// @accept multipart/form-data
// @Param model formData string true "model"
// @Param file formData file true "audio file"
// @Param top_k formData int false "number of top tags to return (0 = backend default)"
// @Param threshold formData number false "drop tags scoring below this value"
// @Success 200 {object} schema.SoundClassificationResult
// @Router /v1/audio/classification [post]
func SoundClassificationEndpoint(cl *config.ModelConfigLoader, ml *model.ModelLoader, appConfig *config.ApplicationConfig) echo.HandlerFunc {
return func(c echo.Context) error {
input, ok := c.Get(middleware.CONTEXT_LOCALS_KEY_LOCALAI_REQUEST).(*schema.OpenAIRequest)
if !ok || input.Model == "" {
return echo.ErrBadRequest
}
modelConfig, ok := c.Get(middleware.CONTEXT_LOCALS_KEY_MODEL_CONFIG).(*config.ModelConfig)
if !ok || modelConfig == nil {
return echo.ErrBadRequest
}
req := backend.SoundDetectionRequest{
TopK: int32(parseFormInt(c, "top_k", 0)),
Threshold: float32(parseFormFloat(c, "threshold", 0)),
}
file, err := c.FormFile("file")
if err != nil {
return err
}
f, err := file.Open()
if err != nil {
return err
}
defer func() { _ = f.Close() }()
dir, err := os.MkdirTemp("", "sound-classification")
if err != nil {
return err
}
defer func() { _ = os.RemoveAll(dir) }()
dst := filepath.Join(dir, path.Base(file.Filename))
dstFile, err := os.Create(dst) // #nosec G304 -- dst is a server-created temp dir joined with path.Base of the upload name (no traversal)
if err != nil {
return err
}
if _, err := io.Copy(dstFile, f); err != nil {
xlog.Debug("Audio file copying error", "filename", file.Filename, "dst", dst, "error", err)
_ = dstFile.Close()
return err
}
_ = dstFile.Close()
req.Audio = dst
result, err := backend.ModelSoundDetection(c.Request().Context(), req, ml, *modelConfig, appConfig)
if err != nil {
xlog.Error("Sound classification failed",
"model", modelConfig.Name,
"audio", dst,
"error", err)
return err
}
return c.JSON(http.StatusOK, result)
}
}