微信小程序_(校園視)開發上傳視頻業務

 

 

  微信小程序_(校園視)  開發用戶註冊登錄  傳送門 html

  微信小程序_(校園視)  開發上傳視頻業務  傳送門 java

  微信小程序_(校園視)  開發視頻的展現頁-上  傳送門 web

  微信小程序_(校園視)  開發視頻的展現頁-下  傳送門 spring

 

 

用戶上傳視頻數據庫

  用戶選擇視頻->打開選擇bgm->選擇/不選擇bgm輸入視頻的描述->Controller上傳視頻->保存視頻的截圖->用戶是否選擇bgmapache

  用戶沒有選擇bgm能夠直接保存視頻,用戶選擇bgm將合併原視頻和bgm新的視頻而且保存json

  用戶點擊上傳視頻觸發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
相關文章
相關標籤/搜索