前面已經把視頻成功的上傳到我們的服務器,選擇了背景音樂的ID,現在需要把視頻和背景音樂進行合并,需要使用一個工具ffmpeg。源碼:https://github.com/limingios/wxProgram.git 中wx-springboot 和 No.15
介紹
>視音頻處理工具,跨平臺的視音頻處理解決方案,主頁:http://ffmpeg.org

應用的場景
播放器:射手播放器,暴風影音,迅雷播放器……
轉換工具:格式工廠,剪輯工具……
直播,視頻加碼,濾鏡,水印,特效……
下載
根據你的需求進行下載,我選擇在windows平臺來進行下載



測試



C:UsersAdministrator>D: D:>cd?D:Program?Filesffmpeg D:Program?Filesffmpeg>cd?bin D:Program?Filesffmpegbin>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:?h364?(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?(h364?(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?Filesffmpegbin>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:已經完成了視頻的上傳,并把相關的信息保存在數據庫中。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。