ffmpeg視頻轉碼相關
- 簡介
- 參數
- 實戰舉栗子
- 獲取視頻時長
- 視頻轉碼
- mp4文件轉為hls m3u8 ts等文件
- 圖片轉視頻
- 抽取視頻第一幀
- 獲取基本信息
- 轉碼日志輸出詳解
- 轉碼耗時測試
簡介
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();}}
mp4文件轉為hls m3u8 ts等文件
public void convertMp4ToM3u8(String inputFilePath, String outputDirectory, String defineOutputFileName) {File inputFile = new File(inputFilePath);if (!inputFile.exists()) {throw new IllegalArgumentException("Input file not found: " + inputFilePath);}File outputDir = new File(outputDirectory);if (!outputDir.exists()) {outputDir.mkdirs();}// Output filename without extensionString outputFileName = inputFile.getName().replaceFirst("[.][^.]+$", "");if (StringUtils.isNotBlank(defineOutputFileName)) {// 自定義名稱outputFileName = defineOutputFileName;}Process process = null;try {// Command to convert MP4 to M3U8 using FFmpegList<String> command = new ArrayList<>();command.add(ffmpegPath);command.add("-i");command.add(inputFilePath);command.add("-c:v");command.add("libx264");command.add("-hls_time");command.add("10"); // 設置每個分片的時長,單位為秒command.add("-hls_list_size");command.add("0");command.add("-hls_segment_filename");command.add(outputDirectory + "/" + outputFileName + "_%03d.ts");command.add(outputDirectory + "/" + outputFileName + ".m3u8");ProcessBuilder pb = new ProcessBuilder(command);pb.inheritIO(); // 將FFmpeg的輸出信息打印到控制臺process = pb.start();int exitCode = process.waitFor();if (exitCode == 0) {log.info("視頻轉換成功!");} else {log.info("視頻轉換失敗!");}} catch (IOException | InterruptedException e) {e.printStackTrace();if (process != null) {process.destroyForcibly(); // 如果發生異常,強制終止進程}} finally {if (process != null) {process.destroyForcibly(); // 如果發生異常,強制終止進程}}// Check if the conversion was successfulFile m3u8File = new File(outputDirectory + "/" + outputFileName + ".m3u8");if (!m3u8File.exists()) {throw new RuntimeException("M3U8 file was not generated");}}
圖片轉視頻
/*** 圖片轉為視頻* E://yla-tool//ffmpeg//ffmpeg-7.0.1-full_build//bin//ffmpeg.exe -framerate 0.2 -f image2 -i 素材%d.png -vf scale=1920:1080 -c:v libx264 -profile:v high -crf 20 -pix_fmt yuv420p test.mp4* E://yla-tool//ffmpeg//ffmpeg-7.0.1-full_build//bin//ffmpeg.exe -r 15 -loop 1 -i 01.jpg -vf scale=1920:1080 -c:v libx264 -profile:v high -crf 20 -pix_fmt yuv420p -t 10 -r 15 111.mp4* 暫不支持多張圖片* @param imagePaths* @param outputVideoPath* @param r 幀率* @param t 時長*/public Integer generateVideo (List<String> imagePaths, String outputVideoPath, int r, int t) {
// StringBuilder ffmpegCommand = new StringBuilder(ffmpegPath + " -framerate ");
// ffmpegCommand.append(fps).append(" -i ");// 設置幀率和輸入格式StringBuilder ffmpegCommand = new StringBuilder(ffmpegPath);ffmpegCommand.append(" -r ");ffmpegCommand.append(r);ffmpegCommand.append(" -loop 1 ");ffmpegCommand.append(" -i ");// 設置幀率和輸入格式for (String imagePath : imagePaths) {ffmpegCommand.append(imagePath).append(" ");// 添加每個圖片的路徑}ffmpegCommand.append("-vf scale=1920:1080 -c:v libx264 -profile:v high -crf 20 -pix_fmt yuv420p ")// 設置視頻編碼和質量.append(" -t ").append(t).append(" -r ").append(r).append(" ").append(outputVideoPath);// 設置視頻輸出路徑Process process = null;try {process = Runtime.getRuntime().exec(ffmpegCommand.toString());BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));String line;while ((line = reader.readLine()) != null) {System.out.println(line);}reader.close();int exitCode = process.waitFor();if (exitCode == 0) {log.info("視頻生成成功,路徑:" + outputVideoPath);} else {log.info("視頻生成失敗!");}return exitCode;} catch (IOException | InterruptedException e) {e.printStackTrace();if (process != null) {process.destroyForcibly(); // 如果發生異常,強制終止進程}} finally {if (process != null) {process.destroyForcibly(); // 如果發生異常,強制終止進程}}return null;}
抽取視頻第一幀
public void previewVideo (HttpServletResponse response, String videoPath) {
// String videoPath = "path/to/your/video/sample.mp4"; // 替換為你的視頻文件路徑
// int startTimeSeconds = 0; // 開始時間,單位為秒
// int durationSeconds = 5; // 需要提取的視頻時長,單位為秒int frameTime = 0; // 提取第一幀圖像的時間,單位為秒 (原取1 但是1秒鐘的視頻 抽幀圖片缺失故改為0)
//
// try {
// // 構建 FFmpeg 命令
// String ffmpegCmd = String.format(ffmpegPath + " -ss %d -i %s -t %d -f image2pipe -vcodec mjpeg -", startTimeSeconds, videoPath, durationSeconds);Process process = null;try {// 構建 FFmpeg 命令
// String ffmpegCmd = String.format(ffmpegPath + " -ss %d -i %s -frames:v 1 -f image2pipe -vcodec mjpeg -", frameTime, videoPath);String imagePath = fileDir + "temp_image_" + UUID.randomUUID() + ".jpg";System.out.println(imagePath);
// -ss 0 -i input.mp4 -frames:v 1 -f image2 output.jpg
// String ffmpegCmd = String.format(" -ss %d -i %s -frames:v 1 -f image2 %s", frameTime, videoPath, imagePath);
// process = Runtime.getRuntime().exec(ffmpegCmd);ProcessBuilder processBuilder = new ProcessBuilder(ffmpegPath,"-ss", frameTime+"","-i", videoPath,"-frames:v", "1","-q:v", "30",imagePath);processBuilder.inheritIO(); // 將FFmpeg的輸出信息打印到控制臺process = processBuilder.start();int exitCode = process.waitFor();if (exitCode == 0) {log.info("抽取第一幀成功!");} else {log.info("抽取第一幀失敗!");}// 讀取生成的圖片InputStream inputStream = new FileInputStream(imagePath);// 設置響應頭response.setContentType("image/jpeg");OutputStream outputStream = response.getOutputStream();// 從 FFmpeg 輸出流讀取數據并寫入到 Servlet 輸出流byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = inputStream.read(buffer)) != -1) {outputStream.write(buffer, 0, bytesRead);}outputStream.flush();outputStream.close();inputStream.close();// 刪除臨時圖片文件Files.delete(Paths.get(imagePath));} catch (IOException | InterruptedException e) {e.printStackTrace();if (process != null) {process.destroyForcibly(); // 如果發生異常,強制終止進程}response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);} finally {if (process != null) {process.destroyForcibly(); // 如果發生異常,強制終止進程}}}
獲取基本信息
package net.yla.board.core.utils;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;public class VideoConverter {public static void main(String[] args) {
// "-c:v", "libx264", "-b:v", "4027k", "-preset", "ultrafast", "-threads", "4", "-c:a", "aac",// String inputVideo = "E:\\testm3u8\\西藏2.mp4";String inputVideo = "E:\\圖片夾\\視頻雪景.mp4";String outputPlaylist = "E:\\testm3u8\\output.m3u8";long l1 = System.currentTimeMillis();
// ProcessBuilder processBuilder = new ProcessBuilder("E:\\yla-tool\\ffmpeg\\ffmpeg-7.0.1-full_build\\bin\\ffmpeg.exe", "-i",inputVideo);// E:\\yla-tool\\ffmpeg\\ffmpeg-7.0.1-full_build\\bin\\ffmpeg.exe -i E:\圖片夾\公司宣傳.mp4 -c:v libx264 -hls_time 10 -hls_list_size 0 -f hls -hls_segment_filename E:\\圖片夾\\output%03d.ts E:\圖片夾\output.m3u8
// ProcessBuilder processBuilder = new ProcessBuilder("E:\\yla-tool\\ffmpeg\\ffmpeg-7.0.1-full_build\\bin\\ffmpeg.exe", "-i", inputVideo, "-c:v", "libx264", "-hls_time", "10", "-hls_list_size", "0", "-f", "hls", "-hls_segment_filename", "E:\\testm3u8\\" + "output%03d.ts", outputPlaylist);ProcessBuilder processBuilder = new ProcessBuilder("E:\\yla-tool\\ffmpeg\\ffmpeg-7.0.1-full_build\\bin\\ffmpeg.exe", "-i",inputVideo);
// ProcessBuilder processBuilder = new ProcessBuilder("E:\\yla-tool\\ffmpeg\\ffmpeg-7.0.1-full_build\\bin\\ffmpeg.exe", "-i",inputVideo, "-c:v", "libx264", "-b:v", "4000k", "-preset", "ultrafast", "-c:a", "aac", System.currentTimeMillis() + ".mp4");try {processBuilder.inheritIO(); // 將FFmpeg的輸出信息打印到控制臺
// processBuilder.redirectErrorStream(true); // 合并錯誤輸出流Process process = processBuilder.start();// BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
// String line;
//
// while ((line = reader.readLine()) != null) {
// System.out.println(line); // 打印FFmpeg輸出的每一行
// // 解析進度信息
// if (line.contains("frame=")) {
// String[] parts = line.split(" ");
// for (String part : parts) {
// if (part.startsWith("time=")) {
// String time = part.split("=")[1];
// System.out.println("Current Time: " + time);
// }
// }
// }
// }int exitCode = process.waitFor();if (exitCode == 0) {System.out.println("視頻轉換成功!");System.out.println("轉換耗時:" + (System.currentTimeMillis() - l1) / 1000 + "秒");} else {System.out.println("視頻轉換失敗!");}} catch (IOException | InterruptedException e) {e.printStackTrace();}}
}
基本信息打印結果如下:
ffmpeg version 7.0.1-full_build-www.gyan.dev Copyright (c) 2000-2024 the FFmpeg developersbuilt with gcc 13.2.0 (Rev5, Built by MSYS2 project)configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-bzlib --enable-lzma --enable-libsnappy --enable-zlib --enable-librist --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-sdl2 --enable-libaribb24 --enable-libaribcaption --enable-libdav1d --enable-libdavs2 --enable-libuavs3d --enable-libxevd --enable-libzvbi --enable-librav1e --enable-libsvtav1 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxeve --enable-libxvid --enable-libaom --enable-libjxl --enable-libopenjpeg --enable-libvpx --enable-mediafoundation --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-libharfbuzz --enable-liblensfun --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-dxva2 --enable-d3d11va --enable-d3d12va --enable-ffnvcodec --enable-libvpl --enable-nvdec --enable-nvenc --enable-vaapi --enable-libshaderc --enable-vulkan --enable-libplacebo --enable-opencl --enable-libcdio --enable-libgme --enable-libmodplug --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libshine --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libcodec2 --enable-libilbc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-ladspa --enable-libbs2b --enable-libflite --enable-libmysofa --enable-librubberband --enable-libsoxr --enable-chromaprintlibavutil 59. 8.100 / 59. 8.100libavcodec 61. 3.100 / 61. 3.100libavformat 61. 1.100 / 61. 1.100libavdevice 61. 1.100 / 61. 1.100libavfilter 10. 1.100 / 10. 1.100libswscale 8. 1.100 / 8. 1.100libswresample 5. 1.100 / 5. 1.100libpostproc 58. 1.100 / 58. 1.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'E:\圖片夾\視頻雪景.mp4':Metadata:major_brand : mp42minor_version : 0compatible_brands: mp42isomavc1creation_time : 2023-11-24T11:51:45.000000ZDuration: 00:00:07.64, start: 0.000000, bitrate: 26320 kb/sStream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 3840x2160, 26340 kb/s, 59.94 fps, 59.94 tbr, 60k tbn (default)Metadata:creation_time : 2023-11-24T11:51:45.000000Zhandler_name : Vimeo Artax Video Handlervendor_id : [0][0][0][0]encoder : AVC CodingStream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 189 kb/s (default)Metadata:creation_time : 2023-11-24T11:51:45.000000Zhandler_name : Vimeo Artax Audio Handlervendor_id : [0][0][0][0]
At least one output file must be specified
轉碼日志輸出詳解
輸出內容如下:
視頻碼率:23604
ffmpeg version 7.0.1-full_build-www.gyan.dev Copyright (c) 2000-2024 the FFmpeg developersbuilt with gcc 13.2.0 (Rev5, Built by MSYS2 project)configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads --disable-autodetect --enable-fontconfig --enable-iconv --enable-gnutls --enable-libxml2 --enable-gmp --enable-bzlib --enable-lzma --enable-libsnappy --enable-zlib --enable-librist --enable-libsrt --enable-libssh --enable-libzmq --enable-avisynth --enable-libbluray --enable-libcaca --enable-sdl2 --enable-libaribb24 --enable-libaribcaption --enable-libdav1d --enable-libdavs2 --enable-libuavs3d --enable-libxevd --enable-libzvbi --enable-librav1e --enable-libsvtav1 --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxeve --enable-libxvid --enable-libaom --enable-libjxl --enable-libopenjpeg --enable-libvpx --enable-mediafoundation --enable-libass --enable-frei0r --enable-libfreetype --enable-libfribidi --enable-libharfbuzz --enable-liblensfun --enable-libvidstab --enable-libvmaf --enable-libzimg --enable-amf --enable-cuda-llvm --enable-cuvid --enable-dxva2 --enable-d3d11va --enable-d3d12va --enable-ffnvcodec --enable-libvpl --enable-nvdec --enable-nvenc --enable-vaapi --enable-libshaderc --enable-vulkan --enable-libplacebo --enable-opencl --enable-libcdio --enable-libgme --enable-libmodplug --enable-libopenmpt --enable-libopencore-amrwb --enable-libmp3lame --enable-libshine --enable-libtheora --enable-libtwolame --enable-libvo-amrwbenc --enable-libcodec2 --enable-libilbc --enable-libgsm --enable-libopencore-amrnb --enable-libopus --enable-libspeex --enable-libvorbis --enable-ladspa --enable-libbs2b --enable-libflite --enable-libmysofa --enable-librubberband --enable-libsoxr --enable-chromaprintlibavutil 59. 8.100 / 59. 8.100libavcodec 61. 3.100 / 61. 3.100libavformat 61. 1.100 / 61. 1.100libavdevice 61. 1.100 / 61. 1.100libavfilter 10. 1.100 / 10. 1.100libswscale 8. 1.100 / 8. 1.100libswresample 5. 1.100 / 5. 1.100libpostproc 58. 1.100 / 58. 1.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'E:\圖片夾\視頻-GreatWall.mp4':Metadata:major_brand : mp42minor_version : 0compatible_brands: mp42isomavc1creation_time : 2024-02-04T21:36:53.000000ZDuration: 00:00:48.73, start: 0.000000, bitrate: 23604 kb/sStream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 3840x2160, 23601 kb/s, 30 fps, 30 tbr, 30 tbn (default)Metadata:creation_time : 2024-02-04T21:36:53.000000Zhandler_name : Vimeo Artax Video Handlervendor_id : [0][0][0][0]encoder : AVC Coding
Stream mapping:Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
Press [q] to stop, [?] for help
[libx264 @ 000001e505081300] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
[libx264 @ 000001e505081300] profile Constrained Baseline, level 5.1, 4:2:0, 8-bit
[libx264 @ 000001e505081300] 264 - core 164 r3191 4613ac3 - H.264/MPEG-4 AVC codec - Copyleft 2003-2024 - http://www.videolan.org/x264.html - options: cabac=0 ref=1 deblock=0:0:0 analyse=0:0 me=dia subme=0 psy=1 psy_rd=1.00:0.00 mixed_ref=0 me_range=16 chroma_me=1 trellis=0 8x8dct=0 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=0 threads=9 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=0 weightp=0 keyint=250 keyint_min=25 scenecut=0 intra_refresh=0 rc=abr mbtree=0 bitrate=23604 ratetol=1.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=0
Output #0, mp4, to '1744097594286.mp4':Metadata:major_brand : mp42minor_version : 0compatible_brands: mp42isomavc1encoder : Lavf61.1.100Stream #0:0(und): Video: h264 (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 3840x2160, q=2-31, 23604 kb/s, 30 fps, 15360 tbn (default)Metadata:creation_time : 2024-02-04T21:36:53.000000Zhandler_name : Vimeo Artax Video Handlervendor_id : [0][0][0][0]encoder : Lavc61.3.100 libx264Side data:cpb: bitrate max/min/avg: 0/0/23604000 buffer size: 0 vbv_delay: N/A
[out#0/mp4 @ 000001e5043e8100] video:140862KiB audio:0KiB subtitle:0KiB other streams:0KiB global headers:0KiB muxing overhead: 0.005820%
frame= 1462 fps= 80 q=-1.0 Lsize= 140870KiB time=00:00:48.73 bitrate=23680.1kbits/s speed=2.68x
[libx264 @ 000001e505081300] frame I:6 Avg QP:29.67 size:814006
[libx264 @ 000001e505081300] frame P:1456 Avg QP:32.41 size: 95713
[libx264 @ 000001e505081300] mb I I16..4: 100.0% 0.0% 0.0%
[libx264 @ 000001e505081300] mb P I16..4: 1.3% 0.0% 0.0% P16..4: 51.9% 0.0% 0.0% 0.0% 0.0% skip:46.8%
[libx264 @ 000001e505081300] final ratefactor: 29.74
[libx264 @ 000001e505081300] coded y,uvDC,uvAC intra: 41.9% 22.8% 1.1% inter: 19.3% 5.8% 0.0%
[libx264 @ 000001e505081300] i16 v,h,dc,p: 23% 26% 35% 16%
[libx264 @ 000001e505081300] i8c dc,h,v,p: 53% 24% 14% 8%
[libx264 @ 000001e505081300] kb/s:23678.63
視頻轉換成功!
轉換耗時:19秒
以下是對這段FFmpeg日志的逐行解釋:
- FFmpeg版本信息
ffmpeg version 7.0.1-full_build-www.gyan.dev Copyright ? 2000-2024 the FFmpeg developers
built with gcc 13.2.0 (Rev5, Built by MSYS2 project)
這是FFmpeg的版本信息,顯示當前使用的是 FFmpeg 7.0.1。 -??opyright信息表明FFmpeg是一個開源軟件,由全球開發者社區維護。
編譯信息:使用了 gcc 13.2.0 編譯,通過MSYS2項目構建。
- 配置信息
configuration: --enable-gpl --enable-version3 --enable-static --disable-w32threads […] --enable-libx264 --enable-libx265 […]
這是FFmpeg的配置選項,表示在編譯時啟用了某些功能:
–enable-gpl:啟用GPL(GNU通用公共許可證)許可協議。
–enable-version3:啟用GPL第三版協議。
–enable-static:編譯為靜態庫,而不是動態庫。
–enable-libx264 和 --enable-libx265:啟用H.264(x264)和H.265(x265)編碼支持。
[…] 表示省略了其他配置選項。
- FFmpeg核心庫版本
libavutil 59. 8.100 / 59. 8.100
libavcodec 61. 3.100 / 61. 3.100
libavformat 61. 1.100 / 61. 1.100
libavdevice 61. 1.100 / 61. 1.100
libavfilter 10. 1.100 / 10. 1.100
libswscale 8. 1.100 / 8. 1.100
libswresample 5. 1.100 / 5. 1.100
libpostproc 58. 1.100 / 58. 1.100
這些是FFmpeg的核心庫版本信息,分別對應:
libavutil:實用函數庫。
libavcodec:音視頻編解碼器庫。
libavformat:音視頻格式處理庫。
libavdevice:輸入/輸出設備處理庫。
libavfilter:音視頻濾鏡庫。
libswscale:視頻縮放和格式轉換庫。
libswresample:音頻重采樣庫。
libpostproc:視頻后處理庫。
- 輸入文件信息
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from ‘E:\圖片夾\視頻-GreatWall.mp4’:
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: mp42isomavc1
creation_time : 2024-02-04T21:36:53.000000Z
Duration: 00:00:48.73, start: 0.000000, bitrate: 23604 kb/s
Stream #0:00x1: Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 3840x2160, 23601 kb/s, 30 fps, 30 tbr, 30 tbn (default)
Metadata:
creation_time : 2024-02-04T21:36:53.000000Z
handler_name : Vimeo Artax Video Handler
vendor_id : [0][0][0][0]
encoder : AVC Coding
輸入文件路徑:E:\圖片夾\視頻-GreatWall.mp4。
文件Metadata:
major_brand:主要品牌標識為 mp42。
minor_version:次要版本號為 0。
compatible_brands:兼容的品牌標識,包括 mp42 和 isom。
creation_time:文件創建時間為 2024-02-04T21:36:53Z。
流媒體信息:
Stream #0:0 是輸入文件的視頻流。
編碼格式:H.264 (High)。
分辨率:3840x2160(4K)。
比特率:23601 kb/s。
幀率:30 fps。
色彩空間:yuv420p,適用于電視(tv),顏色空間為 bt709。
Metadata:
handler_name:處理器名稱為 Vimeo Artax Video Handler。
vendor_id:供應商ID為空。
encoder:編碼器為 AVC Coding。
- 流映射
Stream mapping:
Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
流映射:指明輸入的流如何映射到輸出。
Stream #0:0:輸入的視頻流(H.264)。
輸出的流:h264 (libx264),即使用 libx264 編碼器重新編碼。
- 按鍵提示
Press [q] to stop, [?] for help
提示用戶可以按 q 停止轉碼過程,或按 ? 查看幫助信息。
- 視頻編碼器信息
[libx264 @ 000001e505081300] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
[libx264 @ 000001e505081300] profile Constrained Baseline, level 5.1, 4:2:0, 8-bit
[libx264 @ 000001e505081300] 264 - core 164 r3191 4613ac3 - H.264/MPEG-4 AVC codec - Copyleft 2003-2024 - http://www.videolan.org/x264.html - options: cabac=0 ref=1 deblock=0:0:0 analyse=0:0 me=dia subme=0 psy=1 psy_rd=1.00:0.00 mixed_ref=0 me_range=16 chroma_me=1 trellis=0 8x8dct=0 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=0 threads=9 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=0 weightp=0 keyint=250 keyint_min=25 scenecut=0 intra_refresh=0 rc=abr mbtree=0 bitrate=23604 ratetol=1.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=0
libx264:H.264編碼器的詳細信息。
CPU支持:列出了CPU支持的指令集(如AVX、AVX2等)。
Profile:使用的 profiles 是 Constrained Baseline,適用于移動設備和網頁播放。
Level:視頻編碼級別為 5.1,適用于分辨率高達 4K 的視頻。
編碼選項:詳細列出了編碼器的參數設置,包括:
cabac=0:不使用 CABAC 熵編碼。
ref=1:參考幀數量。
deblock=0:0:0:去塊過濾器的強度為0。
psy=1:啟用心理學優化。
bitrate=23604:目標比特率為23604 kbps,與輸入文件一致。
qcomp=0.60:量化壓縮系數。
- 輸出文件信息
Output #0, mp4, to ‘1744097594286.mp4’:
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: mp42isomavc1
encoder : Lavf61.1.100
Stream #0:0(und): Video: h264 (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 3840x2160, q=2-31, 23604 kb/s, 30 fps, 15360 tbn (default)
Metadata:
creation_time : 2024-02-04T21:36:53.000000Z
handler_name : Vimeo Artax Video Handler
vendor_id : [0][0][0][0]
encoder : Lavc61.3.100 libx264
Side data:
cpb: bitrate max/min/avg: 0/0/23604000 buffer size: 0 vbv_delay: N/A
輸出文件路徑:1744097594286.mp4。
輸出Metadata:
major_brand 和 compatible_brands 與輸入文件一致。
encoder:使用的 muxer( multiplexor,復用器)版本號為 Lavf61.1.100。
流媒體信息:
視頻流的編碼格式為 H.264,分辨率為 3840x2160,比特率為 23604 kb/s。
q=2-31:量化參數范圍。
tbn=15360:時間基數(timebase numerator)。
Side data:關于igrams buffer的信息。
- 轉碼進度
frame= 1462 fps= 80 q=-1.0 Lsize= 140870KiB time=00:00:48.73 bitrate=23680.1kbits/s speed=2.68x
frame=1462:總共處理了1462幀。
fps=80:實際轉碼速度為80幀每秒。
q=-1.0:量化參數 (-1 表示自動調整)。
Lsize=140870KiB:輸出文件大小約為 140.87 MB。
time=00:00:48.73:轉碼完成時長為 48.73 秒。
bitrate=23680.1kbits/s:實際比特率為23680.1 kbps。
speed=2.68x:轉碼速度是實時速度的2.68倍。
- 編碼統計
[libx264 @ 000001e505081300] frame I:6 Avg QP:29.67 size:814006
[libx264 @ 000001e505081300] frame P:1456 Avg QP:32.41 size: 95713
[libx264 @ 000001e505081300] mb I I16…4: 100.0% 0.0% 0.0%
[libx264 @ 000001e505081300] mb P I16…4: 1.3% 0.0% 0.0% P16…4: 51.9% 0.0% 0.0% 0.0% 0.0% skip:46.8%
[libx264 @ 000001e505081300] final ratefactor: 29.74
[libx264 @ 000001e505081300] coded y,uvDC,uvAC intra: 41.9% 22.8% 1.1% inter: 19.3% 5.8% 0.0%
幀類型統計:
I幀:6個,平均QP(量化參數)為29.67,大小為814006 bytes。
P幀:1456個,平均QP為32.41,大小為95713 bytes。
宏塊(mb)統計:
I幀宏塊:100% 使用 I16…4 模式。
P幀宏塊:
I16…4 模式占1.3%。
P16…4 模式占51.9%。
skip(跳過運動補償)占46.8%。
final ratefactor:最終的速率因子為29.74。
編碼效率統計:
chtěIntra(內存預測):41.9% 的Y分量、22.8% 的UV分量DC、1.1% 的UV分量AC。 -_RETRY(運動預測):19.3% 的Y分量、5.8% 的UV分量。
總結:
這是一個H.264視頻的轉碼過程,輸入和輸出格式均為MP4,分辨率為4K(3840x2160),比特率保持不變,使用了x264編碼器進行重新編碼。轉碼速度較快(2.68x),最終輸出文件大小為約140.87 MB。
轉碼耗時測試
ffmpeg安裝位置:E:\yla-tool\ffmpeg\ffmpeg-7.0.1-full_build\bin\ffmpeg.exe
// 獲取源文件碼率
String videoBitrate = getVideoBitrate(inputVideo);
簡單基本命令和加了參數preset 和 b:v碼率設置
文件和命令 | “E:\yla-tool\ffmpeg\ffmpeg-7.0.1-full_build\bin\ffmpeg.exe”, “-i”,inputVideo, “-c:v”, “libx264”, “-c:a”, “aac”, System.currentTimeMillis() + “.mp4” | “E:\yla-tool\ffmpeg\ffmpeg-7.0.1-full_build\bin\ffmpeg.exe”, “-i”,inputVideo, “-c:v”, “libx264”, “-b:v”, videoBitrate+“k”, “-preset”, “ultrafast”, “-c:a”, “aac”, System.currentTimeMillis() + “.mp4” |
---|---|---|
視頻雪景.mp4( 7s 23M 總比特率25116kbps 幀速率59.94幀/秒) | 40s(44M 碼率45243kbps) | 8s(19M 碼率20346kbps) |
視頻-GreatWall.mp4( 48s 137M 總比特率23472kbps 幀速率30幀/秒) | 121s(140M 碼率相似) | 19s(140M 碼率相似) |
參數后續……