美文网首页JAVA微信小程序码农的世界
「小程序JAVA实战」小程序视频封面处理(48)

「小程序JAVA实战」小程序视频封面处理(48)

作者: IT人故事会 | 来源:发表于2019-01-05 00:22 被阅读3次

    原创文章,欢迎转载。转载请注明:转载自IT人故事会,谢谢!
    原文链接地址:「小程序JAVA实战」小程序视频封面处理(48)

    截图这块,在微信小程序工具上,上传视频是有返回截图的,但是万万没想到在手机端是不能用的。所以还得借助ffmpge工具来完成,方式很简单。源码:https://github.com/limingios/wxProgram.git 中wx-springboot 和 No.15

    例子

    注意建议使用jpg的格式,png的格式比较大

    ffmpeg -y -i a.mp4 -ss 00:00:01  -vframes 1 new.jpg
    

    java代码工具类编写

    spring boot common中加入FetchVideoCover

    package com.idig8.utils;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.util.List;
    
    /**
     * 
     * @Description: 获取视频的信息
     */
    public class FetchVideoCover {
        // 视频路径
        private String ffmpegEXE;
    
        public void getCover(String videoInputPath, String coverOutputPath) throws IOException, InterruptedException {
    //      ffmpeg.exe -ss 00:00:01 -i spring.mp4 -vframes 1 bb.jpg
            List<String> command = new java.util.ArrayList<String>();
            command.add(ffmpegEXE);
            
            // 指定截取第1秒
            command.add("-ss");
            command.add("00:00:01");
                    
            command.add("-y");
            command.add("-i");
            command.add(videoInputPath);
            
            command.add("-vframes");
            command.add("1");
            
            command.add(coverOutputPath);
            
            for (String c : command) {
                System.out.print(c + " ");
            }
            
            ProcessBuilder builder = new ProcessBuilder(command);
            Process process = builder.start();
            
            InputStream errorStream = process.getErrorStream();
            InputStreamReader inputStreamReader = new InputStreamReader(errorStream);
            BufferedReader br = new BufferedReader(inputStreamReader);
            
            String line = "";
            while ( (line = br.readLine()) != null ) {
            }
            
            if (br != null) {
                br.close();
            }
            if (inputStreamReader != null) {
                inputStreamReader.close();
            }
            if (errorStream != null) {
                errorStream.close();
            }
        }
    
        public String getFfmpegEXE() {
            return ffmpegEXE;
        }
    
        public void setFfmpegEXE(String ffmpegEXE) {
            this.ffmpegEXE = ffmpegEXE;
        }
    
        public FetchVideoCover() {
            super();
        }
    
        public FetchVideoCover(String ffmpegEXE) {
            this.ffmpegEXE = ffmpegEXE;
        }
        
        public static void main(String[] args) {
            // 获取视频信息。
            FetchVideoCover videoInfo = new FetchVideoCover("c:\\ffmpeg\\bin\\ffmpeg.exe");
            try {
                videoInfo.getCover("c:\\北京北京.avi","c:\\北京.jpg");
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    功能实现

    视频转化完毕后,完成视频截图的转化,并保存在数据库中

    package com.idig8.controller;
    
    import java.io.File;
    import java.util.Date;
    import java.util.UUID;
    
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.multipart.MultipartFile;
    
    import com.idig8.pojo.Bgm;
    import com.idig8.pojo.Videos;
    import com.idig8.service.BgmService;
    import com.idig8.service.VideoService;
    import com.idig8.utils.FetchVideoCover;
    import com.idig8.utils.JSONResult;
    import com.idig8.utils.MergeVideoMp3;
    import com.idig8.utils.enums.VideoStatusEnum;
    import com.idig8.utils.file.FileUtil;
    
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiImplicitParam;
    import io.swagger.annotations.ApiImplicitParams;
    import io.swagger.annotations.ApiOperation;
    import io.swagger.annotations.ApiParam;
    
    
    @RestController
    @Api(value="视频相关业务的接口", tags= {"视频相关业务的controller"})
    @RequestMapping("/video")
    public class VideoController extends BasicController {
        
        @Autowired
        private BgmService bgmService;
        
        @Autowired
        private VideoService videosService;
        
        @Value("${server.file.path}")
        private String fileSpace;
        
        @Value("${server.ffmpeg.path}")
        private String ffmpegexe;
        
        
        @ApiOperation(value="上传视频", notes="上传视频的接口")
        @ApiImplicitParams({
            @ApiImplicitParam(name="userId", value="用户id", required=true, 
                    dataType="String", paramType="form"),
            @ApiImplicitParam(name="bgmId", value="背景音乐id", required=false, 
                    dataType="String", paramType="form"),
            @ApiImplicitParam(name="videoSeconds", value="背景音乐播放长度", required=true, 
                    dataType="String", paramType="form"),
            @ApiImplicitParam(name="videoWidth", value="视频宽度", required=true, 
                    dataType="String", paramType="form"),
            @ApiImplicitParam(name="videoHeight", value="视频高度", required=true, 
                    dataType="String", paramType="form"),
            @ApiImplicitParam(name="desc", value="视频描述", required=false, 
                    dataType="String", paramType="form")
        })
        @PostMapping(value="/upload", headers="content-type=multipart/form-data")
        public JSONResult upload(String userId, 
                    String bgmId, double videoSeconds, 
                    int videoWidth, int videoHeight,
                    String desc,
                    @ApiParam(value="短视频", required=true)
                    MultipartFile file) throws Exception {
            
            if (StringUtils.isBlank(userId)) {
                return JSONResult.errorMsg("用户id不能为空...");
            }
            // 文件保存的命名空间
            String fileName = file.getOriginalFilename();
            // 保存到数据库中的相对路径
            String path = "";
            String videOutPath = "";
            String ImagePath = "";
            try {
                 path = FileUtil.uploadFile(file.getBytes(), fileSpace, fileName);
                } catch (Exception e) {
                    e.getStackTrace();
                       return JSONResult.errorMsg(e.getMessage());
                }                
             
        
            if(StringUtils.isNotBlank(bgmId)){
                Bgm bgm = bgmService.queryBgmById(bgmId);
                String mp3BgmPath = fileSpace + bgm.getPath();
                MergeVideoMp3 mergeVideoMp3 = new MergeVideoMp3(ffmpegexe);
                String videOutPathName = UUID.randomUUID().toString()+".mp4";
                File targetFile = new File(fileSpace + userId);
                if (!targetFile.exists()) {
                    targetFile.mkdirs();
                }
                videOutPath = "/"+userId+"/"+videOutPathName;
                String videoInput = fileSpace +path;
                mergeVideoMp3.convertor(videoInput, mp3BgmPath, videoSeconds, fileSpace +videOutPath);
                
            }else{
                videOutPath = path;
                
            }
            
            ImagePath =  "/"+userId+"/"+UUID.randomUUID().toString()+".jpg";;
            FetchVideoCover fetchVideoCover = new FetchVideoCover(ffmpegexe);
            fetchVideoCover.getCover(fileSpace +videOutPath, fileSpace +ImagePath);
            
            
            Videos videos = new Videos();
            videos.setAudioId(bgmId);
            videos.setCreateTime(new Date());
            videos.setVideoDesc(desc);
            videos.setId(UUID.randomUUID().toString());
            videos.setUserId(userId);
            videos.setVideoHeight(videoHeight);
            videos.setVideoWidth(videoWidth);
            videos.setVideoPath(videOutPath);
            videos.setCoverPath(ImagePath);
            videos.setStatus(VideoStatusEnum.SUCCESS.value);
            videosService.saveVideo(videos);
                     
            return JSONResult.ok(path);
            
        }
    }
    

    小程序中的chooseBgm.js 增加友好提示

    const app = getApp()
    
    Page({
        data: {
          poster: 'http://y.gtimg.cn/music/photo_new/T002R300x300M000003rsKF44GyaSk.jpg?max_age=2592000',
          name: '此时此刻',
          author: '许巍',
          src: 'http://ws.stream.qqmusic.qq.com/M500001VfvsJ21xFqb.mp3?guid=ffffffff82def4af4b12b3cd9337d5e7&uin=346897220&vkey=6292F51E1E384E06DCBDC9AB7C49FD713D632D313AC4858BACB8DDD29067D3C601481D36E62053BF8DFEAF74C0A5CCFADD6471160CAF3E6A&fromtag=46',
          serverUrl:"",
          videoParams:{}
        },
        onLoad:function(params){
          var me = this;
          console.log(params);
         
          me.setData({
            videoParams:params
          })
    
          wx.showLoading({
            title: '请等待...',
          });
          var serverUrl = app.serverUrl;
          // 调用后端
          wx.request({
            url: serverUrl + '/bgm/list',
            method: "POST",
            header: {
              'content-type': 'application/json', // 默认值
            },
            success: function (res) {
              console.log(res.data);
              wx.hideLoading();
              if (res.data.status == 200) {
                var bgmList = res.data.data;
                me.setData({
                  bgmList: bgmList,
                  serverUrl: serverUrl
                });
              } else if (res.data.status == 502) {
                wx.showToast({
                  title: res.data.msg,
                  duration: 2000,
                  icon: "none",
                  success: function () {
                    wx.redirectTo({
                      url: '../userLogin/login',
                    })
                  }
                });
              }
            }
          })
        },
      upload:function(e){
        var me = this;
        var datasParams = me.data.videoParams;
        var bgmId = e.detail.value.bgmId;
        var desc = e.detail.value.desc;
        console.log("bgmId:"+bgmId);
        console.log("desc:" + desc);
        var tempDuration = datasParams.tempDuration;
        var tempHeight = datasParams.tempHeight;
        var tempWidth = datasParams.tempWidth;
        var tempSize = datasParams.tempSize;
        var tempFilePath = datasParams.tempFilePath;
        var thumbTempFilePath = datasParams.thumbTempFilePath;
        var userId = app.userInfo.id;
    
    
        wx.showLoading({
          title: '请等待...',
        });
        var serverUrl = app.serverUrl;
        // 调用后端
       wx.uploadFile({
         url: serverUrl + '/video/upload',
         filePath: tempFilePath,
         formData:{
           userId: userId,
           bgmId: bgmId,
           videoSeconds: tempDuration,
           videoWidth: tempWidth,
           videoHeight: tempHeight,
           desc: desc,
         },
         name: 'file',
         success:function(res){
          console.log(res);
           var status = JSON.parse(res.data).status;
           debugger;
           wx.hideLoading();
           if (status == 200) {
             wx.showToast({
               title: "上传成功~!",
               icon: 'none',
               duration: 3000
             })
           } else if (status == 500) {
             wx.showToast({
               title: res.data.msg,
               icon: 'none',
               duration: 3000
             })
           }
         }
         
       })
      }
    })
    
    
    

    PS:截图也是通过ffmpge的方式,小程序工具的坑很多,官网都没介绍返回截图,但是小程序工具就返回截图了,这就是个坑。

    相关文章

      网友评论

        本文标题:「小程序JAVA实战」小程序视频封面处理(48)

        本文链接:https://www.haomeiwen.com/subject/hvsqnftx.html