zoukankan      html  css  js  c++  java
  • 微信小程序_(校园视)开发上传视频业务

      微信小程序_(校园视)  开发用户注册登陆  传送门 

      微信小程序_(校园视)  开发上传视频业务  传送门 

      微信小程序_(校园视)  开发视频的展示页-上  传送门 

      微信小程序_(校园视)  开发视频的展示页-下  传送门 

    用户上传视频

      用户选择视频->打开选择bgm->选择/不选择bgm输入视频的描述->Controller上传视频->保存视频的截图->用户是否选择bgm

      用户没有选择bgm可以直接保存视频,用户选择bgm将合并原视频和bgm新的视频并且保存

      用户点击上传视频触发uploadVideo方法

          <button size='mini' class='primary' bindtap='uploadVideo'> 上传作品</button>
      uploadVideo:function(){
        var me =this;
        wx.chooseVideo({
          sourceType: ['album'],
          success(res) {
            console.log(res);
          }
        })
      }

    <view>
    
      <view class='container'>
          <image src="{{faceUrl}}" class="face" bindtap='changeFace'></image>
    
        <label class='nickname'>{{nickname}}</label>
            
          <button size='mini' class='primary' bindtap='uploadVideo'> 上传作品</button>
          <button size='mini' type='' class='logout' bindtap='logout'>注销</button>
    
        <view class='container-row'>
          <label class='info-items'>{{fansCounts}} 粉丝</label>
          <label class='info-items'>{{followCounts}} 关注</label>
          <label class='info-items'>{{receiveLikeCounts}} 获赞</label>
        </view>
      </view>
    
    </view>
    
    <view class="line"></view>
    mine.wxml
    var videoUtil = require('../../utils/videoUtil.js')
    
    const app = getApp()
    
    Page({
      data: {
        faceUrl: "../resource/images/noneface.png",
      },
    
      onLoad: function (params) {
          var me = this;
          var user = app.userInfo;
        wx.showLoading({
          title: '请等待...',
        });
        // 调用后端
        var serverUrl = app.serverUrl;
        wx.request({
          url: serverUrl + '/user/query?userId='+user.id,
          method: "POST",
          header: {
            'content-type': 'application/json' // 默认值
          },
          success: function (res) {
            console.log(res.data);
            wx.hideLoading();
            if (res.data.status == 200) {
              var userInfo= res.data.data;
              var faceUrl = "../resource/images/noneface.png";
              if (userInfo.faceImage != null && userInfo.faceImage != '' && userInfo.faceImage!=undefined){
                faceUrl = serverUrl + userInfo.faceImage;
              }
    
              me.setData({
                faceUrl: faceUrl,
                fansCounts: userInfo.fansCounts,
                followCounts: userInfo.followCounts,
                receiveLikeCounts: userInfo.receiveLikeCounts,
                nickname: userInfo.nickname
              });
            } 
          }
        })
      },
    
      logout:function(params){
        var user = app.userInfo;
        var serverUrl = app.serverUrl;
        wx.showLoading({
          title: '请等待...',
        });
        // 调用后端
        wx.request({
          url: serverUrl + '/logout?userId='+user.id,
          method: "POST",
          header: {
            'content-type': 'application/json' // 默认值
          },
          success: function (res) {
            console.log(res.data);
            wx.hideLoading();
            if (res.data.status == 200) {
              // 注销成功 
              wx.showToast({
                 title: '注销成功',
                 icon: 'success',
                 duration: 2000
                });
              //清除全局用户对象
              app.userInfo = null;
              //页面跳转
              wx.navigateTo({
                url: '../userLogin/login',
              })
            }
          }
        })
      },
    
      changeFace:function(){
        var me = this;
        wx.chooseImage({
          count: 1,
          sizeType: ['compressed'],
          sourceType: ['album'],
          success:function(res) {
            var tempFilePaths = res.tempFilePaths;
            console.log(tempFilePaths);
    
            wx.showLoading({
              title: '上传中...',
            })
    
            var serverUrl = app.serverUrl;
            wx.uploadFile({
              url: serverUrl+'/user/uploadFace?userId='+app.userInfo.id, 
              filePath: tempFilePaths[0],
              name: 'file',
              header: {
                'content-type': 'application/json' // 默认值
              },
              success: function (res) {
                var data = JSON.parse(res.data);
                console.log(data);
                wx.hideLoading();
                if(data.status == 200){
                  wx.showToast({
                    title: '上传成功',
                    icon: "success"
                  });
    
                  var imageUrl = data.data;
                  me.setData({
                    faceUrl: serverUrl+imageUrl
                  });
    
                } else if (data.status == 500){
                  wx.showToast({
                    title: data.msg
                  });
                }
              }
            })
    
          }
        })
      },
    
      uploadVideo:function(){
        var me =this;
        wx.chooseVideo({
          sourceType: ['album'],
          success(res) {
            console.log(res);
          }
        })
      }
    
    })
    mine.js

    背景BGM音乐

      选择背景音乐页面

    <view>
        <form bindsubmit='upload'>
    
            <view class="inputView">
                <label class="loginLabel">视频描述:</label>
                <input name="desc" class="inputText" placeholder="说点什么吧" />
            </view>
    
            <!-- 提交 -->
            <button class="submitBtn" type="primary" form-type='submit'>上传视频</button>
            
            <button class="gobackBtn" type="warn" form-type='reset'>重置</button>
        </form>
    </view>
    chooseBgm.wxml
    const app = getApp()
    
    Page({
        data: {
          
        },
    
        onLoad: function (params) {      
        },
    
    })
    chooseBgm.js

      添加音乐模块样式

        <radio-group name="bgm">
    
    <view class='container'>
      <audio poster="{{poster}}"  name="{{name}}"  author="{{author}}" src="{{src}}"  id="myAudio"  controls  loop></audio>
      <radio style='margin-top:20px;' value=''></radio>
    </view>
    
        </radio-group>

    <view>
        <form bindsubmit='upload'>
        
        <radio-group name="bgm">
    
    <view class='container'>
      <audio poster="{{poster}}"  name="{{name}}"  author="{{author}}" src="{{src}}"  id="myAudio"  controls  loop></audio>
      <radio style='margin-top:20px;' value=''></radio>
    </view>
    
        </radio-group>
    
            <view class="inputView">
                <label class="loginLabel">视频描述:</label>
                <input name="desc" class="inputText" placeholder="说点什么吧" />
            </view>
    
            <!-- 提交 -->
            <button class="submitBtn" type="primary" form-type='submit'>上传视频</button>
            
            <button class="gobackBtn" type="warn" form-type='reset'>重置</button>
        </form>
    </view>
    chooseBgm.wxml
    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',
      },
    
        onLoad: function (params) {      
        },
    
    })
    chooseBgm.js

       数据库中单独添加一条数据

      

      音乐文件放在虚拟路径F:imooc-video-garygm下

      

      添加查询Bgm的Controller层

    @RestController
    @Api(value="背景音乐业务的接口",tags= {"背景音乐业务的controller"})
    @RequestMapping("/bgm")
    public class BgmController {
        
        @Autowired
        private BgmService bgmService;
        
        @ApiOperation(value="获取背景音乐列表",notes="获取背景音乐列表的接口")
        @PostMapping("/list")
        public IMoocJSONResult list() {
            return IMoocJSONResult.ok(bgmService.queryBgmList());
        }
        
    }

       添加查询Bgm的Service

        @Transactional(propagation = Propagation.SUPPORTS)
        @Override
        public List<Bgm> queryBgmList() {
            
            return bgmMapper.selectAll();
        }

       

    package com.imooc.controller;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.imooc.service.BgmService;
    import com.imooc.utils.IMoocJSONResult;
    
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;
    
    @RestController
    @Api(value="背景音乐业务的接口",tags= {"背景音乐业务的controller"})
    @RequestMapping("/bgm")
    public class BgmController {
        
        @Autowired
        private BgmService bgmService;
        
        @ApiOperation(value="获取背景音乐列表",notes="获取背景音乐列表的接口")
        @PostMapping("/list")
        public IMoocJSONResult list() {
            return IMoocJSONResult.ok(bgmService.queryBgmList());
        }
        
    }
    BgmController.java
    package com.imooc.service;
    
    import java.util.List;
    
    import com.imooc.pojo.Bgm;
    import com.imooc.pojo.Users;
    
    public interface BgmService {
    
        //查询背景音乐列表
        public List<Bgm> queryBgmList();
        
    
        
    }
    BgmService.java
    package com.imooc.server.impl;
    
    import java.util.List;
    
    import org.n3r.idworker.Sid;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    
    import com.imooc.mapper.BgmMapper;
    import com.imooc.mapper.UsersMapper;
    import com.imooc.pojo.Bgm;
    import com.imooc.pojo.Users;
    import com.imooc.service.BgmService;
    import com.imooc.service.UserService;
    
    import tk.mybatis.mapper.entity.Example;
    import tk.mybatis.mapper.entity.Example.Criteria;
    
    @Service
    public class BgmServiceImpl implements BgmService {
    
        @Autowired
        private BgmMapper bgmMapper;
        
        @Autowired
        private Sid sid;
        
        @Transactional(propagation = Propagation.SUPPORTS)
        @Override
        public List<Bgm> queryBgmList() {
            
            return bgmMapper.selectAll();
        }
    
        
    }
    BgmServiceImpl.java

     微信小程序bgm页面联调获取背景音乐列表

      chooseBgm.wxml中通过使用block循环获得数据库中的bgm

    <block wx:for="{{bgmList}}">
      <view class='container'>
      <audio   name="{{item.name}}"  author="{{item.author}}" src="{{serverUrl}}{{item.path}}"  id="myAudio"  controls  loop></audio>
      <radio style='margin-top:20px;' value='{{item.id}}'></radio>
      </view>
      </block>

      为防止用户歌曲名字输入时过长,可以在<audio>组件中通过style='300px'去进行歌曲名长度控制 

      <audio   name="{{item.name}}"  author="{{item.author}}" src="{{serverUrl}}{{item.path}}" style='300px' id="myAudio"  controls  loop></audio>

      chooseBgm.js中通过编写onLoad函数去对后台发起bgm/list请求

    onLoad: function (params) { 
          var me = this;
    
          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
                });
              }
            }
          })
    
        },

    <view>
        <form bindsubmit='upload'>
    
        <radio-group name="bgm">
    
      <block wx:for="{{bgmList}}">
      <view class='container'>
      <audio   name="{{item.name}}"  author="{{item.author}}" src="{{serverUrl}}{{item.path}}" style='300px' id="myAudio"  controls  loop></audio>
      <radio style='margin-top:20px;' value='{{item.id}}'></radio>
      </view>
      </block>
        </radio-group>
    
    
            <view class="inputView">
                <label class="loginLabel">视频描述:</label>
                <input name="desc" class="inputText" placeholder="说点什么吧" />
            </view>
    
            <!-- 提交 -->
            <button class="submitBtn" type="primary" form-type='submit'>上传视频</button>
            
            <button class="gobackBtn" type="warn" form-type='reset'>重置</button>
        </form>
    </view>
    chooseBgm.wxml
    const app = getApp()
    
    Page({
        data: {
        bgmList:[],
          serverUrl:"",
        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',
      },
    
        onLoad: function (params) { 
          var me = this;
    
          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
                });
              }
            }
          })
    
        },
    
    })
    chooseBgm.js

     开发上传短视频接口

       短视频上传接口类似上传头像

    @PostMapping(value="/upload",headers="content-type=multipart/form-data")
        public IMoocJSONResult uploadFace(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 IMoocJSONResult.errorMsg("用户id不能为空...");
                }
            
                //文件保存命名空间
                String fileSpace = "F:/imooc-video-gary";
                //保存到数据库中的相对路径
                String uploadPathDB = "/" + userId + "/video";
                
                FileOutputStream fileOutputStream = null;
                InputStream inputStream = null;
                
                try {
                    if( file != null ) {
    
                        
                        String fileName = file.getOriginalFilename();
                        if(StringUtils.isNoneBlank(fileName)) {
                            //文件上传的最终保存路径
                            String finalVideoPath = fileSpace + uploadPathDB + "/" + fileName;
                            //设置数据库保存的路径
                            uploadPathDB += ("/" + fileName);
                            
                            File outFile = new File(finalVideoPath);
                            if(outFile.getParentFile()!=null || !outFile.getParentFile().isDirectory()) {
                                //创建父文件夹
                                outFile.getParentFile().mkdirs();
                            }
                            
                            fileOutputStream = new FileOutputStream(outFile);
                            inputStream = file.getInputStream();
                            IOUtils.copy(inputStream, fileOutputStream);
                        }
                        
                    }else {
                        return IMoocJSONResult.errorMsg("上传出错...");
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    return IMoocJSONResult.errorMsg("上传出错...");
                }finally {
                    if(fileOutputStream != null) {
                        fileOutputStream.flush();
                        fileOutputStream.close();
                    }
                }
                
                return IMoocJSONResult.ok();
        }

    package com.imooc.controller;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    
    import org.apache.commons.lang3.StringUtils;
    import org.apache.tomcat.util.http.fileupload.IOUtils;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.multipart.MultipartFile;
    
    import com.imooc.pojo.Users;
    import com.imooc.utils.IMoocJSONResult;
    
    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 {
        
        @ApiOperation(value="用户视频", notes="上传视频的接口")
        @ApiImplicitParams({
            @ApiImplicitParam(name="userId",value="用户id",required=true,
                    dataType="String" ,paramType="query"),
            @ApiImplicitParam(name="bgmId",value="背景音乐id",required=false,
                    dataType="String" ,paramType="query"),
            @ApiImplicitParam(name="videoSeconds",value="背景音乐播放长度",required=true,
                    dataType="String" ,paramType="query"),
            @ApiImplicitParam(name="videoWidth",value="视频的宽度",required=true,
                    dataType="String" ,paramType="query"),
            @ApiImplicitParam(name="videoHeight",value="视频的高度",required=true,
                    dataType="String" ,paramType="query"),
            @ApiImplicitParam(name="desc",value="视频的描述",required=false,
                    dataType="String" ,paramType="query")
        })
    
        @PostMapping(value="/upload",headers="content-type=multipart/form-data")
        public IMoocJSONResult uploadFace(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 IMoocJSONResult.errorMsg("用户id不能为空...");
                }
            
                //文件保存命名空间
                String fileSpace = "F:/imooc-video-gary";
                //保存到数据库中的相对路径
                String uploadPathDB = "/" + userId + "/video";
                
                FileOutputStream fileOutputStream = null;
                InputStream inputStream = null;
                
                try {
                    if( file != null ) {
    
                        
                        String fileName = file.getOriginalFilename();
                        if(StringUtils.isNoneBlank(fileName)) {
                            //文件上传的最终保存路径
                            String finalVideoPath = fileSpace + uploadPathDB + "/" + fileName;
                            //设置数据库保存的路径
                            uploadPathDB += ("/" + fileName);
                            
                            File outFile = new File(finalVideoPath);
                            if(outFile.getParentFile()!=null || !outFile.getParentFile().isDirectory()) {
                                //创建父文件夹
                                outFile.getParentFile().mkdirs();
                            }
                            
                            fileOutputStream = new FileOutputStream(outFile);
                            inputStream = file.getInputStream();
                            IOUtils.copy(inputStream, fileOutputStream);
                        }
                        
                    }else {
                        return IMoocJSONResult.errorMsg("上传出错...");
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    return IMoocJSONResult.errorMsg("上传出错...");
                }finally {
                    if(fileOutputStream != null) {
                        fileOutputStream.flush();
                        fileOutputStream.close();
                    }
                }
                
                return IMoocJSONResult.ok();
        }
        
    }
    VideoController.java

      小程序上传视频

      视频从mine页面传参到chooseBgm页面

     uploadVideo:function(){
        var me =this;
        wx.chooseVideo({
          sourceType: ['album'],
          success(res) {
            console.log(res);
            
            var duration = res.duration;
            var tmpheight = res.height;
            var tmpwidth = res.width;
            var tmpVideoUrl = res.tempFilePath;
            var tmpCoverUrl = res.thumbTempFilePath;
    
            if(duration>300){
              wx.showToast({
                title: '视频长度不能超过5分钟...',
                icon:"none",
                duration:2500
              })
            } else if(duration<3){
              wx.showToast({
                title: '视频长度太短,请上传超过3秒的视频...',
                icon: "none",
                duration: 2500
              })
            }else{
              //打开选择bgm页面
              wx.navigateTo({
                url: '../chooseBgm/chooseBgm?duration=' + duration
                  + "&tmpheight=" + tmpheight
                  + "&tmpwidth=" + tmpwidth
                  + "&tmpVideoUrl=" + tmpVideoUrl
                  + "&tmpCoverUrl=" + tmpCoverUrl
                ,
              })
            }
    
          }
        })
      }

      chooseBgm页面通过upload函数将视频上传缓存到本地

     upload:function(e){
        var me = this;
    
        var bgmId = e.detail.value.bgmId;
        var desc = e.detail.value.desc;
    
        console.log("bgmId:"+ bgmId);
        console.log("desc:" + desc);
    
        var duration = me.data.videoParams.duration;
        var tmpheight = me.data.videoParams.tmpheight;
        var tmpwidth = me.data.videoParams.tmpwidth;
        var tmpVideoUrl = me.data.videoParams.tmpVideoUrl;
        var tmpCoverUrl = me.data.videoParams.tmpCoverUrl;
      
        //上传短视频
        wx.showLoading({
          title: '上传中...',
        })
    
        var serverUrl = app.serverUrl;
        wx.uploadFile({
          url: serverUrl + '/video/upload',
          formData:{
            userId: app.userInfo.id,
            bgmId:bgmId,
            desc: desc,
            videoSeconds: duration,
            videoWidth: tmpheight,
            videoHeight: tmpwidth,
          },
          filePath: tmpVideoUrl,
          name: 'file',
          header: {
            'content-type': 'application/json' // 默认值
          },
          success: function (res) {
            var data = JSON.parse(res.data);
            console.log(res);
            wx.hideLoading();
            if (data.status == 200) {
              wx.showToast({
                title: '上传成功',
                icon: "success"
              });
            }
          }
        })
    
      }

    <view>
        <form bindsubmit='upload'>
    
        <radio-group name="bgmId">
    
      <block wx:for="{{bgmList}}" wx:key="">
      <view class='container'>
      <audio   name="{{item.name}}"  author="{{item.author}}" src="{{serverUrl}}{{item.path}}" style='300px' id="myAudio"  controls  loop></audio>
      <radio style='margin-top:20px;' value='{{item.id}}'></radio>
      </view>
      </block>
        </radio-group>
    
    
            <view class="inputView">
                <label class="loginLabel">视频描述:</label>
                <input name="desc" class="inputText" placeholder="说点什么吧" />
            </view>
    
            <!-- 提交 -->
            <button class="submitBtn" type="primary" form-type='submit'>上传视频</button>
            
            <button class="gobackBtn" type="warn" form-type='reset'>重置</button>
        </form>
    </view>
    chooseBgm.xml
    const app = getApp()
    
    Page({
        data: {
        bgmList:[],
        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
                });
              }
            }
          })
    
        },
    
      upload:function(e){
        var me = this;
    
        var bgmId = e.detail.value.bgmId;
        var desc = e.detail.value.desc;
    
        console.log("bgmId:"+ bgmId);
        console.log("desc:" + desc);
    
        var duration = me.data.videoParams.duration;
        var tmpheight = me.data.videoParams.tmpheight;
        var tmpwidth = me.data.videoParams.tmpwidth;
        var tmpVideoUrl = me.data.videoParams.tmpVideoUrl;
        var tmpCoverUrl = me.data.videoParams.tmpCoverUrl;
      
        //上传短视频
        wx.showLoading({
          title: '上传中...',
        })
    
        var serverUrl = app.serverUrl;
        wx.uploadFile({
          url: serverUrl + '/video/upload',
          formData:{
            userId: app.userInfo.id,
            bgmId:bgmId,
            desc: desc,
            videoSeconds: duration,
            videoWidth: tmpheight,
            videoHeight: tmpwidth,
          },
          filePath: tmpVideoUrl,
          name: 'file',
          header: {
            'content-type': 'application/json' // 默认值
          },
          success: function (res) {
            var data = JSON.parse(res.data);
            console.log(res);
            wx.hideLoading();
            if (data.status == 200) {
              wx.showToast({
                title: '上传成功',
                icon: "success"
              });
            }
          }
        })
    
      }
    
    })
    chooseBgm.js
    var videoUtil = require('../../utils/videoUtil.js')
    
    const app = getApp()
    
    Page({
      data: {
        faceUrl: "../resource/images/noneface.png",
      },
    
      onLoad: function (params) {
          var me = this;
          var user = app.userInfo;
        wx.showLoading({
          title: '请等待...',
        });
        // 调用后端
        var serverUrl = app.serverUrl;
        wx.request({
          url: serverUrl + '/user/query?userId='+user.id,
          method: "POST",
          header: {
            'content-type': 'application/json' // 默认值
          },
          success: function (res) {
            console.log(res.data);
            wx.hideLoading();
            if (res.data.status == 200) {
              var userInfo= res.data.data;
              var faceUrl = "../resource/images/noneface.png";
              if (userInfo.faceImage != null && userInfo.faceImage != '' && userInfo.faceImage!=undefined){
                faceUrl = serverUrl + userInfo.faceImage;
              }
    
              me.setData({
                faceUrl: faceUrl,
                fansCounts: userInfo.fansCounts,
                followCounts: userInfo.followCounts,
                receiveLikeCounts: userInfo.receiveLikeCounts,
                nickname: userInfo.nickname
              });
            } 
          }
        })
      },
    
      logout:function(params){
        var user = app.userInfo;
        var serverUrl = app.serverUrl;
        wx.showLoading({
          title: '请等待...',
        });
        // 调用后端
        wx.request({
          url: serverUrl + '/logout?userId='+user.id,
          method: "POST",
          header: {
            'content-type': 'application/json' // 默认值
          },
          success: function (res) {
            console.log(res.data);
            wx.hideLoading();
            if (res.data.status == 200) {
              // 注销成功 
              wx.showToast({
                 title: '注销成功',
                 icon: 'success',
                 duration: 2000
                });
              //清除全局用户对象
              app.userInfo = null;
              //页面跳转
              wx.navigateTo({
                url: '../userLogin/login',
              })
            }
          }
        })
      },
    
      changeFace:function(){
        var me = this;
        wx.chooseImage({
          count: 1,
          sizeType: ['compressed'],
          sourceType: ['album'],
          success:function(res) {
            var tempFilePaths = res.tempFilePaths;
            console.log(tempFilePaths);
    
            wx.showLoading({
              title: '上传中...',
            })
    
            var serverUrl = app.serverUrl;
            wx.uploadFile({
              url: serverUrl+'/user/uploadFace?userId='+app.userInfo.id, 
              filePath: tempFilePaths[0],
              name: 'file',
              header: {
                'content-type': 'application/json' // 默认值
              },
              success: function (res) {
                var data = JSON.parse(res.data);
                console.log(data);
                wx.hideLoading();
                if(data.status == 200){
                  wx.showToast({
                    title: '上传成功',
                    icon: "success"
                  });
    
                  var imageUrl = data.data;
                  me.setData({
                    faceUrl: serverUrl+imageUrl
                  });
    
                } else if (data.status == 500){
                  wx.showToast({
                    title: data.msg
                  });
                }
              }
            })
    
          }
        })
      },
    
      uploadVideo:function(){
        var me =this;
        wx.chooseVideo({
          sourceType: ['album'],
          success(res) {
            console.log(res);
            
            var duration = res.duration;
            var tmpheight = res.height;
            var tmpwidth = res.width;
            var tmpVideoUrl = res.tempFilePath;
            var tmpCoverUrl = res.thumbTempFilePath;
    
            if(duration>300){
              wx.showToast({
                title: '视频长度不能超过5分钟...',
                icon:"none",
                duration:2500
              })
            } else if(duration<3){
              wx.showToast({
                title: '视频长度太短,请上传超过3秒的视频...',
                icon: "none",
                duration: 2500
              })
            }else{
              //打开选择bgm页面
              wx.navigateTo({
                url: '../chooseBgm/chooseBgm?duration=' + duration
                  + "&tmpheight=" + tmpheight
                  + "&tmpwidth=" + tmpwidth
                  + "&tmpVideoUrl=" + tmpVideoUrl
                  + "&tmpCoverUrl=" + tmpCoverUrl
                ,
              })
            }
    
          }
        })
      }
    
    })
    mine.js

    ffmpeg

      ffmpeg:视音频处理工具,跨平台的视音频处理解决方案

      视频转换命令

    $ ffmpeg -i input.mp4 output.avi

       

    Java于ffmpeg的结合

       在common层中创建FFMpegTest.java类,实现java于ffmpeg的结合

    package com.imooc.utils;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class FFMpegTest {
    
        private String ffmpegEXE;
        
        public FFMpegTest(String ffmpegEXE) {
            super();
            this.ffmpegEXE = ffmpegEXE;
        }
    
        public void convertor(String videoInputPath,String videoOutputPath) throws Exception{
            //$ ffmpeg -i input.mp4 output.avi
            List<String> command = new ArrayList<>();
            command.add(ffmpegEXE);
            command.add("-i");
            command.add(videoInputPath);
            command.add(videoOutputPath);
            
            for(String c:command) {
                System.out.print(c);
            }
            
            ProcessBuilder process = new ProcessBuilder(command);
            process.start();
        }
        
        public static void main(String[] args) {
            FFMpegTest ffmpeg = new FFMpegTest("F:\Garyffmpeg\ffmpeg\bin\ffmpeg.exe");
            try {
                ffmpeg.convertor("E:\19222\毕业生.mp4","E:\19222\毕.avi");
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
    }
    FFMpegTest.java

       可以看到转码格式的输出

      为了提高资源的利用率,可以在convertor()方法中提高流资源利用率

    public void convertor(String videoInputPath,String videoOutputPath) throws Exception{
            //$ ffmpeg -i input.mp4 output.avi
            List<String> command = new ArrayList<>();
            command.add(ffmpegEXE);
            command.add("-i");
            command.add(videoInputPath);
            command.add(videoOutputPath);
            
            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();
            }
            
        }
    package com.imooc.utils;
    
    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.util.ArrayList;
    import java.util.List;
    
    public class FFMpegTest {
    
        private String ffmpegEXE;
        
        public FFMpegTest(String ffmpegEXE) {
            super();
            this.ffmpegEXE = ffmpegEXE;
        }
    
        public void convertor(String videoInputPath,String videoOutputPath) throws Exception{
            //$ ffmpeg -i input.mp4 output.avi
            List<String> command = new ArrayList<>();
            command.add(ffmpegEXE);
            command.add("-i");
            command.add(videoInputPath);
            command.add(videoOutputPath);
            
            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 static void main(String[] args) {
            FFMpegTest ffmpeg = new FFMpegTest("F:\Garyffmpeg\ffmpeg\bin\ffmpeg.exe");
            try {
                ffmpeg.convertor("E:\19222\毕业生.mp4","E:\19222\毕2.avi");
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
    }
    FFMpegTest.java

    ffmpeg操作视频与bgm结合

      视频与bgm结合,最终长度以视频的为主

      Gary.mp4视频与GaryMusic.mp3音频合成,合成新的new.mp4文件

      

      同理使用java代码生成mp4视频

    public void convertor(String videoInputPath,String mp3InputPath,
                double seconds,String videoOutputPath) throws Exception{
            //ffmpeg.exe -i Gary.mp4 -i GaryMusic.mp3 -t 7 -y new.mp4
            List<String> command = new ArrayList<>();
            command.add(ffmpegEXE);
            
            command.add("-i");
            command.add(videoInputPath);
            
            command.add("-i");
            command.add(mp3InputPath);
            
            command.add("-t");
            command.add(String.valueOf(seconds));
            
            command.add("-y");
            command.add(videoOutputPath);
            
            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();
            }
            
        }
    package com.imooc.utils;
    
    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.util.ArrayList;
    import java.util.List;
    
    public class MergeVideoMp3 {
    
        private String ffmpegEXE;
        
        public MergeVideoMp3(String ffmpegEXE) {
            super();
            this.ffmpegEXE = ffmpegEXE;
        }
    
        public void convertor(String videoInputPath,String mp3InputPath,
                double seconds,String videoOutputPath) throws Exception{
            //ffmpeg.exe -i Gary.mp4 -i GaryMusic.mp3 -t 7 -y new.mp4
            List<String> command = new ArrayList<>();
            command.add(ffmpegEXE);
            
            command.add("-i");
            command.add(videoInputPath);
            
            command.add("-i");
            command.add(mp3InputPath);
            
            command.add("-t");
            command.add(String.valueOf(seconds));
            
            command.add("-y");
            command.add(videoOutputPath);
            
            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 static void main(String[] args) {
            MergeVideoMp3 ffmpeg = new MergeVideoMp3("F:\Garyffmpeg\ffmpeg\bin\ffmpeg.exe");
            try {
                ffmpeg.convertor("E:\19222\毕业生.mp4","E:\19222\GaryMusic.mp3",7.1,"E:\19222\通过java生成的视频.mp4");
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
    }
    MergeVideoMp3.java

     小程序上传视频后调用视频处理工具类联调

       可以在小程序端添加判断用户是否选择了BGM,如果不用户选择合成BGM,那就查询bgm的信息,并且合并视频生成新的视频

    if(StringUtils.isNotBlank(bgmId)) {
                    Bgm bgm = bgmService.queryBgmById(bgmId);
                    String mp3InputPath = FILE_SPACE + bgm.getPath();
                    //System.out.println("1:mp3InputPath + "+mp3InputPath);
                    MergeVideoMp3 tool = new MergeVideoMp3(FFMPEG_EXE);
                    String videoInputPath = finalVideoPath;
                    
                    String videdoOutputName = UUID.randomUUID().toString() + ".mp4";
                    uploadPathDB = "/" + userId + "/video" + "/" +videdoOutputName;
                    finalVideoPath = FILE_SPACE + uploadPathDB;
                    tool.convertor(videoInputPath, mp3InputPath, videoSeconds, finalVideoPath);
                    
                }

      FFMpegTest.java作为FFMpeg合并短视频的BGM

    public void convertor(String videoInputPath,String videoOutputPath) throws Exception{
            //$ ffmpeg -i input.mp4 output.avi
            List<String> command = new ArrayList<>();
            command.add(ffmpegEXE);
            command.add("-i");
            command.add(videoInputPath);
            command.add(videoOutputPath);
            
            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();
            }
            
        }

    package com.imooc.utils;
    
    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.util.ArrayList;
    import java.util.List;
    
    public class FFMpegTest {
    
        private String ffmpegEXE;
        
        public FFMpegTest(String ffmpegEXE) {
            super();
            this.ffmpegEXE = ffmpegEXE;
        }
    
        public void convertor(String videoInputPath,String videoOutputPath) throws Exception{
            //$ ffmpeg -i input.mp4 output.avi
            List<String> command = new ArrayList<>();
            command.add(ffmpegEXE);
            command.add("-i");
            command.add(videoInputPath);
            command.add(videoOutputPath);
            
            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 static void main(String[] args) {
            FFMpegTest ffmpeg = new FFMpegTest("F:\Garyffmpeg\ffmpeg\bin\ffmpeg.exe");
            try {
                ffmpeg.convertor("E:\19222\毕业生.mp4","E:\19222\毕2.avi");
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
    }
    FFMpegTest.java
    package com.imooc.controller;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.util.UUID;
    
    import org.apache.commons.lang3.StringUtils;
    import org.apache.tomcat.util.http.fileupload.IOUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.multipart.MultipartFile;
    
    import com.imooc.pojo.Bgm;
    import com.imooc.pojo.Users;
    import com.imooc.service.BgmService;
    import com.imooc.utils.IMoocJSONResult;
    import com.imooc.utils.MergeVideoMp3;
    
    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;
        
        @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 IMoocJSONResult uploadFace(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 IMoocJSONResult.errorMsg("用户id不能为空...");
                }
            
                //文件保存命名空间
                //String fileSpace = "F:/imooc-video-gary";
                //保存到数据库中的相对路径
                String uploadPathDB = "/" + userId + "/video";
                
                FileOutputStream fileOutputStream = null;
                InputStream inputStream = null;
                String finalVideoPath = "";
                try {
                    if( file != null ) {
    
                        
                        String fileName = file.getOriginalFilename();
                        if(StringUtils.isNoneBlank(fileName)) {
                            //文件上传的最终保存路径
                            
                            finalVideoPath = FILE_SPACE + uploadPathDB + "/" + fileName;
                            //设置数据库保存的路径
                            uploadPathDB += ("/" + fileName);
                            
                            File outFile = new File(finalVideoPath);
                            if(outFile.getParentFile()!=null || !outFile.getParentFile().isDirectory()) {
                                //创建父文件夹
                                outFile.getParentFile().mkdirs();
                            }
                            
                            fileOutputStream = new FileOutputStream(outFile);
                            inputStream = file.getInputStream();
                            IOUtils.copy(inputStream, fileOutputStream);
                        }
                        
                    }else {
                        return IMoocJSONResult.errorMsg("上传出错...");
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    return IMoocJSONResult.errorMsg("上传出错...");
                }finally {
                    if(fileOutputStream != null) {
                        fileOutputStream.flush();
                        fileOutputStream.close();
                    }
                }
                
                //判断bgmId是否为空,
                //如果不为空,那就查询bgm的信息,并且合并视频生成新的视频
                
                if(StringUtils.isNotBlank(bgmId)) {
                    Bgm bgm = bgmService.queryBgmById(bgmId);
                    String mp3InputPath = FILE_SPACE + bgm.getPath();
                    //System.out.println("1:mp3InputPath + "+mp3InputPath);
                    MergeVideoMp3 tool = new MergeVideoMp3(FFMPEG_EXE);
                    String videoInputPath = finalVideoPath;
                    
                    String videdoOutputName = UUID.randomUUID().toString() + ".mp4";
                    uploadPathDB = "/" + userId + "/video" + "/" +videdoOutputName;
                    finalVideoPath = FILE_SPACE + uploadPathDB;
                    tool.convertor(videoInputPath, mp3InputPath, videoSeconds, finalVideoPath);
                    
                }
                
                System.out.println("uploadPathDB="+uploadPathDB);
                System.out.println("finalVideoPath="+finalVideoPath);
                
                return IMoocJSONResult.ok();
        }
        
    }
    VideoController.java
    const app = getApp()
    
    Page({
        data: {
        bgmList:[],
        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
                });
              }
            }
          })
    
        },
    
      upload: function (e) {
        var me = this;
    
        var bgmId = e.detail.value.bgmId;
        var desc = e.detail.value.desc;
    
        console.log("bgmId:" + bgmId);
        console.log("desc:" + desc);
    
        var duration = me.data.videoParams.duration;
        var tmpheight = me.data.videoParams.tmpheight;
        var tmpwidth = me.data.videoParams.tmpwidth;
        var tmpVideoUrl = me.data.videoParams.tmpVideoUrl;
        var tmpCoverUrl = me.data.videoParams.tmpCoverUrl;
    
        //上传短视频
        wx.showLoading({
          title: '上传中...',
        })
    
        var serverUrl = app.serverUrl;
        wx.uploadFile({
          url: serverUrl + '/video/upload',
          formData: {
            userId: app.userInfo.id,
            bgmId: bgmId,
            desc: desc,
            videoSeconds: duration,
            videoWidth: tmpheight,
            videoHeight: tmpwidth,
          },
          filePath: tmpVideoUrl,
          name: 'file',
          header: {
            'content-type': 'application/json' // 默认值
          },
          success: function (res) {
            var data = JSON.parse(res.data);
            console.log(res);
            wx.hideLoading();
            if (data.status == 200) {
              wx.showToast({
                title: '上传成功',
                icon: "success"
              });
            }
          }
        })
    
      }
    
    })
    chooseBGM.js

    保存视频到数据库中

      在VideoController中将数视频信息存储到数据库中

        //保存视频信息到数据库
        Videos video = new Videos();
        video.setAudioId(bgmId);
        video.setUserId(userId);
        video.setVideoSeconds((float)videoSeconds);
        video.setVideoHeight(videoHeight);
        video.setVideoWidth(videoWidth);
        video.setVideoDesc(desc);
        video.setVideoPath(uploadPathDB);
        video.setStatus(VideoStatusEnum.SUCCESS.value);
        video.setCreateTime(new Date());
    
        videoService.saveVideo(video);

      保存数据库方法

        @Transactional(propagation = Propagation.REQUIRED)
        @Override
        public void saveVideo(Videos video) {
            
            String id = sid.nextShort();
            video.setId(id);
            
            videosMapper.insertSelective(video);
        }

     

    package com.imooc.service;
    
    import java.util.List;
    
    import com.imooc.pojo.Bgm;
    import com.imooc.pojo.Users;
    import com.imooc.pojo.Videos;
    
    public interface VideoService {
    
        //保存视频
        public void saveVideo(Videos video);
        
    }
    VideoService.java
    package com.imooc.server.impl;
    
    import java.util.List;
    
    import org.n3r.idworker.Sid;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    
    import com.imooc.mapper.BgmMapper;
    import com.imooc.mapper.UsersMapper;
    import com.imooc.mapper.VideosMapper;
    import com.imooc.pojo.Bgm;
    import com.imooc.pojo.Users;
    import com.imooc.pojo.Videos;
    import com.imooc.service.BgmService;
    import com.imooc.service.UserService;
    import com.imooc.service.VideoService;
    
    import tk.mybatis.mapper.entity.Example;
    import tk.mybatis.mapper.entity.Example.Criteria;
    
    @Service
    public class VideoServiceImpl implements VideoService {
    
        @Autowired
        private VideosMapper videosMapper;
        
        @Autowired
        private Sid sid;
        
    
        @Transactional(propagation = Propagation.REQUIRED)
        @Override
        public void saveVideo(Videos video) {
            
            String id = sid.nextShort();
            video.setId(id);
            
            videosMapper.insertSelective(video);
        }
    
    
        
    }
    VideoServiceImpl.java
    package com.imooc.controller;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.util.Date;
    import java.util.UUID;
    
    import org.apache.commons.lang3.StringUtils;
    import org.apache.tomcat.util.http.fileupload.IOUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.multipart.MultipartFile;
    
    import com.imooc.enums.VideoStatusEnum;
    import com.imooc.pojo.Bgm;
    import com.imooc.pojo.Users;
    import com.imooc.pojo.Videos;
    import com.imooc.service.BgmService;
    import com.imooc.service.VideoService;
    import com.imooc.utils.IMoocJSONResult;
    import com.imooc.utils.MergeVideoMp3;
    
    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 videoService;
        
        
        @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 IMoocJSONResult uploadFace(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 IMoocJSONResult.errorMsg("用户id不能为空...");
                }
            
                //文件保存命名空间
                //String fileSpace = "F:/imooc-video-gary";
                //保存到数据库中的相对路径
                String uploadPathDB = "/" + userId + "/video";
                
                FileOutputStream fileOutputStream = null;
                InputStream inputStream = null;
                String finalVideoPath = "";
                try {
                    if( file != null ) {
    
                        
                        String fileName = file.getOriginalFilename();
                        if(StringUtils.isNoneBlank(fileName)) {
                            //文件上传的最终保存路径
                            
                            finalVideoPath = FILE_SPACE + uploadPathDB + "/" + fileName;
                            //设置数据库保存的路径
                            uploadPathDB += ("/" + fileName);
                            
                            File outFile = new File(finalVideoPath);
                            if(outFile.getParentFile()!=null || !outFile.getParentFile().isDirectory()) {
                                //创建父文件夹
                                outFile.getParentFile().mkdirs();
                            }
                            
                            fileOutputStream = new FileOutputStream(outFile);
                            inputStream = file.getInputStream();
                            IOUtils.copy(inputStream, fileOutputStream);
                        }
                        
                    }else {
                        return IMoocJSONResult.errorMsg("上传出错...");
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    return IMoocJSONResult.errorMsg("上传出错...");
                }finally {
                    if(fileOutputStream != null) {
                        fileOutputStream.flush();
                        fileOutputStream.close();
                    }
                }
                
                //判断bgmId是否为空,
                //如果不为空,那就查询bgm的信息,并且合并视频生成新的视频
                
                if(StringUtils.isNotBlank(bgmId)) {
                    Bgm bgm = bgmService.queryBgmById(bgmId);
                    String mp3InputPath = FILE_SPACE + bgm.getPath();
                    //System.out.println("1:mp3InputPath + "+mp3InputPath);
                    MergeVideoMp3 tool = new MergeVideoMp3(FFMPEG_EXE);
                    String videoInputPath = finalVideoPath;
                    
                    String videdoOutputName = UUID.randomUUID().toString() + ".mp4";
                    uploadPathDB = "/" + userId + "/video" + "/" +videdoOutputName;
                    finalVideoPath = FILE_SPACE + uploadPathDB;
                    tool.convertor(videoInputPath, mp3InputPath, videoSeconds, finalVideoPath);
                    
                }
                
                //保存视频信息到数据库
                Videos video = new Videos();
                video.setAudioId(bgmId);
                video.setUserId(userId);
                video.setVideoSeconds((float)videoSeconds);
                video.setVideoHeight(videoHeight);
                video.setVideoWidth(videoWidth);
                video.setVideoDesc(desc);
                video.setVideoPath(uploadPathDB);
                video.setStatus(VideoStatusEnum.SUCCESS.value);
                video.setCreateTime(new Date());
                
                videoService.saveVideo(video);
                
                return IMoocJSONResult.ok();
        }
        
    }
    VideoController.java

    上传封面图保存到数据库中

      因为wx.uploadFile()方法上传是单文件,所以视频和封面必须要分开上传

      保存视频uploadCover(Sring userId,String videoId)方法

    @ApiOperation(value="上传封面", notes="上传封面的接口")
        @ApiImplicitParams({        
            @ApiImplicitParam(name="userId",value="用户id",required=true,
                    dataType="String" ,paramType="form"),
            @ApiImplicitParam(name="videoId",value="视频主键id",required=true,
                    dataType="String" ,paramType="form")
        })
        @PostMapping(value="/uploadCover",headers="content-type=multipart/form-data")
        public IMoocJSONResult uploadCover(String userId,String videoId, 
                @ApiParam(value="视频封面",required=true)
                MultipartFile file) throws Exception {
            
                if(StringUtils.isBlank(userId) ||StringUtils.isBlank(videoId) ) {
                    return IMoocJSONResult.errorMsg("视频主键id和用户id不能为空...");
                }
            
                //文件保存命名空间
                //String fileSpace = "F:/imooc-video-gary";
                //保存到数据库中的相对路径
                String uploadPathDB = "/" + userId + "/video";
                
                FileOutputStream fileOutputStream = null;
                InputStream inputStream = null;
                String finalCoverPath = "";
                try {
                    if( file != null ) {
    
                        
                        String fileName = file.getOriginalFilename();
                        if(StringUtils.isNoneBlank(fileName)) {
                            //文件上传的最终保存路径
                            
                            finalCoverPath = FILE_SPACE + uploadPathDB + "/" + fileName;
                            //设置数据库保存的路径
                            uploadPathDB += ("/" + fileName);
                            
                            File outFile = new File(finalCoverPath);
                            if(outFile.getParentFile()!=null || !outFile.getParentFile().isDirectory()) {
                                //创建父文件夹
                                outFile.getParentFile().mkdirs();
                            }
                            
                            fileOutputStream = new FileOutputStream(outFile);
                            inputStream = file.getInputStream();
                            IOUtils.copy(inputStream, fileOutputStream);
                        }
                        
                    }else {
                        return IMoocJSONResult.errorMsg("上传出错...");
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    return IMoocJSONResult.errorMsg("上传出错...");
                }finally {
                    if(fileOutputStream != null) {
                        fileOutputStream.flush();
                        fileOutputStream.close();
                    }
                }
                
                videoService.updateVideo(videoId, uploadPathDB);
                
                return IMoocJSONResult.ok();
        }

      将视频封面保存进数据库方法

        @Transactional(propagation = Propagation.REQUIRED)
        @Override
        public void updateVideo(String videoId, String coverPath) {
            
            Videos video = new Videos();
            video.setId(videoId);
            video.setCoverPath(coverPath);
            videosMapper.updateByPrimaryKeySelective(video);
            
        }

    package com.imooc.server.impl;
    
    import java.util.List;
    
    import org.n3r.idworker.Sid;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    
    import com.imooc.mapper.BgmMapper;
    import com.imooc.mapper.UsersMapper;
    import com.imooc.mapper.VideosMapper;
    import com.imooc.pojo.Bgm;
    import com.imooc.pojo.Users;
    import com.imooc.pojo.Videos;
    import com.imooc.service.BgmService;
    import com.imooc.service.UserService;
    import com.imooc.service.VideoService;
    
    import tk.mybatis.mapper.entity.Example;
    import tk.mybatis.mapper.entity.Example.Criteria;
    
    @Service
    public class VideoServiceImpl implements VideoService {
    
        @Autowired
        private VideosMapper videosMapper;
        
        @Autowired
        private Sid sid;
        
    
        @Transactional(propagation = Propagation.REQUIRED)
        @Override
        public String saveVideo(Videos video) {
            
            String id = sid.nextShort();
            video.setId(id);
            
            videosMapper.insertSelective(video);
            
            return id;
        }
    
        @Transactional(propagation = Propagation.REQUIRED)
        @Override
        public void updateVideo(String videoId, String coverPath) {
            
            Videos video = new Videos();
            video.setId(videoId);
            video.setCoverPath(coverPath);
            videosMapper.updateByPrimaryKeySelective(video);
            
        }
    
    
        
    }
    VideoServiceImpl.java
    package com.imooc.controller;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.util.Date;
    import java.util.UUID;
    
    import org.apache.commons.lang3.StringUtils;
    import org.apache.tomcat.util.http.fileupload.IOUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.multipart.MultipartFile;
    
    import com.imooc.enums.VideoStatusEnum;
    import com.imooc.pojo.Bgm;
    import com.imooc.pojo.Users;
    import com.imooc.pojo.Videos;
    import com.imooc.service.BgmService;
    import com.imooc.service.VideoService;
    import com.imooc.utils.IMoocJSONResult;
    import com.imooc.utils.MergeVideoMp3;
    
    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 videoService;
        
        
        @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 IMoocJSONResult uploadFace(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 IMoocJSONResult.errorMsg("用户id不能为空...");
                }
            
                //文件保存命名空间
                //String fileSpace = "F:/imooc-video-gary";
                //保存到数据库中的相对路径
                String uploadPathDB = "/" + userId + "/video";
                
                FileOutputStream fileOutputStream = null;
                InputStream inputStream = null;
                String finalVideoPath = "";
                try {
                    if( file != null ) {
    
                        
                        String fileName = file.getOriginalFilename();
                        if(StringUtils.isNoneBlank(fileName)) {
                            //文件上传的最终保存路径
                            
                            finalVideoPath = FILE_SPACE + uploadPathDB + "/" + fileName;
                            //设置数据库保存的路径
                            uploadPathDB += ("/" + fileName);
                            
                            File outFile = new File(finalVideoPath);
                            if(outFile.getParentFile()!=null || !outFile.getParentFile().isDirectory()) {
                                //创建父文件夹
                                outFile.getParentFile().mkdirs();
                            }
                            
                            fileOutputStream = new FileOutputStream(outFile);
                            inputStream = file.getInputStream();
                            IOUtils.copy(inputStream, fileOutputStream);
                        }
                        
                    }else {
                        return IMoocJSONResult.errorMsg("上传出错...");
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    return IMoocJSONResult.errorMsg("上传出错...");
                }finally {
                    if(fileOutputStream != null) {
                        fileOutputStream.flush();
                        fileOutputStream.close();
                    }
                }
                
                //判断bgmId是否为空,
                //如果不为空,那就查询bgm的信息,并且合并视频生成新的视频
                
                if(StringUtils.isNotBlank(bgmId)) {
                    Bgm bgm = bgmService.queryBgmById(bgmId);
                    String mp3InputPath = FILE_SPACE + bgm.getPath();
                    //System.out.println("1:mp3InputPath + "+mp3InputPath);
                    MergeVideoMp3 tool = new MergeVideoMp3(FFMPEG_EXE);
                    String videoInputPath = finalVideoPath;
                    
                    String videdoOutputName = UUID.randomUUID().toString() + ".mp4";
                    uploadPathDB = "/" + userId + "/video" + "/" +videdoOutputName;
                    finalVideoPath = FILE_SPACE + uploadPathDB;
                    tool.convertor(videoInputPath, mp3InputPath, videoSeconds, finalVideoPath);
                    
                }
                
                //保存视频信息到数据库
                Videos video = new Videos();
                video.setAudioId(bgmId);
                video.setUserId(userId);
                video.setVideoSeconds((float)videoSeconds);
                video.setVideoHeight(videoHeight);
                video.setVideoWidth(videoWidth);
                video.setVideoDesc(desc);
                video.setVideoPath(uploadPathDB);
                video.setStatus(VideoStatusEnum.SUCCESS.value);
                video.setCreateTime(new Date());
                
                String videoId = videoService.saveVideo(video);
                
                return IMoocJSONResult.ok(videoId);
        }
        
        @ApiOperation(value="上传封面", notes="上传封面的接口")
        @ApiImplicitParams({        
            @ApiImplicitParam(name="userId",value="用户id",required=true,
                    dataType="String" ,paramType="form"),
            @ApiImplicitParam(name="videoId",value="视频主键id",required=true,
                    dataType="String" ,paramType="form")
        })
        @PostMapping(value="/uploadCover",headers="content-type=multipart/form-data")
        public IMoocJSONResult uploadCover(String userId,String videoId, 
                @ApiParam(value="视频封面",required=true)
                MultipartFile file) throws Exception {
            
                if(StringUtils.isBlank(userId) ||StringUtils.isBlank(videoId) ) {
                    return IMoocJSONResult.errorMsg("视频主键id和用户id不能为空...");
                }
            
                //文件保存命名空间
                //String fileSpace = "F:/imooc-video-gary";
                //保存到数据库中的相对路径
                String uploadPathDB = "/" + userId + "/video";
                
                FileOutputStream fileOutputStream = null;
                InputStream inputStream = null;
                String finalCoverPath = "";
                try {
                    if( file != null ) {
    
                        
                        String fileName = file.getOriginalFilename();
                        if(StringUtils.isNoneBlank(fileName)) {
                            //文件上传的最终保存路径
                            
                            finalCoverPath = FILE_SPACE + uploadPathDB + "/" + fileName;
                            //设置数据库保存的路径
                            uploadPathDB += ("/" + fileName);
                            
                            File outFile = new File(finalCoverPath);
                            if(outFile.getParentFile()!=null || !outFile.getParentFile().isDirectory()) {
                                //创建父文件夹
                                outFile.getParentFile().mkdirs();
                            }
                            
                            fileOutputStream = new FileOutputStream(outFile);
                            inputStream = file.getInputStream();
                            IOUtils.copy(inputStream, fileOutputStream);
                        }
                        
                    }else {
                        return IMoocJSONResult.errorMsg("上传出错...");
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    return IMoocJSONResult.errorMsg("上传出错...");
                }finally {
                    if(fileOutputStream != null) {
                        fileOutputStream.flush();
                        fileOutputStream.close();
                    }
                }
                
                videoService.updateVideo(videoId, uploadPathDB);
                
                return IMoocJSONResult.ok();
        }
        
        
        
        
        
    }
    VideoController.java

    小程序端上传视频业务流程实现

      当小程序端成功上传视频回调函数返回200时,上传视频封面

    if (data.status == 200) {
    
              var videoId = data.data;
    
              //上传短视频封面
              wx.showLoading({
                title: '上传中...',
              })
              wx.uploadFile({
                url: serverUrl + '/video/uploadCover',
                formData: {
                  userId: app.userInfo.id,
                  videoId: videoId
                },
                filePath: tmpCoverUrl,
                name: 'file',
                header: {
                  'content-type': 'application/json' // 默认值
                },
                success: function (res) {
                  var data = JSON.parse(res.data);
                  wx.hideLoading();
                  if (data.status == 200) {
                    wx.showToast({
                      title: '上传成功',
                      icon: "success"
                    });
                    wx.navigateBack({
                      delta:1,
                    })
                  } else {
                    wx.showToast({
                      title: '上传失败!',
                      icon: "success"
                    });
                  }
                }
              })
    
    
            }else{
              wx.showToast({
                title: '上传失败!',
                icon:"success"
              });
            }
    const app = getApp()
    
    Page({
        data: {
        bgmList:[],
        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
                });
              }
            }
          })
    
        },
    
      upload: function (e) {
        var me = this;
    
        var bgmId = e.detail.value.bgmId;
        var desc = e.detail.value.desc;
    
        console.log("bgmId:" + bgmId);
        console.log("desc:" + desc);
    
        var duration = me.data.videoParams.duration;
        var tmpheight = me.data.videoParams.tmpheight;
        var tmpwidth = me.data.videoParams.tmpwidth;
        var tmpVideoUrl = me.data.videoParams.tmpVideoUrl;
        var tmpCoverUrl = me.data.videoParams.tmpCoverUrl;
    
        //上传短视频
        wx.showLoading({
          title: '上传中...',
        })
    
        var serverUrl = app.serverUrl;
        wx.uploadFile({
          url: serverUrl + '/video/upload',
          formData: {
            userId: app.userInfo.id,
            bgmId: bgmId,
            desc: desc,
            videoSeconds: duration,
            videoWidth: tmpheight,
            videoHeight: tmpwidth,
          },
          filePath: tmpVideoUrl,
          name: 'file',
          header: {
            'content-type': 'application/json' // 默认值
          },
          success: function (res) {
            var data = JSON.parse(res.data);
            wx.hideLoading();
            if (data.status == 200) {
    
              var videoId = data.data;
    
              //上传短视频封面
              wx.showLoading({
                title: '上传中...',
              })
              wx.uploadFile({
                url: serverUrl + '/video/uploadCover',
                formData: {
                  userId: app.userInfo.id,
                  videoId: videoId
                },
                filePath: tmpCoverUrl,
                name: 'file',
                header: {
                  'content-type': 'application/json' // 默认值
                },
                success: function (res) {
                  var data = JSON.parse(res.data);
                  wx.hideLoading();
                  if (data.status == 200) {
                    wx.showToast({
                      title: '上传成功',
                      icon: "success"
                    });
                    wx.navigateBack({
                      delta:1,
                    })
                  } else {
                    wx.showToast({
                      title: '上传失败!',
                      icon: "success"
                    });
                  }
                }
              })
    
    
            }else{
              wx.showToast({
                title: '上传失败!',
                icon:"success"
              });
            }
          }
        })
    
      }
    
    })
    chooseBgm.js

      为避免在微信小程序端截不到视频封面的图片,即使用ffmpeg技术去实现

      截图思路:截视频的第1s

    bin>ffmpeg.exe -ss 00:00:01 -y -i new.mp4 -vframes 1 new2.jpg

    package com.imooc.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("F:\Garyffmpeg\ffmpeg\bin\ffmpeg.exe");
            try {
                videoInfo.getCover("e:\19222\Gary12.mp4","e:\19222\Gary1212.jpg");
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    FetchVideoCover.java

    上传视频流程整合视频截图功能

      在VideoController.java中实现视频截图功能并保存到数据库中

                //对视频封面进行截图
                FetchVideoCover videoInfo = new FetchVideoCover(FFMPEG_EXE);
                videoInfo.getCover(finalVideoPath,FILE_SPACE + coverPathDB);
                
                //保存视频信息到数据库
                Videos video = new Videos();
                video.setAudioId(bgmId);
                video.setUserId(userId);
                video.setVideoSeconds((float)videoSeconds);
                video.setVideoHeight(videoHeight);
                video.setVideoWidth(videoWidth);
                video.setVideoDesc(desc);
                video.setVideoPath(uploadPathDB);
                video.setCoverPath(coverPathDB);
                video.setStatus(VideoStatusEnum.SUCCESS.value);
                video.setCreateTime(new Date());
    package com.imooc.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("F:\Garyffmpeg\ffmpeg\bin\ffmpeg.exe");
            try {
                videoInfo.getCover("e:\19222\Gary12.mp4","e:\19222\Gary1212.jpg");
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    FetchVideoCover.java
    package com.imooc.controller;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.util.Date;
    import java.util.UUID;
    
    import org.apache.commons.lang3.StringUtils;
    import org.apache.tomcat.util.http.fileupload.IOUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.multipart.MultipartFile;
    
    import com.imooc.enums.VideoStatusEnum;
    import com.imooc.pojo.Bgm;
    import com.imooc.pojo.Users;
    import com.imooc.pojo.Videos;
    import com.imooc.service.BgmService;
    import com.imooc.service.VideoService;
    import com.imooc.utils.FetchVideoCover;
    import com.imooc.utils.IMoocJSONResult;
    import com.imooc.utils.MergeVideoMp3;
    
    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 videoService;
        
        
        @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 IMoocJSONResult uploadFace(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 IMoocJSONResult.errorMsg("用户id不能为空...");
                }
            
                //文件保存命名空间
                //String fileSpace = "F:/imooc-video-gary";
                //保存到数据库中的相对路径
                String uploadPathDB = "/" + userId + "/video";
                String coverPathDB = "/" + userId + "/video";
                
                FileOutputStream fileOutputStream = null;
                InputStream inputStream = null;
                String finalVideoPath = "";
                try {
                    if( file != null ) {
    
                        String fileName = file.getOriginalFilename();
                        //Gary.mp4  使用spilt进行分割
                        String fileNamePrefix = fileName.split("\.")[0];
                        
                        
                        
                        if(StringUtils.isNoneBlank(fileName)) {
                            //文件上传的最终保存路径
                            
                            finalVideoPath = FILE_SPACE + uploadPathDB + "/" + fileName;
                            //设置数据库保存的路径
                            uploadPathDB += ("/" + fileName);
                            coverPathDB = coverPathDB + "/" + fileNamePrefix + ".jpg";
                            
                            File outFile = new File(finalVideoPath);
                            if(outFile.getParentFile()!=null || !outFile.getParentFile().isDirectory()) {
                                //创建父文件夹
                                outFile.getParentFile().mkdirs();
                            }
                            
                            fileOutputStream = new FileOutputStream(outFile);
                            inputStream = file.getInputStream();
                            IOUtils.copy(inputStream, fileOutputStream);
                        }
                        
                    }else {
                        return IMoocJSONResult.errorMsg("上传出错...");
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    return IMoocJSONResult.errorMsg("上传出错...");
                }finally {
                    if(fileOutputStream != null) {
                        fileOutputStream.flush();
                        fileOutputStream.close();
                    }
                }
                
                //判断bgmId是否为空,
                //如果不为空,那就查询bgm的信息,并且合并视频生成新的视频
                
                if(StringUtils.isNotBlank(bgmId)) {
                    Bgm bgm = bgmService.queryBgmById(bgmId);
                    String mp3InputPath = FILE_SPACE + bgm.getPath();
                    //System.out.println("1:mp3InputPath + "+mp3InputPath);
                    MergeVideoMp3 tool = new MergeVideoMp3(FFMPEG_EXE);
                    String videoInputPath = finalVideoPath;
                    
                    String videdoOutputName = UUID.randomUUID().toString() + ".mp4";
                    uploadPathDB = "/" + userId + "/video" + "/" +videdoOutputName;
                    finalVideoPath = FILE_SPACE + uploadPathDB;
                    tool.convertor(videoInputPath, mp3InputPath, videoSeconds, finalVideoPath);
                    
                }
                
                //对视频封面进行截图
                FetchVideoCover videoInfo = new FetchVideoCover(FFMPEG_EXE);
                videoInfo.getCover(finalVideoPath,FILE_SPACE + coverPathDB);
                
                //保存视频信息到数据库
                Videos video = new Videos();
                video.setAudioId(bgmId);
                video.setUserId(userId);
                video.setVideoSeconds((float)videoSeconds);
                video.setVideoHeight(videoHeight);
                video.setVideoWidth(videoWidth);
                video.setVideoDesc(desc);
                video.setVideoPath(uploadPathDB);
                video.setCoverPath(coverPathDB);
                video.setStatus(VideoStatusEnum.SUCCESS.value);
                video.setCreateTime(new Date());
                
                String videoId = videoService.saveVideo(video);
                
                return IMoocJSONResult.ok(videoId);
        }
        
        @ApiOperation(value="上传封面", notes="上传封面的接口")
        @ApiImplicitParams({        
            @ApiImplicitParam(name="userId",value="用户id",required=true,
                    dataType="String" ,paramType="form"),
            @ApiImplicitParam(name="videoId",value="视频主键id",required=true,
                    dataType="String" ,paramType="form")
        })
        @PostMapping(value="/uploadCover",headers="content-type=multipart/form-data")
        public IMoocJSONResult uploadCover(String userId,String videoId, 
                @ApiParam(value="视频封面",required=true)
                MultipartFile file) throws Exception {
            
                if(StringUtils.isBlank(userId) ||StringUtils.isBlank(videoId) ) {
                    return IMoocJSONResult.errorMsg("视频主键id和用户id不能为空...");
                }
            
                //文件保存命名空间
                //String fileSpace = "F:/imooc-video-gary";
                //保存到数据库中的相对路径
                String uploadPathDB = "/" + userId + "/video";
                
                FileOutputStream fileOutputStream = null;
                InputStream inputStream = null;
                String finalCoverPath = "";
                try {
                    if( file != null ) {
    
                        
                        String fileName = file.getOriginalFilename();
                        if(StringUtils.isNoneBlank(fileName)) {
                            //文件上传的最终保存路径
                            
                            finalCoverPath = FILE_SPACE + uploadPathDB + "/" + fileName;
                            //设置数据库保存的路径
                            uploadPathDB += ("/" + fileName);
                            
                            File outFile = new File(finalCoverPath);
                            if(outFile.getParentFile()!=null || !outFile.getParentFile().isDirectory()) {
                                //创建父文件夹
                                outFile.getParentFile().mkdirs();
                            }
                            
                            fileOutputStream = new FileOutputStream(outFile);
                            inputStream = file.getInputStream();
                            IOUtils.copy(inputStream, fileOutputStream);
                        }
                        
                    }else {
                        return IMoocJSONResult.errorMsg("上传出错...");
                    }
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    return IMoocJSONResult.errorMsg("上传出错...");
                }finally {
                    if(fileOutputStream != null) {
                        fileOutputStream.flush();
                        fileOutputStream.close();
                    }
                }
                
                videoService.updateVideo(videoId, uploadPathDB);
                
                return IMoocJSONResult.ok();
        }
        
        
        
        
        
    }
    VideoController.java
    const app = getApp()
    
    Page({
        data: {
        bgmList:[],
        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
                });
              }
            }
          })
    
        },
    
      upload: function (e) {
        var me = this;
    
        var bgmId = e.detail.value.bgmId;
        var desc = e.detail.value.desc;
    
        console.log("bgmId:" + bgmId);
        console.log("desc:" + desc);
    
        var duration = me.data.videoParams.duration;
        var tmpheight = me.data.videoParams.tmpheight;
        var tmpwidth = me.data.videoParams.tmpwidth;
        var tmpVideoUrl = me.data.videoParams.tmpVideoUrl;
        var tmpCoverUrl = me.data.videoParams.tmpCoverUrl;
    
        //上传短视频
        wx.showLoading({
          title: '上传中...',
        })
    
        var serverUrl = app.serverUrl;
        wx.uploadFile({
          url: serverUrl + '/video/upload',
          formData: {
            userId: app.userInfo.id,
            bgmId: bgmId,
            desc: desc,
            videoSeconds: duration,
            videoWidth: tmpheight,
            videoHeight: tmpwidth,
          },
          filePath: tmpVideoUrl,
          name: 'file',
          header: {
            'content-type': 'application/json' // 默认值
          },
          success: function (res) {
            var data = JSON.parse(res.data);
            wx.hideLoading();
            if (data.status == 200) {
    
              wx.showToast({
                title: '上传成功!',
                icon: "success"
              });
              // 上传成功后跳回之前的页面
              wx.navigateBack({
                delta: 1
              })
    /*
              var videoId = data.data;
    
              //上传短视频封面
              wx.showLoading({
                title: '上传中...',
              })
              wx.uploadFile({
                url: serverUrl + '/video/uploadCover',
                formData: {
                  userId: app.userInfo.id,
                  videoId: videoId
                },
                filePath: tmpCoverUrl,
                name: 'file',
                header: {
                  'content-type': 'application/json' // 默认值
                },
                success: function (res) {
                  var data = JSON.parse(res.data);
                  wx.hideLoading();
                  if (data.status == 200) {
                    wx.showToast({
                      title: '上传成功',
                      icon: "success"
                    });
                    wx.navigateBack({
                      delta:1,
                    })
                  } else {
                    wx.showToast({
                      title: '上传失败!',
                      icon: "success"
                    });
                  }
                }
              })
    
    */
    
            }else{
              wx.showToast({
                title: '上传失败!',
                icon:"success"
              });
            }
          }
        })
    
      }
    
    })
    chooseBGM.js
    (如需转载学习,请标明出处)
  • 相关阅读:
    进程间通讯----消息队列和共享内存方式的实现
    初探 Yii2 的测试模式 index-test.php
    nginx缓存功能的设置
    php五大运行模式CGI,FAST-CGI,CLI,ISAPI,APACHE模式
    workerman如何写mysql连接池
    Varnish 一般是放在 Nginx 前面还是后面的?
    关于PATH_INFO
    Java8 Lambda表达式
    synchronized的一些记录
    类和实例
  • 原文地址:https://www.cnblogs.com/1138720556Gary/p/10701602.html
Copyright © 2011-2022 走看看