| package localai |
|
|
| import ( |
| "bufio" |
| "encoding/base64" |
| "encoding/json" |
| "fmt" |
| "io" |
| "net/http" |
| "net/url" |
| "os" |
| "path/filepath" |
| "strings" |
| "time" |
|
|
| "github.com/google/uuid" |
| "github.com/labstack/echo/v4" |
| "github.com/mudler/LocalAI/core/config" |
| "github.com/mudler/LocalAI/core/http/middleware" |
| "github.com/mudler/LocalAI/core/schema" |
|
|
| "github.com/mudler/LocalAI/core/backend" |
|
|
| model "github.com/mudler/LocalAI/pkg/model" |
| "github.com/mudler/xlog" |
| ) |
|
|
| func downloadFile(url string) (string, error) { |
| |
| resp, err := http.Get(url) |
| if err != nil { |
| return "", err |
| } |
| defer resp.Body.Close() |
|
|
| |
| out, err := os.CreateTemp("", "video") |
| if err != nil { |
| return "", err |
| } |
| defer out.Close() |
|
|
| |
| _, err = io.Copy(out, resp.Body) |
| return out.Name(), err |
| } |
|
|
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| func VideoEndpoint(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.VideoRequest) |
| if !ok || input.Model == "" { |
| xlog.Error("Video Endpoint - Invalid Input") |
| return echo.ErrBadRequest |
| } |
|
|
| config, ok := c.Get(middleware.CONTEXT_LOCALS_KEY_MODEL_CONFIG).(*config.ModelConfig) |
| if !ok || config == nil { |
| xlog.Error("Video Endpoint - Invalid Config") |
| return echo.ErrBadRequest |
| } |
|
|
| src := "" |
| if input.StartImage != "" { |
|
|
| var fileData []byte |
| var err error |
| |
| |
| if strings.HasPrefix(input.StartImage, "http://") || strings.HasPrefix(input.StartImage, "https://") { |
| out, err := downloadFile(input.StartImage) |
| if err != nil { |
| return fmt.Errorf("failed downloading file:%w", err) |
| } |
| defer os.RemoveAll(out) |
|
|
| fileData, err = os.ReadFile(out) |
| if err != nil { |
| return fmt.Errorf("failed reading file:%w", err) |
| } |
|
|
| } else { |
| |
| |
| fileData, err = base64.StdEncoding.DecodeString(input.StartImage) |
| if err != nil { |
| return err |
| } |
| } |
|
|
| |
| outputFile, err := os.CreateTemp(appConfig.GeneratedContentDir, "b64") |
| if err != nil { |
| return err |
| } |
| |
| writer := bufio.NewWriter(outputFile) |
| _, err = writer.Write(fileData) |
| if err != nil { |
| outputFile.Close() |
| return err |
| } |
| outputFile.Close() |
| src = outputFile.Name() |
| defer os.RemoveAll(src) |
| } |
|
|
| xlog.Debug("Parameter Config", "config", config) |
|
|
| switch config.Backend { |
| case "stablediffusion": |
| config.Backend = model.StableDiffusionGGMLBackend |
| case "": |
| config.Backend = model.StableDiffusionGGMLBackend |
| } |
|
|
| width := input.Width |
| height := input.Height |
|
|
| if width == 0 { |
| width = 512 |
| } |
| if height == 0 { |
| height = 512 |
| } |
|
|
| b64JSON := input.ResponseFormat == "b64_json" |
|
|
| tempDir := "" |
| if !b64JSON { |
| tempDir = filepath.Join(appConfig.GeneratedContentDir, "videos") |
| } |
| |
| outputFile, err := os.CreateTemp(tempDir, "b64") |
| if err != nil { |
| return err |
| } |
| outputFile.Close() |
|
|
| |
| output := outputFile.Name() + ".mp4" |
|
|
| |
| err = os.Rename(outputFile.Name(), output) |
| if err != nil { |
| return err |
| } |
|
|
| baseURL := middleware.BaseURL(c) |
|
|
| fn, err := backend.VideoGeneration( |
| height, |
| width, |
| input.Prompt, |
| input.NegativePrompt, |
| src, |
| input.EndImage, |
| output, |
| input.NumFrames, |
| input.FPS, |
| input.Seed, |
| input.CFGScale, |
| input.Step, |
| ml, |
| *config, |
| appConfig, |
| ) |
| if err != nil { |
| return err |
| } |
| if err := fn(); err != nil { |
| return err |
| } |
|
|
| item := &schema.Item{} |
|
|
| if b64JSON { |
| defer os.RemoveAll(output) |
| data, err := os.ReadFile(output) |
| if err != nil { |
| return err |
| } |
| item.B64JSON = base64.StdEncoding.EncodeToString(data) |
| } else { |
| base := filepath.Base(output) |
| item.URL, err = url.JoinPath(baseURL, "generated-videos", base) |
| if err != nil { |
| return err |
| } |
| } |
|
|
| id := uuid.New().String() |
| created := int(time.Now().Unix()) |
| resp := &schema.OpenAIResponse{ |
| ID: id, |
| Created: created, |
| Data: []schema.Item{*item}, |
| } |
|
|
| jsonResult, _ := json.Marshal(resp) |
| xlog.Debug("Response", "response", string(jsonResult)) |
|
|
| |
| return c.JSON(200, resp) |
| } |
| } |
|
|