转自;https://idig8.com/2018/09/16/xiaochengxujavashizhanxiaochengxushipinchuligongjuffmpeg46/

前面已经把视频成功的上传到我们的服务器,选择了背景音乐的ID,现在需要把视频和背景音乐进行合并,需要使用一个工具ffmpeg。源码:https://github.com/limingios/wxProgram.git 中wx-springboot 和 No.15

ffmpeg

  • 介绍
    >视音频处理工具,跨平台的视音频处理解决方案,主页:http://ffmpeg.org

  • 应用的场景
  1. 播放器:射手播放器,暴风影音,迅雷播放器……
  2. 转换工具:格式工厂,剪辑工具……
  3. 直播,视频加码,滤镜,水印,特效……
  • 下载

根据你的需求进行下载,我选择在windows平台来进行下载

  • 测试

C:\Users\Administrator>D:

D:\>cd D:\Program Files\ffmpeg

D:\Program Files\ffmpeg>cd bin

D:\Program Files\ffmpeg\bin>ffmpeg.exe -i shanzhu.mp4 shanzhu.avi
ffmpeg version N-91949-g6304268e39 Copyright (c) 2000-2018 the FFmpeg developers
built with gcc 8.2.1 (GCC) 20180813
configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth
libavutil 56. 19.101 / 56. 19.101
libavcodec 58. 30.100 / 58. 30.100
libavformat 58. 18.100 / 58. 18.100
libavdevice 58. 4.103 / 58. 4.103
libavfilter 7. 31.100 / 7. 31.100
libswscale 5. 2.100 / 5. 2.100
libswresample 3. 2.100 / 3. 2.100
libpostproc 55. 2.100 / 55. 2.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'shanzhu.mp4':
Metadata:
major_brand : mp42
minor_version : 1
compatible_brands: mp41mp42isom
creation_time : 2018-09-16T05:29:47.000000Z
Duration: 00:00:09.34, start: 0.000000, bitrate: 1210 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 544x960, 1159 kb/s, 29.97 fps, 29.97 tbr, 600 tbn, 1200 tbc (default)
Metadata:
creation_time : 2018-09-16T05:29:47.000000Z
handler_name : Core Media Video
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 46 kb/s (default)
Metadata:
creation_time : 2018-09-16T05:29:47.000000Z
handler_name : Core Media Audio
Stream mapping:
Stream #0:0 -> #0:0 (h264 (native) -> mpeg4 (native))
Stream #0:1 -> #0:1 (aac (native) -> mp3 (libmp3lame))
Press [q] to stop, [?] for help
Output #0, avi, to 'shanzhu.avi':
Metadata:
major_brand : mp42
minor_version : 1
compatible_brands: mp41mp42isom
ISFT : Lavf58.18.100
Stream #0:0(und): Video: mpeg4 (FMP4 / 0x34504D46), yuv420p, 544x960, q=2-31, 200 kb/s, 29.97 fps, 29.97 tbn, 29.97 tbc (default)
Metadata:
creation_time : 2018-09-16T05:29:47.000000Z
handler_name : Core Media Video
encoder : Lavc58.30.100 mpeg4
Side data:
cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1
Stream #0:1(und): Audio: mp3 (libmp3lame) (U[0][0][0] / 0x0055), 44100 Hz, mono, fltp (default)
Metadata:
creation_time : 2018-09-16T05:29:47.000000Z
handler_name : Core Media Audio
encoder : Lavc58.30.100 libmp3lame
frame= 280 fps=0.0 q=31.0 Lsize= 1096kB time=00:00:09.34 bitrate= 961.3kbits/s speed=16.7x
video:999kB audio:72kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 2.338377%

  • java程序调用cmd转换视频

springboot-common中添加FFMpegTest

package com.idig8.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 -y output.avi
List<String> command = new ArrayList<>();
command.add(ffmpegEXE); command.add("-i");
command.add(videoInputPath);
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) {
FFMpegTest ffmpeg = new FFMpegTest("D:\\Program Files\\ffmpeg\\bin\\ffmpeg.exe");
try {
ffmpeg.convertor("D:\\Program Files\\ffmpeg\\bin\\shanzhu.mp4", "D:\\Program Files\\ffmpeg\\bin\\shanzhu.avi");
} catch (Exception e) {
e.printStackTrace();
}
} }
  • 视频音频合并命令
    > 通过这种方式,可以让我们的mp4和我们的mp3 做一个结合。
ffmpeg.exe -i shanzhu.avi -i music.mp3 -t 10 -y 合并音乐和视频.avi

D:\Program Files\ffmpeg\bin>ffmpeg.exe -i shanzhu.avi -i music.mp3 -t 10 -y 合并音乐和视频.avi
ffmpeg version N-91949-g6304268e39 Copyright (c) 2000-2018 the FFmpeg developers
built with gcc 8.2.1 (GCC) 20180813
configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libspeex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth
libavutil 56. 19.101 / 56. 19.101
libavcodec 58. 30.100 / 58. 30.100
libavformat 58. 18.100 / 58. 18.100
libavdevice 58. 4.103 / 58. 4.103
libavfilter 7. 31.100 / 7. 31.100
libswscale 5. 2.100 / 5. 2.100
libswresample 3. 2.100 / 3. 2.100
libpostproc 55. 2.100 / 55. 2.100
Input #0, avi, from 'shanzhu.avi':
Metadata:
encoder : Lavf58.18.100
Duration: 00:00:09.38, start: 0.000000, bitrate: 957 kb/s
Stream #0:0: Video: mpeg4 (Simple Profile) (FMP4 / 0x34504D46), yuv420p, 544x960 [SAR 1:1 DAR 17:30], 876 kb/s, 29.97 fps, 29.97 tbr, 29.97 tbn, 30k tbc
Stream #0:1: Audio: mp3 (U[0][0][0] / 0x0055), 44100 Hz, mono, fltp, 64 kb/s
[mp3 @ 000001fcfa57d6c0] Estimating duration from bitrate, this may be inaccurate
Input #1, mp3, from 'music.mp3':
Duration: 00:00:33.47, start: 0.000000, bitrate: 320 kb/s
Stream #1:0: Audio: mp3, 48000 Hz, stereo, fltp, 320 kb/s
Stream mapping:
Stream #0:0 -> #0:0 (mpeg4 (native) -> mpeg4 (native))
Stream #1:0 -> #0:1 (mp3 (mp3float) -> mp3 (libmp3lame))
Press [q] to stop, [?] for help
Output #0, avi, to '鍚堝苟闊充箰鍜岃棰?avi':
Metadata:
ISFT : Lavf58.18.100
Stream #0:0: Video: mpeg4 (FMP4 / 0x34504D46), yuv420p(progressive), 544x960 [SAR 1:1 DAR 17:30], q=2-31, 200 kb/s, 29.97 fps, 29.97 tbn, 29.97 tbc
Metadata:
encoder : Lavc58.30.100 mpeg4
Side data:
cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1
Stream #0:1: Audio: mp3 (libmp3lame) (U[0][0][0] / 0x0055), 48000 Hz, stereo, fltp
Metadata:
encoder : Lavc58.30.100 libmp3lame
frame= 280 fps=274 q=31.0 Lsize= 1076kB time=00:00:10.00 bitrate= 880.4kbits/s speed=9.79x
video:892kB audio:157kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 2.510280%
  • java程序调用cmd转换视频增加音频
package com.idig8.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 苏州大裤衩.mp4 -i bgm.mp3 -t 7 -y 新的视频.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("D:\\Program Files\\ffmpeg\\bin\\ffmpeg.exe");
try {
ffmpeg.convertor("D:\\Program Files\\ffmpeg\\bin\\shanzhu.mp4", "D:\\Program Files\\ffmpeg\\bin\\music.mp3", 7.1, "D:\\Program Files\\ffmpeg\\bin\\合并音乐和视频.avi");
} catch (Exception e) {
e.printStackTrace();
}
} }

开发功能

视频上传后通过java调用ffmpge.exe完成音乐和视频的合并,并将视频信息保存在数据库中。

  • 视频service开发
    VideoService
package com.idig8.service;

import com.idig8.pojo.Videos;

public interface VideoService {

    /**
* 保存视频信息
* @param Id
* @return
*/
public void saveVideo(Videos video);
}

VideoServiceImpl

package com.idig8.service.Impl;

import java.util.List;

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.idig8.mapper.BgmMapper;
import com.idig8.pojo.Bgm;
import com.idig8.service.BgmService; @Service
public class BgmServiceImpl implements BgmService { @Autowired
private BgmMapper bgmMapper; @Transactional(propagation =Propagation.SUPPORTS)
@Override
public List<Bgm> queryBgmList(){ return bgmMapper.selectAll();
} @Transactional(propagation =Propagation.SUPPORTS)
@Override
public Bgm queryBgmById(String Id){ return bgmMapper.selectByPrimaryKey(Id);
} }

BgmService

package com.idig8.service;

import java.util.List;

import com.idig8.pojo.Bgm;

public interface BgmService {

    /**
* 获取所有的Bgm列表
* @return
*/
public List<Bgm> queryBgmList(); /**
* 通过bgmId获取Bgm对象
* @param Id
* @return
*/
public Bgm queryBgmById(String Id);
}

BgmServiceImpl

package com.idig8.service.Impl;

import java.util.List;

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.idig8.mapper.BgmMapper;
import com.idig8.pojo.Bgm;
import com.idig8.service.BgmService; @Service
public class BgmServiceImpl implements BgmService { @Autowired
private BgmMapper bgmMapper; @Transactional(propagation =Propagation.SUPPORTS)
@Override
public List<Bgm> queryBgmList(){ return bgmMapper.selectAll();
} @Transactional(propagation =Propagation.SUPPORTS)
@Override
public Bgm queryBgmById(String Id){ return bgmMapper.selectByPrimaryKey(Id);
} }

VideoController

package com.idig8.controller;

import java.io.File;
import java.util.Date;
import java.util.UUID; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import com.idig8.pojo.Bgm;
import com.idig8.pojo.Videos;
import com.idig8.service.BgmService;
import com.idig8.service.VideoService;
import com.idig8.utils.JSONResult;
import com.idig8.utils.MergeVideoMp3;
import com.idig8.utils.enums.VideoStatusEnum;
import com.idig8.utils.file.FileUtil; 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 videosService; @Value("${server.file.path}")
private String fileSpace; @Value("${server.ffmpeg.path}")
private String ffmpegexe; @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 JSONResult upload(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 JSONResult.errorMsg("用户id不能为空...");
}
// 文件保存的命名空间
String fileName = file.getOriginalFilename();
// 保存到数据库中的相对路径
String path = "";
String videOutPath = "";
try {
path = FileUtil.uploadFile(file.getBytes(), fileSpace, fileName);
} catch (Exception e) {
e.getStackTrace();
return JSONResult.errorMsg(e.getMessage());
} if(StringUtils.isNotBlank(bgmId)){
Bgm bgm = bgmService.queryBgmById(bgmId);
String mp3BgmPath = fileSpace + bgm.getPath();
MergeVideoMp3 mergeVideoMp3 = new MergeVideoMp3(ffmpegexe);
String videOutPathName = UUID.randomUUID().toString()+".mp4";
File targetFile = new File(fileSpace + userId);
if (!targetFile.exists()) {
targetFile.mkdirs();
}
videOutPath = "/"+userId+"/"+videOutPathName;
String videoInput = fileSpace +path;
mergeVideoMp3.convertor(videoInput, mp3BgmPath, videoSeconds, fileSpace +videOutPath);
} Videos videos = new Videos();
videos.setAudioId(bgmId);
videos.setCreateTime(new Date());
videos.setVideoDesc(desc);
videos.setId(UUID.randomUUID().toString());
videos.setUserId(userId);
videos.setVideoHeight(videoHeight);
videos.setVideoWidth(videoWidth);
videos.setVideoPath(videOutPath);
videos.setStatus(VideoStatusEnum.SUCCESS.value);
videosService.saveVideo(videos); return JSONResult.ok(path); }
}

PS:已经完成了视频的上传,并把相关的信息保存在数据库中。

「小程序JAVA实战」小程序视频处理工具ffmpeg(47)的更多相关文章

  1. 「小程序JAVA实战」小程序视频封面处理(48)

    转自:https://idig8.com/2018/09/16/xiaochengxujavashizhanxiaochengxushipinfengmianchuli47/ 截图这块,在微信小程序工 ...

  2. 「小程序JAVA实战」小程序的flex布局(22)

    转自:https://idig8.com/2018/08/09/xiaochengxu-chuji-22/ 之前已经把小程序的框架说完了,接下来说说小程序的组件,在说组件之前,先说说布局吧.源码:ht ...

  3. 「小程序JAVA实战」小程序的留言和评价功能(70)

    转自:https://idig8.com/2018/10/28/xiaochengxujavashizhanxiaochengxudeliuyanhepingjiagongneng69/ 目前小程序这 ...

  4. 「小程序JAVA实战」小程序的举报功能开发(68)

    转自:https://idig8.com/2018/09/25/xiaochengxujavashizhanxiaochengxudeweixinapicaidancaozuo66-2/ 通过点击举报 ...

  5. 「小程序JAVA实战」小程序的个人信息作品,收藏,关注(66)

    转自:https://idig8.com/2018/09/24/xiaochengxujavashizhanxiaochengxudegerenxinxizuopinshoucangguanzhu65 ...

  6. 「小程序JAVA实战」小程序的关注功能(65)

    转自:https://idig8.com/2018/09/24/xiaochengxujavashizhanxiaochengxudeguanzhugongneng64/ 在个人页面,根据发布者个人和 ...

  7. 「小程序JAVA实战」小程序的视频点赞功能开发(62)

    转自:https://idig8.com/2018/09/24/xiaochengxujavashizhanxiaochengxudeshipindianzangongnengkaifa61/ 视频点 ...

  8. 「小程序JAVA实战」小程序的springboot后台拦截器(61)

    转自:https://idig8.com/2018/09/24/xiaochengxujavashizhanxiaochengxudespringboothoutailanjieqi60/ 之前咱们把 ...

  9. 「小程序JAVA实战」小程序首页视频(49)

    转自:https://idig8.com/2018/09/21/xiaochengxujavashizhanxiaochengxushouyeshipin48/ 视频显示的内容是视频的截图,用户的头像 ...

随机推荐

  1. openv+contrib配置总结

    本文转载于:https://www.cnblogs.com/wjy-lulu/p/6805557.html 开门见山的说:别用opencv3.0,这个版本添加扩展库不怎么好,能不能成功我不敢说,我是试 ...

  2. db2时间函数

    获取当前日期: select current date from sysibm.sysdummy1; values current date; --获取当前时间 select current time ...

  3. 【hive】分组求排名

    分组求排名 相信好多使用Mysql的用户一定对分组求排名的需求感到发怵. 但是在hive或者oracle来说就能简单实现. 采用窗口函数:rank() over() / row_number() ov ...

  4. 控制反转(IOC)模式

    控制反转(Inversion of Control):提倡实现松耦合层.组件和类的设计原则,颠倒程序的控制流程.IoC使用分离执行特定问题处理代码的概念: IoC意味着将你设计好的对象交给容器控制,而 ...

  5. 2018.12.21 Cmos- RF

    1 PSK 趋肤效应 50欧匹配 smith s参数 :在datasheet里面会有 Information coding Bluetooth : Continous Variable Slope D ...

  6. react native遇到的坑

    1.模拟器报错no bundle url present https://github.com/facebook/react-native/issues/12754 http://www.cnblog ...

  7. linux网络监控_网速测试

    Linux下查看网络即时网速 1.sar命令(一般般) sar -n DEV 1 100 1代表一秒统计并显示一次 100代表统计一百次 sar在sysstat包 2.使用ntop图形工具(没详细用过 ...

  8. PyalgoTrade 计算权重平滑平均价(三)

    本节介绍如何使用收盘价的SMA价格的策略 from pyalgotrade import strategy from pyalgotrade.barfeed import yahoofeed from ...

  9. CSS元素、边框、背景、列表样式

    一.元素样式 1.width控制元素宽度 2.height控制元素宽度 3.padding控制元素内边距 内容与边框之间的距离 4.margin控制元素外边距 元素边框与其他元素边框之间的距离,如果两 ...

  10. POI2013题解

    POI2013题解 只做了BZ上有的\(13\)道题. 就这样还扔了两道神仙构造和一道计算几何题.所以只剩下十道题了. [BZOJ3414][Poi2013]Inspector 肯定是先二分答案,然后 ...