This commit is contained in:
@@ -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 != "" {
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
20
internal/util/ffmpeg.go
Normal 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
|
||||||
|
|
||||||
|
}
|
||||||
5
main.go
5
main.go
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user