java使用FFmpeg合成视频和音频并获取视频中的音频等操作(实例代码详解)
作者:shshjj 发布时间:2023-10-28 15:42:24
FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。
ffmpeg命令参数如下:
通用选项
-L license
-h 帮助
-fromats 显示可用的格式,编解码的,协议的。。。
-f fmt 强迫采用格式fmt
-I filename 输入文件
-y 覆盖输出文件
-t duration 设置纪录时间 hh:mm:ss[.xxx]格式的记录时间也支持
-ss position 搜索到指定的时间 [-]hh:mm:ss[.xxx]的格式也支持
-title string 设置标题
-author string 设置作者
-copyright string 设置版权
-comment string 设置评论
-target type 设置目标文件类型(vcd,svcd,dvd) 所有的格式选项(比特率,编解码以及缓冲区大小)自动设置 ,只需要输入如下的就可以了:
ffmpeg -i myfile.avi -target vcd /tmp/vcd.mpg
-hq 激活高质量设置
-itsoffset offset 设置以秒为基准的时间偏移,该选项影响所有后面的输入文件。该偏移被加到输入文件的时戳,定义一个正偏移意味着相应的流被延迟了 offset秒。 [-]hh:mm:ss[.xxx]的格式也支持
视频选项
-b bitrate 设置比特率,缺省200kb/s
-r fps 设置帧频 缺省25
-s size 设置帧大小 格式为WXH 缺省160X128.下面的简写也可以直接使用:
Sqcif 128X96 qcif 176X144 cif 252X288 4cif 704X576
-aspect aspect 设置横纵比 4:3 16:9 或 1.3333 1.7777
-croptop size 设置顶部切除带大小 像素单位
-cropbottom size –cropleft size –cropright size
-padtop size 设置顶部补齐的大小 像素单位
-padbottom size –padleft size –padright size –padcolor color 设置补齐条颜色(hex,6个16进制的数,红:绿:兰排列,比如 000000代表黑色)
-vn 不做视频记录
-bt tolerance 设置视频码率容忍度kbit/s
-maxrate bitrate设置最大视频码率容忍度
-minrate bitreate 设置最小视频码率容忍度
-bufsize size 设置码率控制缓冲区大小
-vcodec codec 强制使用codec编解码方式。 如果用copy表示原始编解码数据必须被拷贝。
-sameq 使用同样视频质量作为源(VBR)
-pass n 选择处理遍数(1或者2)。两遍编码非常有用。第一遍生成统计信息,第二遍生成精确的请求的码率
-passlogfile file 选择两遍的纪录文件名为file
高级选项
-g gop_size 设置图像组大小
-intra 仅适用帧内编码
-qscale q 使用固定的视频量化标度(VBR)
-qmin q 最小视频量化标度(VBR)
-qmax q 最大视频量化标度(VBR)
-qdiff q 量化标度间最大偏差 (VBR)
-qblur blur 视频量化标度柔化(VBR)
-qcomp compression 视频量化标度压缩(VBR)
-rc_init_cplx complexity 一遍编码的初始复杂度
-b_qfactor factor 在p和b帧间的qp因子
-i_qfactor factor 在p和i帧间的qp因子
-b_qoffset offset 在p和b帧间的qp偏差
-i_qoffset offset 在p和i帧间的qp偏差
-rc_eq equation 设置码率控制方程 默认tex^qComp
-rc_override override 特定间隔下的速率控制重载
-me method 设置运动估计的方法 可用方法有 zero phods log x1 epzs(缺省) full
-dct_algo algo 设置dct的算法 可用的有 0 FF_DCT_AUTO 缺省的DCT 1 FF_DCT_FASTINT 2 FF_DCT_INT 3 FF_DCT_MMX 4 FF_DCT_MLIB 5 FF_DCT_ALTIVEC
-idct_algo algo 设置idct算法。可用的有 0 FF_IDCT_AUTO 缺省的IDCT 1 FF_IDCT_INT 2 FF_IDCT_SIMPLE 3 FF_IDCT_SIMPLEMMX 4 FF_IDCT_LIBMPEG2MMX 5 FF_IDCT_PS2 6 FF_IDCT_MLIB 7 FF_IDCT_ARM 8 FF_IDCT_ALTIVEC 9 FF_IDCT_SH4 10 FF_IDCT_SIMPLEARM
-er n 设置错误残留为n 1 FF_ER_CAREFULL 缺省 2 FF_ER_COMPLIANT 3 FF_ER_AGGRESSIVE 4 FF_ER_VERY_AGGRESSIVE
-ec bit_mask 设置错误掩蔽为bit_mask,该值为如下值的位掩码 1 FF_EC_GUESS_MVS (default=enabled) 2 FF_EC_DEBLOCK (default=enabled)
-bf frames 使用frames B 帧,支持mpeg1,mpeg2,mpeg4
-mbd mode 宏块决策 0 FF_MB_DECISION_SIMPLE 使用mb_cmp 1 FF_MB_DECISION_BITS 2 FF_MB_DECISION_RD
-4mv 使用4个运动矢量 仅用于mpeg4
-part 使用数据划分 仅用于mpeg4
-bug param 绕过没有被自动监测到编码器的问题
-strict strictness 跟标准的严格性
-aic 使能高级帧内编码 h263+
-umv 使能无限运动矢量 h263+
-deinterlace 不采用交织方法
-interlace 强迫交织法编码 仅对mpeg2和mpeg4有效。当你的输入是交织的并且你想要保持交织以最小图像损失的时候采用该选项。可选的方法是不交织,但是损失更大
-psnr 计算压缩帧的psnr
-vstats 输出视频编码统计到vstats_hhmmss.log
-vhook module 插入视频处理模块 module 包括了模块名和参数,用空格分开
音频选项
-ab bitrate 设置音频码率
-ar freq 设置音频采样率
-ac channels 设置通道 缺省为1
-an 不使能音频纪录
-acodec codec 使用codec编解码
音视频捕获选项
-vd device 设置视频捕获设备。比如/dev/video0
-vc channel 设置视频捕获通道 DV1394专用
-tvstd standard 设置电视标准 NTSC PAL(SECAM)
-dv1394 设置DV1394捕获
-av device 设置音频设备 比如/dev/dsp
高级选项
-map file:stream 设置输入流映射
-debug 打印特定调试信息
-benchmark 为基准测试加入时间
-hex 倾倒每一个输入包
-bitexact 仅使用位精确算法 用于编解码测试
-ps size 设置包大小,以bits为单位
-re 以本地帧频读数据,主要用于模拟捕获设备
-loop 循环输入流。只工作于图像流,用于ffserver测试
横向合并视频
ffmpeg -i input1.mp4 -i input2.mp4 -lavfi hstack output.mp4
上面的命令虽然可以合并视频,两个视频可以正常播放,但是只保留了前面一个的音频。
下面会介绍怎么避开这个坑。
注意这时候input1和input2必须同样的高度,如果不一样的高度可以使用-shortest参数来保证同样的高度。
如果希望合并多个视频,可以使用下面命令行。
ffmpeg -i input1.mp4 -i input2.mp4 -i input3.mp4 -lavfi hstack=inputs=3 output.mp4
其中input=3表示希望合并的视频的个数
纵向合并视频
ffmpeg -i input1.mp4 -i input2.mp4 -lavfi vstack output.mp4
网格合并视频
当多个视频时,还可以合并成网格状,比如2x2,3x3这种。但是视频个数不一定需要是偶数,如果是奇数,可以用黑色图片来占位。
ffmpeg -f lavfi -i color=c=black:s=1280x720 -vframes 1 black.png
该命令将创建一张1280*720的图片
然后就可以使用下面这个命令来合并成网格视频了,如果只有三个视频,可以选择上面创建的黑色图片替代。
ffmpeg -i top_left.mp4 -i top_right.mp4 -i bottom_left.mp4 -i bottom_right.mp4 \
-lavfi "[0:v][1:v]hstack[top];[2:v][3:v]hstack[bottom];[top][bottom]vstack"
-shortest 2by2grid.mp4
上面创建的是正规的2x2网格视频。想象一下,现在只有三个视频,我想把第一个视频摆放在第一行的中间,然后把第二、三个视频摆放在第二行。那么就可以使用下面两个命令了。
ffmpeg -f lavfi -i color=c=black:s=640x720 -vframes 1 black.png
ffmpeg -i black.png -i top_center.mp4 -i bottom_left.mp4 -i bottom_right.mp4
-lavfi "[0:v][1:v][0:v]hstack=inputs=3[top];[2:v][3:v]hstack[bottom];[top][bottom]vstack"
-shortest 3_videos_2x2_grid.mp4
合并音频和视频
ffmpeg -i video.mp4 -i audio.wav -c:v copy -c:a aac -strict experimental output.mp4
如果视频中已经包含了音频,这个时候还可以替换视频中的音频,使用下面命令行。
ffmpeg -i video.mp4 -i audio.wav -c:v copy -c:a aac -strict experimental
-map 0:v:0 -map 1:a:0 output.mp4
合并两个音频
ffmpeg -i input1.mp3 -i input2.mp3 -filter_complex amerge -ac 2 -c:a libmp3lame -q:a 4 output.mp3
获取视频中的音频
ffmpeg -i input.mp4 -vn -y -acodec copy output.m4a
去掉视频中的音频
ffmpeg -i input.mp4 -an output.mp4
现在介绍,怎么合并两个视频并保留两个视频中的音频。也就是抖音中的合拍功能。
1.合并两个视频,但是发现只有一个声音。无所谓。
2.抽取两个视频中的音频,然后合并成一个音频。
3.将这个音频替换到之前的合并视频中。
4.ok了。
5.可以使用ffplay播放了。
附上java代码,可直接使用。使用前需要先将FFmpeg的bin目录配置在环境变量中。配置完成后,在cmd中拼 ffmpeg -version
如果能ping通说明配置成功,然后直接使用以下代码即可成功。
package com.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
/**
* 视频中获取音频文件
*/
public class VideoUtils {
//FFmpeg全路径
private static final String FFMPEG_PATH = "D:\\666\\ffmpeg-20190730-a0c1970-win64-static\\bin\\ffmpeg.exe";
//音频保存路径
private static final String TMP_PATH = "D:\\666";
/**
* 从视频中提取音频信息
* @param videoUrl
* @return
*/
public static String videoToAudio(String videoUrl){
String aacFile = "";
try {
aacFile = TMP_PATH + "/" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())
+ UUID.randomUUID().toString().replaceAll("-", "") + ".mp3";
String command = FFMPEG_PATH + " -i "+ videoUrl + " -vn -acodec copy "+ aacFile;
System.out.println("video to audio command : " + command);
Process process = Runtime.getRuntime().exec(command);
process.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
public static void main(String[] args){
try {
// videoToAudio("D:\\laji\\2.mp4");
String videoInputPath = "D:\\laji\\aa.mp4";
String audioInputPath = "D:\\laji\\a.mp3";
String videoOutPath = "D:\\laji\\bb1.avi";
convetor(videoInputPath,audioInputPath,videoOutPath);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("---------获取音频文件成功!-----------");
}
/**
* @param videoInputPath 原视频的全路径
* @param audioInputPath 音频的全路径
* @param videoOutPath 视频与音频结合之后的视频的路径
* @throws Exception
*/
public static void convetor(String videoInputPath, String audioInputPath, String videoOutPath)
throws Exception {
Process process = null;
try {
String command =FFMPEG_PATH + " -i " + videoInputPath + " -i " + audioInputPath + " -c:v copy -c:a aac -strict experimental " +
" -map 0:v:0 -map 1:a:0 "
+ " -y " + videoOutPath;
process = Runtime.getRuntime().exec(command);
process.waitFor();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 使用这种方式会在瞬间大量消耗CPU和内存等系统资源,所以这里我们需要对流进行处理
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();
}
}
}
来源:https://blog.csdn.net/shshjj/article/details/98185454


猜你喜欢
- 废话不多说,直接上代码: 很简单:将类复制到项目中,最后在配置文件上配置一下:logUrl即可。 默认保存在:项目/temp/lo
- 背景随着富客户端框架的盛行,以及众多优秀的前端js框架,很多情况我们会遇到跨域的问题,而js的ajax请求是不允许直接跨域访问的,当然你会说
- Android 列表选择框 Spinner详解及实例Spinner 是 Android 的列表选择框,不过 spinner 并不需要显示下拉
- 笔者在网上发现了,很多种方法 ,当然咱们找最好用的,也简单的 下面废话不多说直接上代码 我在啰嗦几句 第一这个脚本挂在需要相应的游戏体上 第
- 本文实例为大家分享了C#简单爬虫案例,供大家参考,具体内容如下using System;using System.Collections.G
- C#事件使用+= -=使用起来是很方便的,但是却不能整体清空所有事件。比如一个常见的操作,打开界面注册监听事件,关闭界面需要把所有的事件清空
- > 因为我的工作要用kotlin所以今天在这里给大家总结一下关于全局语言切换的kotlin语言实现实现,很简单,希望在这里可以帮助到有
- 函数名称 说明ActiveKeyboardLayout 激活一个不同的键盘布局,该布局必须先由 LoadKeyBoardLayout函数装载
- Android RadioButton 图片位置与大小Java:rgGroup = (RadioGroup) findViewById(R.
- 怎么使用异步,就是用委托进行处理,如果委托对象在调用列表中只有一个方法,它就可以异步执行这个方法。委托类有两个方法
- 本文实例为大家分享了SeekBar拖动条的应用代码,供大家参考,具体内容如下目标效果在该页面中放一个拖动条的状态提示信息,一个拖动条以及一个
- 本文实例讲述了C#实现求一组数据众数的方法。分享给大家供大家参考。具体如下:1.算法描述1)输入合法性检验(输入不能为空)2)制作数组副本,
- 初学Android编程,Android SDK中提供的Sample代码自然是最好的学习材料。 
- 对于一些特殊的情况,split拆分后并没有保留全的元素如下例子:String x ="a,,,,,,";String [
- pom.xml文件中添加如下配置项创建maven项目后,在pom.xml文件中添加如下配置项:<properties> &nbs
- 阿里、华为、腾讯Java技术面试题精选,具体内容如下JVM的类加载机制是什么?有哪些实现方式?类加载机制:类的加载指的是将类的.class文
- 0.前言文章需求:对于学生来说,目前网上确实没有比较统一而且质量好的支付教程。因为支付对个人开发者尤其是学生来说不太友好。因此,自己折腾两天
- 1.前言1.1.FastJson的介绍:JSON(javaScript Object Notation)是一种轻量级的数据交换格式。主要采用
- 我就废话不多说了,大家还是直接看代码吧~private LineRenderer line1; &
- 线程封闭线程封闭一般通过以下三个方法:Ad-hoc线程封闭:程序控制实现,最糟糕,忽略堆栈封闭:局部变量,无并发问题ThreadLocal线