添加歌曲封面接口
All checks were successful
Go CI / test-and-build (push) Successful in 12s

This commit is contained in:
2026-04-06 23:16:34 +08:00
parent 3182b29932
commit 0b7cd05486
5 changed files with 63 additions and 1 deletions

View File

@@ -3,22 +3,32 @@ package config
import ( import (
"log" "log"
"os" "os"
"path"
"strconv" "strconv"
) )
type Config struct { type Config struct {
DatabasePath string DatabasePath string
CachePath string
} }
// LoadConfig loads configuration from environment variables // LoadConfig loads configuration from environment variables
func LoadConfig() *Config { func LoadConfig() *Config {
cfg := &Config{ cfg := &Config{
DatabasePath: getEnv("DATABASE_PATH", "./butterfliu.db"), DatabasePath: getEnv("DATABASE_PATH", "./butterfliu.db"),
CachePath: getEnv("CACHE_PATH", "./cache"),
} }
os.MkdirAll(cfg.CachePath, os.ModeAppend)
return cfg return cfg
} }
func (self *Config) GetCachePath(cacheType string) string {
path := path.Join(self.CachePath, cacheType)
os.MkdirAll(path, os.ModeAppend)
return path
}
// getEnv gets an environment variable with a default value // getEnv gets an environment variable with a default value
func getEnv(key, defaultValue string) string { func getEnv(key, defaultValue string) string {
if value := os.Getenv(key); value != "" { if value := os.Getenv(key); value != "" {

View File

@@ -41,3 +41,18 @@ func (c *SongController) Stream(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, mediaFile.Path) http.ServeFile(w, r, mediaFile.Path)
} }
func (c *SongController) Cover(w http.ResponseWriter, r *http.Request) {
paramID := chi.URLParam(r, "id")
id, err := strconv.Atoi(paramID)
if err != nil {
http.Error(w, "无效的歌曲 ID", http.StatusBadRequest)
return
}
coverPath, err := c.service.GetCover(id)
if err != nil {
http.Error(w, "获取封面异常", http.StatusNotFound)
return
}
http.ServeFile(w, r, coverPath)
}

View File

@@ -1,8 +1,12 @@
package service package service
import ( import (
"butterfliu/config"
"butterfliu/internal/model" "butterfliu/internal/model"
"butterfliu/internal/repository" "butterfliu/internal/repository"
"butterfliu/internal/util"
"path"
"strconv"
) )
type SongService struct { type SongService struct {
@@ -29,3 +33,13 @@ func (s *SongService) GetMediaFile(id int) (model.MediaFile, error) {
} }
return s.mediaRepo.Get(song.MediaFileID) return s.mediaRepo.Get(song.MediaFileID)
} }
func (s *SongService) GetCover(id int) (string, error) {
file, err := s.GetMediaFile(id)
if err != nil {
return "", err
}
util.ExtractCover(file.Path, id)
conf := config.LoadConfig()
return path.Join(conf.GetCachePath("cover"), strconv.Itoa(id)+".jpg"), nil
}

20
internal/util/ffmpeg.go Normal file
View File

@@ -0,0 +1,20 @@
package util
import (
"os/exec"
"strconv"
)
func ExtractCover(filePath string, id int) bool {
if _, err := exec.LookPath("ffmpeg"); err != nil {
return false
}
coverPath := "cache/cover/" + strconv.Itoa(id) + ".jpg"
cmd := exec.Command("ffmpeg", "-i", filePath, "-an", "-vcodec", "mjpeg", "-q:v", "5", "-f", "image2", "-y", coverPath)
if err := cmd.Run(); err != nil {
return false
}
return true
}

View File

@@ -4,6 +4,7 @@ import (
"butterfliu/internal/controller" "butterfliu/internal/controller"
"butterfliu/internal/repository" "butterfliu/internal/repository"
"butterfliu/internal/service" "butterfliu/internal/service"
"butterfliu/config"
"log" "log"
"net/http" "net/http"
@@ -12,7 +13,8 @@ import (
) )
func main() { func main() {
err := InitDB("./butterfliu.db") config := config.LoadConfig()
err := InitDB(config.DatabasePath)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@@ -46,6 +48,7 @@ func main() {
r.Route("/api/songs", func(r chi.Router) { r.Route("/api/songs", func(r chi.Router) {
r.Get("/", songController.GetAllWithDetails) r.Get("/", songController.GetAllWithDetails)
r.Get("/{id}/stream", songController.Stream) r.Get("/{id}/stream", songController.Stream)
r.Get("/{id}/cover", songController.Cover)
}) })
r.Route("/api", func(r chi.Router) { r.Route("/api", func(r chi.Router) {