// Package common // @Link https://github.com/bufanyun/hotgo // @Copyright Copyright (c) 2023 HotGo CLI // @Author Ms <133814250@qq.com> // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE package common import ( "context" "hotgo/api/admin/common" "hotgo/internal/library/storager" "hotgo/internal/service" "hotgo/utility/validate" "os" "os/exec" "path/filepath" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/google/uuid" ) var Upload = new(cUpload) type cUpload struct{} // UploadFile 上传文件 func (c *cUpload) UploadFile(ctx context.Context, _ *common.UploadFileReq) (res common.UploadFileRes, err error) { r := g.RequestFromCtx(ctx) uploadType := r.Header.Get("uploadType") if uploadType != "default" && !validate.InSlice(storager.KindSlice, uploadType) { err = gerror.New("上传类型是无效的") return } file := r.GetUploadFile("file") if file == nil { err = gerror.New("没有找到上传的文件") return } return service.CommonUpload().UploadFile(ctx, uploadType, file) } // UploadVideo 上传视频 func (c *cUpload) UploadVideo(ctx context.Context, _ *common.UploadVideoReq) (res common.UploadVideoRes, err error) { r := g.RequestFromCtx(ctx) uploadType := r.Header.Get("uploadType") if uploadType != "default" && !validate.InSlice(storager.KindSlice, uploadType) { err = gerror.New("上传类型是无效的") return } file := r.GetUploadFile("file") if file == nil { err = gerror.New("没有找到上传的文件") return } // 1. 保存上传视频到本地临时目录 tmpDir := "./tmp/video" _, _ = file.Save(tmpDir) tmpFile := tmpDir + "/" + file.Filename // 2. 用ffmpeg切片为m3u8和ts文件 m3u8UUID := uuid.New().String() hlsDir := "./tmp/hls/" + m3u8UUID _ = os.MkdirAll(hlsDir, 0755) defer func() { os.RemoveAll(hlsDir) }() m3u8File := m3u8UUID + ".m3u8" m3u8Path := hlsDir + "/" + m3u8File ffmpegCmd := exec.Command("ffmpeg", "-i", tmpFile, "-c:v", "libx264", "-hls_time", "10", "-hls_playlist_type", "vod", m3u8Path) err = ffmpegCmd.Run() if err != nil { err = gerror.Wrap(err, "ffmpeg切片失败") return } // 3. 遍历切片目录,上传所有m3u8和ts文件到minio minioDrive := new(storager.MinioDrive) var m3u8MinioPath string files, _ := filepath.Glob(hlsDir + "/*") for _, f := range files { fileInfo, errStat := os.Stat(f) if errStat == nil && !fileInfo.IsDir() { minioPath, err2 := minioDrive.UploadFromPath(ctx, f, filepath.Base(f)) if err2 != nil { err = err2 return } if filepath.Ext(f) == ".m3u8" { m3u8MinioPath = minioPath } } } // 4. 返回m3u8文件的minio路径 return common.UploadVideoRes{ Path: m3u8MinioPath, }, nil } // CheckMultipart 检查文件分片 func (c *cUpload) CheckMultipart(ctx context.Context, req *common.CheckMultipartReq) (res *common.CheckMultipartRes, err error) { data, err := service.CommonUpload().CheckMultipart(ctx, &req.CheckMultipartInp) if err != nil { return nil, err } res = new(common.CheckMultipartRes) res.CheckMultipartModel = data return } // UploadPart 上传分片 func (c *cUpload) UploadPart(ctx context.Context, req *common.UploadPartReq) (res *common.UploadPartRes, err error) { data, err := service.CommonUpload().UploadPart(ctx, &req.UploadPartInp) if err != nil { return nil, err } res = new(common.UploadPartRes) res.UploadPartModel = data return }