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

 

 

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

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

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

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

 

 

用户上传视频

  用户选择视频->打开选择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-gary\bgm下

  

 

  添加查询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='width:300px'去进行歌曲名长度控制 

  <audio   name="{{item.name}}"  author="{{item.author}}" src="{{serverUrl}}{{item.path}}" style='width: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='width: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='width: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

 

posted @ 2019-04-13 16:17 Cynical丶Gary 阅读(...) 评论(...) 编辑 收藏