x-movie/server/main.go

155 lines
3.4 KiB
Go
Raw Normal View History

2023-07-04 15:47:01 +00:00
package main
import (
"bytes"
"io/fs"
"log"
"net/http"
"os/exec"
"path/filepath"
2023-07-08 09:44:51 +00:00
"sort"
"strconv"
2023-07-04 15:47:01 +00:00
"strings"
"github.com/gin-gonic/gin"
)
2023-07-08 09:44:51 +00:00
// Category 电影分类结构
type Category struct {
Name string `json:"name"`
Movies []Movie `json:"movies"`
}
2023-07-04 15:47:01 +00:00
// Movie 电影结构
type Movie struct {
2023-07-08 09:44:51 +00:00
Name string `json:"filename"`
Image string `json:"image"`
Duration int `json:"duration"`
2023-07-04 15:47:01 +00:00
}
2023-07-08 09:44:51 +00:00
// var movies []Movie
var categories []Category
2023-07-04 15:47:01 +00:00
func initMovie() {
2023-07-08 09:44:51 +00:00
// 需要改进 如果存在这个文件的略缩图, 就不存进movieDict里
2023-07-04 15:47:01 +00:00
var movieDict map[string]string = make(map[string]string)
matches, err := filepath.Glob("movie/*")
if err != nil {
log.Println(err)
}
for _, filename := range matches {
base := filepath.Base(filename)
2023-07-08 09:44:51 +00:00
// ext := filepath.Ext(base)
2023-07-04 15:47:01 +00:00
base = base[:strings.IndexByte(base, '.')]
if _, ok := movieDict[base]; ok {
delete(movieDict, base)
} else {
movieDict[base] = filename
}
}
for key, filename := range movieDict {
2023-07-07 19:15:48 +00:00
// width := 160
// height := 120
2023-07-04 15:47:01 +00:00
log.Println(filename)
2023-07-07 19:15:48 +00:00
cmd := exec.Command("ffmpeg",
"-i", filename,
"-vf", "select='isnan(prev_selected_t)+gte(t-prev_selected_t\\,35)',scale=320:180,tile=3x3",
"-frames:v", "1",
"movie/"+key+".png",
)
2023-07-04 15:47:01 +00:00
var buffer bytes.Buffer
cmd.Stdout = &buffer
if cmd.Run() != nil {
2023-07-07 19:15:48 +00:00
log.Println(buffer.String())
2023-07-04 15:47:01 +00:00
panic("could not generate frame")
}
2023-07-07 19:15:48 +00:00
2023-07-08 09:44:51 +00:00
}
// 初始化分类
categories = []Category{
{Name: "15min", Movies: []Movie{}},
{Name: "30min", Movies: []Movie{}},
{Name: "60min", Movies: []Movie{}},
{Name: "大于60min", Movies: []Movie{}},
2023-07-04 15:47:01 +00:00
}
filepath.Walk("./movie", func(path string, info fs.FileInfo, err error) error {
if !info.IsDir() && filepath.Ext(info.Name()) != ".png" {
base := info.Name()
2023-07-08 09:44:51 +00:00
cmd := exec.Command("ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries", "stream=duration", "-of", "default=nw=1:nk=1", "./movie/"+info.Name())
durationOutput, err := cmd.Output()
if err != nil {
log.Printf("Error getting duration for %s: %v", info.Name(), err)
return err
}
duration, err := strconv.ParseFloat(strings.Trim(string(durationOutput), "\n "), 64)
if err != nil {
log.Printf("Error parsing duration for %s: %v", info.Name(), err)
return err
}
2023-07-04 15:47:01 +00:00
log.Println(path, info.Name())
2023-07-08 09:44:51 +00:00
movie := Movie{
Name: info.Name(),
Image: base[:strings.IndexByte(base, '.')] + ".png",
Duration: int(duration / 60.0),
}
if movie.Duration <= 15 {
categories[0].Movies = append(categories[0].Movies, movie)
} else if movie.Duration <= 30 {
categories[1].Movies = append(categories[1].Movies, movie)
} else if movie.Duration <= 60 {
categories[2].Movies = append(categories[2].Movies, movie)
} else {
categories[3].Movies = append(categories[3].Movies, movie)
}
2023-07-04 15:47:01 +00:00
}
return nil
})
2023-07-08 09:44:51 +00:00
for _, category := range categories {
var movies = category.Movies
sort.Slice(movies, func(i, j int) bool {
return movies[i].Duration < movies[j].Duration
})
}
// log.Printf("%##v", categories)
2023-07-04 15:47:01 +00:00
}
func main() {
initMovie()
eg := gin.Default()
eg.Use(Cors())
eg.Static("/res", "movie/")
// 添加以下代码以提供frontend静态文件
eg.Static("/static", "../build/static")
eg.NoRoute(func(c *gin.Context) {
path := c.Request.URL.Path
if filepath.Ext(path) == "" {
c.File("../build/index.html")
} else {
c.Status(http.StatusNotFound)
}
})
movie := eg.Group("movie")
movie.GET("/", MovieList)
eg.Run(":4444")
}