ffmpeg视频转码相关
ffmpeg视频转码相关
- 简介
- 参数
- 实战举栗子
- 获取视频时长
- 视频转码
简介
FFmpeg 是领先的多媒体框架,能够解码、编码、 转码、复用、解复用、流、过滤和播放 几乎所有人类和机器创建的东西。
ffmpeg官网: https://ffmpeg.org/
ffmpeg中文网: https://ffmpeg.p2hp.com/
参数
-
基本操作
输入文件
-i input.mp4:指定输入文件。输出文件
output.mp4:指定输出文件名称。
-
视频参数
设置分辨率
-s 1280x720:设置输出视频的分辨率(宽x高)。设置帧率
-r 24:设置输出视频的帧率(帧每秒,FPS)。设置视频码率
-b:v 2000k:设置视频码率(比特率)。设置GOP大小
-g 48:设置GOP(组图像)大小,通常与帧率相关。设置封面
-ss 00:00:01:从指定时间点截取一帧作为封面(配合 -vframes 1 使用)。
-
音频参数
设置音频码率
-b:a 128k:设置音频码率。设置采样率
-ar 44100:设置音频采样率。选择音频通道
-ac 2:设置音频通道数(如立体声为2)。
- 格式转换
指定输出格式
-f mp4:强制指定输出格式。
-
截图和分片
截图
-ss 00:00:05 -vframes 1 output.jpg:从第5秒时间点截取一帧并保存为图片。分片输出
-f segment -segment_time 10 -c copy output%03d.mp4:将视频每10秒切成一个分片。
-
音视频同步
同步音视频
-async 1:在流式传输中同步音视频。声音延迟
-itsoffset 0.5 -i input.mp4:调整声音与视频的同步(+延迟/-提前)。
-
旋转或翻转视频
旋转video
-vf “rotate=90”:旋转视频90度(支持0,90,180,270度)。水平翻转
-vf “hflip”:水平翻转视频。垂直翻转
-vf “vflip”:垂直翻转视频。
-
过滤器
ffmpeg 支持复杂的过滤器链,例如:添加水印
-i watermark.png -filter_complex “overlay=W-w:0” output.mp4:在视频右下角添加水印。画中画
-i small.mp4 -filter_complex “overlay=main_w/2:main_h/2” output.mp4:在视频中插入另外一个小视频。
-
编码器
指定视频编码器
-c:v h264:使用H.264编码器。指定音频编码器
-c:a aac:使用AAC音频编码器。
-
时间控制
播放速度
-vf “setpts=2*PTS”:将视频速度加快2倍。剪辑视频
-ss 00:01:00 -t 00:01:00 -c copy output.mp4:从第1分钟开始剪辑1分钟的视频。提取音频
-vn -ar 44100 -ac 2 -ab 128k output.mp3:提取视频中的音频并保存为MP3。生成静音
-f lavfi -i anullsrc -c:a aac output.mka:生成一个没有视频的静音文件。
-
压缩和质量
CRF(质量控制)
-crf 18:设置视频质量(18-28,数值越小质量越高)。预设
-preset ultrafast:设置编码速度(如:ultrafast, superfast, veryfast, faster, fast, medium)。
示例
将 MP4 转换为 H.264 编码的 MKV:
ffmpeg -i input.mp4 -c:v h264 output.mkv
将视频压缩到1Mbps:
ffmpeg -i input.mp4 -c:v h264 -b:v 1000k output.mp4
提取视频的音频:
ffmpeg -i input.mp4 -vn -ar 44100 -ac 2 -ab 128k output.mp3
将视频旋转90度:
ffmpeg -i input.mp4 -vf “rotate=90” output.mp4
实战举栗子
获取视频时长
// Duration: 00:00:30.03, start: 0.000000, bitrate: 1191 kb/spublic String getVideoDuration(String inputFilePath) {Process process = null;try {// 定义远程视频的URL// 构建FFmpeg命令ProcessBuilder processBuilder = new ProcessBuilder(ffmpegPath, "-i",inputFilePath);// 读取FFmpeg的输出信息// 创建ProcessBuilder并执行命令processBuilder.redirectErrorStream(true);process = processBuilder.start();// 读取FFmpeg命令输出BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));String line;while ((line = reader.readLine()) != null) {if (line.contains("Duration:")) {// 获取包含视频时长信息的行String durationLine = line.split("Duration:")[1].split(",")[0].split("\\.")[0].trim();// 00:00:30
// String durationLine = line.split("Duration:")[1].split(",")[0].trim();// 00:00:30.03
// String[] durationParts = durationLine.split(":");
// int hours = Integer.parseInt(durationParts[0].trim());
// int minutes = Integer.parseInt(durationParts[1].trim());
// double seconds = Double.parseDouble(durationParts[2].trim());
// // 计算总秒数
// double totalSeconds = hours * 3600 + minutes * 60 + seconds;System.out.println("视频时长:" + durationLine);return durationLine;}}reader.close();} catch (IOException e) {e.printStackTrace();if (process != null) {process.destroyForcibly(); // 如果发生异常,强制终止进程}} finally {if (process != null) {process.destroyForcibly(); // 强制终止进程}}System.out.println("无法获取视频时长。");return null;}public Integer getVideoDurationSecond(String inputFilePath) {String videoDuration = getVideoDuration(inputFilePath);if (videoDuration == null) {return 0;}String[] durationParts = videoDuration.split(":");int hours = Integer.parseInt(durationParts[0].trim());int minutes = Integer.parseInt(durationParts[1].trim());int seconds = Integer.parseInt(durationParts[2].trim());// 计算总秒数return hours * 3600 + minutes * 60 + seconds;}
视频转码
public void transcodeVideo(String inputFilePath, String outputFilePath) {ProcessBuilder processBuilder = new ProcessBuilder(ffmpegPath, "-i",inputFilePath, "-c:v", "libx264", "-c:a", "aac", outputFilePath);try {processBuilder.inheritIO(); // 将FFmpeg的输出信息打印到控制台
// processBuilder.redirectErrorStream(true); // 合并错误输出流Process process = processBuilder.start();int exitCode = process.waitFor();if (exitCode == 0) {log.info("视频转码成功!");} else {log.info("视频转码失败!");}} catch (IOException | InterruptedException e) {e.printStackTrace();}}
参数后续……