赞
踩
根据业务需求 实现golang 结合ffmpeg 实现h265转码h264格式并上传阿里云oss
开发环境 gin+gorm+ubuntu20.04 go版本1.20 ffmpeg为6.1
ffmpeg 安装可参考Ubuntu20.04安装ffmpeg(解决h265转码h264而安装)-CSDN博客
- type VideoResponse struct {
- Size int64 `json:"size"`
- Path string `json:"path"`
- FullPath string `json:"full_path"`
- Name string `json:"name"`
- Type string `json:"type"`
- }
-
- const paths = "static/uploadfile/"
-
- type Video struct {
- api.Api
- }
-
- setOnlinePath 设置上传路径
- //func setOnlinePath(c *gin.Context) string {
- // shopUuid := c.GetHeader(mzl_shop.ShopUuidKey)
- // onlinePath := config.ApplicationConfig.Mode + "/" + "shopUuid_" + shopUuid + "/"
- // return onlinePath
- //}
-
- // UploadVideo 上传视频
- // @Summary 上传视频
- // @Description 获取JSON
- // @Tags 公共接口
- // @Accept multipart/form-data
- // @Param file formData file true "file"
- // @Param fileName formData file true "fileName"
- // @Success 200 {string} string "{"code": 200, "message": "添加成功"}"
- // @Success 200 {string} string "{"code": -1, "message": "添加失败"}"
- // @Router /api/v1/public/UploadVideo [post]
- // @Security Bearer
- func (e Video) UploadVideo(c *gin.Context) {
- e.MakeContext(c)
- if e.GetShopUuid() == "" {
- e.Error(200, errors.New(""), "商户号不能为空")
- return
- }
- // 获取文件
- files, err := c.FormFile("file")
- if err != nil {
- e.Error(200, errors.New(""), "视频文件不能为空")
- return
- }
- fileName := c.PostForm("fileName")
- if fileName == "" {
- guid := uuid.New().String()
- fileName = guid + utils.GetExt(files.Filename)
- }
-
- err = utils.IsNotExistMkDir(path)
- if err != nil {
- e.Error(500, errors.New(""), "初始化文件路径失败")
- }
- singleFile := paths + fileName
- //保存文件
- _ = c.SaveUploadedFile(files, singleFile)
- fileType, _ := utils.GetType(singleFile)
- fileResponse := VideoResponse{
- Size: pkg.GetFileSize(singleFile),
- Path: singleFile,
- //FullPath: urlPerfix + singleFile,
- FullPath: singleFile,
- Name: fileName,
- Type: fileType,
- }
- resp, err := e.GetOssoOperate(c, fileResponse)
- if err != nil {
- e.Error(200, errors.New(""), "视频上传失败")
- return
- }
- e.OK(resp, "视频上传成功")
- }
-
- // video 操作
- func (e Video) GetOssoOperate(c *gin.Context, fileResponse VideoResponse) (resp dto.UploadCallbackResp, err error) {
- rq := dto.UploadCallbackReq{}
- _ = c.ShouldBind(&rq)
- err = e.MakeContext(c).Errors
- if err != nil {
- // 处理错误
- e.Logger.Error(err)
- e.Error(500, err, err.Error())
- return
- }
- //一定要绝对路径 不然找不到文件
- filePrefix := "/www/wwwroot/xxxxx/uploadfile" //输入
- fileOutPrefix := "/www/wwwroot/xxxxx/uploadfile/out_file" //输出
- filePath := "/" + fileResponse.Name
- fileName := filePrefix + filePath
- codec := checkVideoCodec(fileName)
- switch codec {
- case "h265":
- tempFilePath := fileOutPrefix + filePath
- err = convertVideoCodec(fileName, tempFilePath, "libx264")
- if err != nil {
- log.Println("输出失败:%s", err)
- return
- }
- // 替换原文件(并删除输出文件)
- err = os.Rename(tempFilePath, fileName)
- if err != nil {
- log.Println("替换原文件失败:%s", err)
- return
- }
- }
- // 上传到对象存储
- oxsStore := file_store.OXS{
- Endpoint: config.OssConfig.Endpoint,
- AccessKeyID: config.OssConfig.AccessKeyId,
- AccessKeySecret: config.OssConfig.AccessKeySecret,
- BucketName: config.OssConfig.BucketName,
- }
- var oxs = oxsStore.Setup(file_store.AliYunOSS)
- ossFileName := config.ApplicationConfig.Mode + "/shopUuid_" + e.GetShopUuid() + filePath
- err = oxs.UpLoad(ossFileName, fileName)
- if err != nil {
- fmt.Println("err::", err)
- }
- // 删除本地文件
- err = os.Remove(fileResponse.Path)
- if err != nil {
- log.Println("删除文件 Error:", err)
- return
- }
-
- // 敏感过滤
- req := dto2.SafetyReq{}
- rq.MimeType = fileResponse.Type
- //oss文件地址
- rq.Filename = "xxxxxx/" + ossFileName
- resp.Data = rq
- greenSer := green.GreenService{
- Endpoint: config.GreenConfig.Endpoint,
- Region: config.GreenConfig.Region,
- AccessKeyId: config.GreenConfig.AccessKeyId,
- AccessKeySecret: config.GreenConfig.AccessKeySecret,
- }
- if strings.Contains(fileResponse.Type, "video/mp4") {
- req.Type = dto2.GreenTypeVideo
- req.Content = rq.Filename
- req.Level = 70
- req.Num = 5
- req.Offset = 2
- } else {
- e.Logger.Error("MimeType:" + rq.MimeType)
- e.OK(resp, "回调成功")
- return
- }
- res, err := greenSer.InitHandle(&req)
- if err != nil {
- e.Logger.Error(err)
- return
- }
- if res == nil {
- e.Logger.Error("res is nil")
- e.OK(resp, "回调成功")
- return
- }
- // 存在敏感
- if res.Confidence == 1 {
- // 删除资源
- err = ossObj().DeleteObject(ossFileName)
- if err != nil {
- // 处理错误
- e.Logger.Error(err)
- }
- // 设置返回
- resp.Msg = res.Msg
- resp.Code = res.Confidence
- e.OK(resp, resp.Msg)
- return
- }
- return
- }

调用用ffmpeg命令判断视频格式&转码为h264封装得操作方法
- // 检查视频编码格式
- func checkVideoCodec(filePath string) string {
- _, stderr, err := executeFFmpegCommand("-i", filePath, "-hide_banner", "-f", "null", "-")
- if err != nil {
- fmt.Printf("Error executing command: %v\n", err)
- fmt.Println("ffmpeg output:", stderr)
- return ""
- }
- if strings.Contains(stderr, "hevc") || strings.Contains(stderr, "h265") || strings.Contains(stderr, "mpeg") || strings.Contains(stderr, "av1") || strings.Contains(stderr, "Copy") {
- return "h265"
- } else if strings.Contains(stderr, "avc1") || strings.Contains(stderr, "h264") {
- return "h264"
- }
-
- return "unknown"
- }
-
- // 转换视频编码格式
- func convertVideoCodec(filePath, outputPath, codec string) error {
- // 调整转码参数,例如使用多线程和更快的预设
- args := []string{"-i", filePath, "-vcodec", codec, "-preset", "ultrafast", "-threads", "0", outputPath} //快 但是视频会变大
- //args := []string{"-i", filePath, "-vcodec", codec, outputPath} //慢 但是时间久
- //args := []string{"-i", filePath, "-vcodec", codec, "-preset", "veryfast", "-threads", "0", outputPath}
- _, stderr, err := executeFFmpegCommand(args...)
- if err != nil {
- fmt.Printf("Command finished with error: %v\n", err)
- fmt.Printf("ffmpeg error output: %s\n", stderr)
- return err
- }
- return nil
- }
-
- // 执行ffmpeg命令并返回输出
- func executeFFmpegCommand(args ...string) (string, string, error) {
- cmd := exec.Command("ffmpeg", args...)
- var out bytes.Buffer
- var stderr bytes.Buffer
- cmd.Stdout = &out
- cmd.Stderr = &stderr
- err := cmd.Run()
- return out.String(), stderr.String(), err
- }

apifox 传入file和filename
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。