大项目总结(2) | 青训营笔记

114 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 8 天

这篇笔记是大项目的第二次总结,我会总结在大项目中遇到的一些技术问题以及解决方法

/douyin/publish/action 发表视频

上传视频

data, err := c.FormFile("data")
if err != nil {
   c.JSON(http.StatusOK, model.Response{
      StatusCode: 1,
      StatusMsg:  err.Error(),
   })
   return
}
filename := filepath.Base(data.Filename)
//user := usersLoginInfo[token]
//获取文件名后缀
fileSuffix := path.Ext(filename)
laststVideoId, err := dal.GetLatestVideoId(mysql.DB)
if err != nil {
   c.JSON(http.StatusOK, model.Response{
      StatusCode: 1,
      StatusMsg:  err.Error(),
   })
   return
}
//文件名为用户id_视频id.后缀
finalName := fmt.Sprintf("%d_%d%s", user.Id, laststVideoId+1, fileSuffix)
photoName := fmt.Sprintf("%d_%d", user.Id, laststVideoId+1)
fmt.Println(filename)
saveFile := filepath.Join("./public/video/", finalName)
if err := c.SaveUploadedFile(data, saveFile); err != nil {
   c.JSON(http.StatusOK, model.Response{
      StatusCode: 1,
      StatusMsg:  err.Error(),
   })
   return
}
dal.GetSnapshot("./public/video/"+finalName, "./public/photo/"+photoName, 1)
c.JSON(http.StatusOK, model.Response{
   StatusCode: 0,
   StatusMsg:  finalName + " uploaded successfully",
})

1、使用hertz框架中的FormFile函数接收从前端发送来的文件(如果要上传多个文件,用MultipartForm函数)

2、使用hertz框架中的SaveUploadedFile将文件存到本地,它的参数是文件和保存路径。

上述代码中,我将上传的视频重命名为作者id_视频id.视频后缀,防止文件名的重复,获取后缀用了path.Ext函数。

为了获得视频封面,我用了GetSnapShot函数获取了视频的第一帧作为封面,GetSnapShot函数在下文叙述。

GetSnapShot函数

获取视频的第一帧用了FFmpeg模块。FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件)。它提供了录制、转换以及流化音视频的完整解决方案。

GetSnapShot函数的参数为视频路径,保存图片路径,截取的第几帧。返回值为图片名和error。

导入FFmpeg库

import (
    "github.com/disintegration/imaging" 
    ffmpeg "github.com/u2takey/ffmpeg-go"
)

代码

package main

import (
       "bytes"
       "fmt"
       "github.com/disintegration/imaging"
       ffmpeg "github.com/u2takey/ffmpeg-go"
       "log"
       "os"
       "strings"
)

 

func GetSnapshot(videoPath, snapshotPath string, frameNum int) (snapshotName string, err error) {

       buf := bytes.NewBuffer(nil)
       err = ffmpeg.Input(videoPath).
              Filter("select", ffmpeg.Args{fmt.Sprintf("gte(n,%d)", frameNum)}).
              Output("pipe:", ffmpeg.KwArgs{"vframes": 1, "format": "image2", "vcodec": "mjpeg"}).
              WithOutput(buf, os.Stdout).
              Run()

       if err != nil {
              log.Fatal("生成缩略图失败:", err)
              return "", err

       }

       img, err := imaging.Decode(buf)
       if err != nil {
              log.Fatal("生成缩略图失败:", err)
              return "", err

       }
       
       err = imaging.Save(img, snapshotPath+".png")
       if err != nil {
              log.Fatal("生成缩略图失败:", err)
              return "", err

       }

       names := strings.Split(snapshotPath, "\\")
       snapshotName = names[len(names)-1] + ".png"
       return
}

func main() {
       _, err := GetSnapshot("./test.mp4", "test", 1)
       if err != nil {
              return
       }
}

通过上述代码,将函数的参数设为1,就可以得到视频第一帧的图片作为视频封面。

总结

以上就是我对大项目的一些总结,本人水平有限,如有错误欢迎指正。