内容简介:前面已经把视频成功的上传到我们的服务器,选择了背景音乐的ID,现在需要把视频和背景音乐进行合并,需要使用一个工具ffmpeg。源码:https://github.com/limingios/wxProgram.git 中wx-springboot 和 No.15根据你的需求进行下载,我选择在windows平台来进行下载
前面已经把视频成功的上传到我们的服务器,选择了背景音乐的ID,现在需要把视频和背景音乐进行合并,需要使用一个工具ffmpeg。源码:https://github.com/limingios/wxProgram.git 中wx-springboot 和 No.15
ffmpeg
-
介绍
>视音频处理工具,跨平台的视音频处理解决方案,主页:http://ffmpeg.org
- 应用的场景
- 播放器:射手播放器,暴风影音,迅雷播放器……
- 转换工具:格式工厂,剪辑工具……
- 直播,视频加码,滤镜,水印,特效……
-
下载
根据你的需求进行下载,我选择在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:已经完成了视频的上传,并把相关的信息保存在数据库中。
>>原创文章,欢迎转载。转载请注明:转载自IT人故事会,谢谢!
>>原文链接地址:
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 「小程序JAVA实战」小程序搜索功能(54)
- 「小程序JAVA实战」小程序视频封面处理(47)
- 「小程序JAVA实战」小程序开源搜索组件(52)
- 「小程序JAVA实战」小程序的关注功能(64)
- 「小程序JAVA实战」小程序注册界面的开发(29)
- 「小程序JAVA实战」小程序数据缓存API(53)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Programming in Haskell
Graham Hutton / Cambridge University Press / 2007-1-18 / GBP 34.99
Haskell is one of the leading languages for teaching functional programming, enabling students to write simpler and cleaner code, and to learn how to structure and reason about programs. This introduc......一起来看看 《Programming in Haskell》 这本书的介绍吧!