「小程序JAVA实战」小程序视频处理工具ffmpeg(47)
转自;https://idig8.com/2018/09/16/xiaochengxujavashizhanxiaochengxushipinchuligongjuffmpeg46/
前面已经把视频成功的上传到我们的服务器,选择了背景音乐的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:已经完成了视频的上传,并把相关的信息保存在数据库中。
「小程序JAVA实战」小程序视频处理工具ffmpeg(47)的更多相关文章
- 「小程序JAVA实战」小程序视频封面处理(48)
转自:https://idig8.com/2018/09/16/xiaochengxujavashizhanxiaochengxushipinfengmianchuli47/ 截图这块,在微信小程序工 ...
- 「小程序JAVA实战」小程序的flex布局(22)
转自:https://idig8.com/2018/08/09/xiaochengxu-chuji-22/ 之前已经把小程序的框架说完了,接下来说说小程序的组件,在说组件之前,先说说布局吧.源码:ht ...
- 「小程序JAVA实战」小程序的留言和评价功能(70)
转自:https://idig8.com/2018/10/28/xiaochengxujavashizhanxiaochengxudeliuyanhepingjiagongneng69/ 目前小程序这 ...
- 「小程序JAVA实战」小程序的举报功能开发(68)
转自:https://idig8.com/2018/09/25/xiaochengxujavashizhanxiaochengxudeweixinapicaidancaozuo66-2/ 通过点击举报 ...
- 「小程序JAVA实战」小程序的个人信息作品,收藏,关注(66)
转自:https://idig8.com/2018/09/24/xiaochengxujavashizhanxiaochengxudegerenxinxizuopinshoucangguanzhu65 ...
- 「小程序JAVA实战」小程序的关注功能(65)
转自:https://idig8.com/2018/09/24/xiaochengxujavashizhanxiaochengxudeguanzhugongneng64/ 在个人页面,根据发布者个人和 ...
- 「小程序JAVA实战」小程序的视频点赞功能开发(62)
转自:https://idig8.com/2018/09/24/xiaochengxujavashizhanxiaochengxudeshipindianzangongnengkaifa61/ 视频点 ...
- 「小程序JAVA实战」小程序的springboot后台拦截器(61)
转自:https://idig8.com/2018/09/24/xiaochengxujavashizhanxiaochengxudespringboothoutailanjieqi60/ 之前咱们把 ...
- 「小程序JAVA实战」小程序首页视频(49)
转自:https://idig8.com/2018/09/21/xiaochengxujavashizhanxiaochengxushouyeshipin48/ 视频显示的内容是视频的截图,用户的头像 ...
随机推荐
- Appium 自动化测试(8) -- Appium Python client -- API
最好的学习方法,就是看源码! 在 \appium\webdriver\webdriver.py ,新增了两个封装好定位安卓元素的方法,如 find_element_by_accessibility ...
- 2-10~2-11 配置iptables防火墙增强服务 selinux简单讲解
学习一个服务的过程: 1.此服务器的概述:名字,功能,特点,端口号 2.安装 3.配置文件的位置 4.服务启动关闭脚本,查看端口 5.此服务的使用方法 6.修改配置文件,实战举例 7.排错(从下到上, ...
- 棋盘分割(二维区间DP)
题目大意:给一个棋盘,棋盘上每个格子中都有一个值,现在需要将棋盘切成n个矩形,总共切n-1刀,求最小的均方差.均方差定义为:,其中. 题目分析:将均方差化简得到:均方差2=(Σxi2)/n-平均值2. ...
- poj1191 棋盘分割。 dp
连接:http://poj.org/problem?id=1191 思路:额,其实就是直接搞记录一下就可以了. #include <stdio.h> #include <string ...
- CF86D
题解: 莫队分块 分块大小为sqrt(n) 代码: #include<bits/stdc++.h> using namespace std; ; typedef long long ll; ...
- css中用#id.class的形式定义样式,为什么这样用,不直接写成.class.代码如下:#skin_0.selected{}这种的
<ul class="skin"> <li id="skin_0" title="蓝色" class="sele ...
- timer Compliant Controller project (4)layout and gerber, paning
1 LAYOUT 2 Gerber 3 CAM350-Paining
- 响应: 500 OOPS: priv_sock_get_int 错误: 读取目录列表失败
/************************************************************************* * 响应: 500 OOPS: priv_sock ...
- PyQt4 py2exe 打包 HardwareManager
#!/usr/bin/env python # -*- coding: UTF-8 -*- # 1. 以下代码保存在HardwareManager项目的目录下,名称叫:setup.py: # 2. 打 ...
- JS 实战1(添加、删除)
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs ...