微信小程序_(校園視) 開發用戶註冊登錄 傳送門 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>
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); } }) } })
背景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>
const app = getApp()
Page({
data: {
},
onLoad: function (params) {
},
})
添加音樂模塊樣式
<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>
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) { }, })
數據庫中單獨添加一條數據
音樂文件放在虛擬路徑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()); } }
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(); }
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(); } }
微信小程序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>
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 }); } } }) }, })
開發上傳短視頻接口
短視頻上傳接口相似上傳頭像
@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(); } }
小程序上傳視頻
視頻從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>
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" }); } } }) } })
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 , }) } } }) } })
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(); } } }
能夠看到轉碼格式的輸出
爲了提升資源的利用率,能夠在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(); } } }
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(); } } }
小程序上傳視頻後調用視頻處理工具類聯調
能夠在小程序端添加判斷用戶是否選擇了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(); } } }
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(); } }
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" }); } } }) } })
保存視頻到數據庫中
在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); }
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); } }
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(); } }
上傳封面圖保存到數據庫中
由於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); } }
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(); } }
小程序端上傳視頻業務流程實現
當小程序端成功上傳視頻回調函數返回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" }); } } }) } })
爲避免在微信小程序端截不到視頻封面的圖片,即便用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(); } } }
上傳視頻流程整合視頻截圖功能
在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(); } } }
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(); } }
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" }); } } }) } })