小言_互联网的博客

第6章:上传视频业务流程开发(6-26 使用ffmpeg生成截图— 6-28 小程序端与后台联调测试上传流程)

307人阅读  评论(0)

学习目标:

6-26 使用ffmpeg生成截图
6-27 上传视频流程整合视频截图功能
6-28 小程序端与后台联调测试上传流程


学习内容:

6-26 使用ffmpeg生成截图

1、在cmd命令中使用ffmpeg生成截图:尽量生成jpg,不占内存

2、在spring boot实现这个命令:

首先新建FetchVideoCover.java工具类:


代码如下:

package com.asayi.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:\\JavaEE\\ffmpeg-4.3.1\\bin\\ffmpeg.exe");
		try {
   
			videoInfo.getCover("F:\\JavaEE\\ffmpeg-4.3.1\\bin\\springday.mp4",
					            "F:\\JavaEE\\ffmpeg-4.3.1\\bin\\111.jpg");

		} catch (Exception e) {
   
			e.printStackTrace();
		}
	}
}

对上述代码,右键测试运行:

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

更改VideoController.java的代码如下,新增上传视频到数据库的部分

package com.asayi.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.io.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.alibaba.druid.util.StringUtils;
import com.asayi.enums.VideoStatusEnum;
import com.asayi.pojo.AsayiUsers;
import com.asayi.pojo.Bgm;
import com.asayi.pojo.Videos;
import com.asayi.service.BgmService;
import com.asayi.service.VideoService;
import com.asayi.utils.FetchVideoCover;
import com.asayi.utils.IMoocJSONResult;
import com.asayi.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 = "double",paramType = "form"),
		
	    @ApiImplicitParam(name = "videoWidth",value = "视频宽度",required = true,
                         dataType = "int",paramType = "form"),
		
	    @ApiImplicitParam(name = "videoHeight",value = "视频高度",required = true,
                         dataType = "int",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.isEmpty(userId)) {
   
			return IMoocJSONResult.errorMsg("用户id不能为空...");
		}
		
//		//文件保存的命名空间
//		String fileSpace="F:/武汉理工风景/大四上/毕业设计/user_videos_dev";
		//保存到数据库中的相对路径
		String uploadPathDB="/"+userId+"/video";
		String coverPathDB="/"+userId+"/video";	
		
		FileOutputStream fileOutputStream=null;
		InputStream inputStream=null;	
		//文件上传的最终保存路径
		String finalVideoPath="";
		
		try {
   
			if (file!=null) {
   
				String fileName=file.getOriginalFilename();
				//abc.mp4
				String fileNamePrefix=fileName.split("\\.")[0];
				
				if(!StringUtils.isEmpty(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) {
   
			e.printStackTrace();
			return IMoocJSONResult.errorMsg("上传出错...");
		}finally {
   
			if(fileOutputStream!=null) {
   
				fileOutputStream.flush();
				fileOutputStream.close();
			}
		}
		
		//判断bgmId是否为空,如果不为空,
		//那就查询bgm的信息,并且合并视频,生成新的视频到数据库。
		
		if(!StringUtils.isEmpty(bgmId)) {
   
			Bgm bgm=BgmService.queryBgmById(bgmId);
			String mp3InputPath=FILE_SPACE+bgm.getPath();
			

			MergeVideoMp3 tool=new MergeVideoMp3(FFMPEG_EXE);

			//去除原视频的音频前的路径
			String videoBgmInputPath=finalVideoPath;
			
			//去除原视频的音频后的路径
			String videoBgmOutputName=UUID.randomUUID().toString()+".mp4";
			uploadPathDB="/"+userId+"/video"+"/"+videoBgmOutputName;
			String videoBgmOutputPath=FILE_SPACE+uploadPathDB;
			
			//音视频合并前的路径=去除原视频的音频后的路径
			String videoInputPath=videoBgmOutputPath;
			
			//音视频合并后的路径
			String videoOutputName=UUID.randomUUID().toString()+".mp4";
			uploadPathDB="/"+userId+"/video"+"/"+videoOutputName;
			finalVideoPath=FILE_SPACE+uploadPathDB;
			
			tool.deleteBgm(videoBgmInputPath, videoBgmOutputPath);
			tool.convertor(videoInputPath, mp3InputPath, videoSeconds, finalVideoPath);
		}
		System.out.println("uploadPathDB="+uploadPathDB);
		System.out.println("finalVideoPath="+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.isEmpty(videoId)||StringUtils.isEmpty(userId)) {
   
			return IMoocJSONResult.errorMsg("视频主键id或用户id不能为空...");
		}
		
//		//文件保存的命名空间
//		String fileSpace="F:/武汉理工风景/大四上/毕业设计/user_videos_dev";
		//保存到数据库中的相对路径
		String uploadPathDB="/"+userId+"/video";
		
		FileOutputStream fileOutputStream=null;
		InputStream inputStream=null;
		
		//文件上传的最终保存路径
		String finalCoverPath="";
		
		try {
   
			if (file!=null) {
   

				
				String fileName=file.getOriginalFilename();
				if(!StringUtils.isEmpty(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) {
   
			e.printStackTrace();
			return IMoocJSONResult.errorMsg("上传出错...");
		}finally {
   
			if(fileOutputStream!=null) {
   
				fileOutputStream.flush();
				fileOutputStream.close();
			}
		}
		
		videoService.updateVideo(videoId, uploadPathDB);
				
		return IMoocJSONResult.ok();
	}
	
}

6-28 小程序端与后台联调测试上传流程

chooseBgm.js的代码如下:

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,
                videoHeight:tmpheight,
                videoWidth:tmpwidth
              },
              filePath: tmpVideoUrl,
              name: 'file',
              header:{
   
                'content-type':'application/json'//默认值
              },
              success (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;
                  // debugger;
                  //   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(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:'loading'
                    //       });
                    //     }
                    //   }
                    // })
  

                }else{
   
                  wx.showToast({
   
                    title: '上传失败!',
                    icon:'loading'
                  });
                }           
              }
            })

    }
})


上一章最后的问题,问啥总是显示上传失败,明明都已经全部上传到数据库里面了,原来是我状态获取错了!


转载:https://blog.csdn.net/weixin_43820675/article/details/116349226
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场