ffmpeg实现视频转码
# ffmpeg 实现视频转码
# 什么是视频编码
视频上传成功后需要对视频进行转码处理。
什么是视频编码?
查阅百度百科如下:
- 所谓视频编码方式 (opens new window)就是指通过压缩技术 (opens new window),将原始视频格式 (opens new window)的文件转换成另一种视频格式文件的方式。视频流 (opens new window)传输中最为重要的编解码标准有国际电联 (opens new window)的H.261 (opens new window)、H.263、H.264 (opens new window),运动静止图像专家组的M-JPEG (opens new window)和国际标准化组织 (opens new window)运动图像 (opens new window)专家组的MPEG (opens new window)系列标准,此外在互联网上被广泛应用的还有Real-Networks的RealVideo (opens new window)、微软 (opens new window)公司的WMV (opens new window)以及Apple公司的QuickTime (opens new window)等。
- 详情参考 :https://baike.baidu.com/item/%E8%A7%86%E9%A2%91%E7%BC%96%E7%A0%81/839038 (opens new window)
首先我们要分清文件格式和编码格式:
- 文件格式:是指
.mp4
、.avi
、.rmvb
等 - 这些不同扩展名的视频文件的文件格式,视频文件的内容主要包括视频和音频,其文件格式是按照一定的编码格式去编码,并且按照该文件所规定的封装格式将视频、音频、字幕等信息封装在一起,
- 播放器会根据它们的封装格式去提取出编码,然后由播放器解码,最终播放音视频。
音视频编码格式:通过音视频的压缩技术,将视频格式转换成另一种视频格式,通过视频编码实现流媒体的传输。比如:一个 .avi
的视频文件原来的编码是 a,通过编码后编码格式变为 b,音频原来为 c,通过编码后变为 d。
音视频编码格式各类繁多,主要有几下几类:
MPEG 系列
- (由 ISO[国际标准组织机构] 下属的 MPEG[运动图象专家组] 开发 )视频编码方面主要是 Mpeg1(vcd 用的就是它)、Mpeg2(DVD 使用)、Mpeg4(的 DVDRIP 使用的都是它的变种,如:divx,xvid 等)、Mpeg4 AVC(正热门);
- 音频编码方面主要是 MPEG Audio Layer 1/2、MPEG Audio Layer 3(大名鼎鼎的 mp3)、MPEG-2 AAC 、MPEG-4 AAC 等等。
- 注意:DVD 音频没有采用 Mpeg 的。
H.26X 系列
- (由 ITU[国际电传视讯联盟] 主导,侧重网络传输,注意:只是视频编码)包括 H.261、H.262、H.263、H.263+、H.263++、H.264(就是 MPEG4 AVC-合作的结晶)
- 目前最常用的编码标准是视频 H.264,音频 AAC。
提问:
H.264 是编码格式还是文件格式?
H.264(也称为 AVC,即高级视频编码)是一种视频编码格式,也就是一种视频压缩标准。它定义了如何对视频数据进行压缩、编码与解码。
- 简单来说,H.264 描述的是视频数据的压缩算法,而不是存储文件的格式。
- 通常,我们会将经过 H.264 编码的视频数据存储在不同的容器文件中,例如 MP4、MKV、AVI 等。
mp4 是编码格式还是文件格式?
MP4(MPEG-4 Part 14)是一种容器文件格式。它用于存储多媒体数据,比如视频、音频、字幕等。容器格式本身不定义视频或音频如何编码,而是作为一个“包装”,能够包含多种编码格式的数据。
常见的情况是:
- 视频部分使用 H.264 编码,
- 音频部分使用 AAC 编码,
- 然后一起存储在 MP4 文件中。
小结
- H.264:是一种视频编码标准,用于压缩视频数据。
- MP4:是一种容器格式,用于存储音视频数据,可以包含使用 H.264 编码的视频和其他编码格式的音频数据。
# 代码示例
@Slf4j
public class FfmpegProcess {
static String inputFile = VideoConstant.VIDEO_FILE_PATH1;
static String inputFile2 = VideoConstant.VIDEO_INPUT_PATH;
static String transcodeFile = VideoConstant.OUTPUT_FILE_PREFIX + "\\transcode.avi";
public static void main(String[] args) throws Exception {
String command = getVideoTranscodeCommand(inputFile2, transcodeFile);
System.out.println("执行命令: " + command);
// 创建操作系统进程
ProcessBuilder builder = new ProcessBuilder();
// 执行命令
executeCommand(builder, command, "windows");
// 合并标准输出和标准错误输出流
builder.redirectErrorStream(true);
Process process = builder.start();
// 异步读取输出流,避免阻塞
CompletableFuture<Void> future = readOutputAsync(process.getInputStream());
int exitCode = process.waitFor();
if (exitCode == 0) {
System.out.println("执行成功");
} else {
System.err.println("执行过程中出现错误,退出代码:" + exitCode);
}
}
/**
* 获取视频转码的命令
*
* @param inputFile 输入文件路径
* @param transcodeFile 转码文件路径
* @return 视频转码的命令
*/
private static String getVideoTranscodeCommand(String inputFile, String transcodeFile) {
return String.format("%s -y -i %s %s", VideoConstant.FFMPEG_PATH, inputFile, transcodeFile);
}
/**
* 异步读取 ffmpeg 输出流
*/
private static CompletableFuture<Void> readOutputAsync(InputStream inputStream) {
return CompletableFuture.runAsync(() -> {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
log.error("读取 ffmpeg 输出流异常", e);
}
});
}
/**
* 执行命令
*
* @param builder 进程构建器
* @param command 命令
* @param osType 操作系统类型
*/
private static void executeCommand(ProcessBuilder builder, String command, String osType) {
switch (osType) {
case "windows":
builder.command("cmd", "/c", command);
break;
case "Linux":
case "macOS":
builder.command("bash", "-c", command);
break;
default:
throw new RuntimeException("不支持的操作系统类型");
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
上次更新: 2025/2/8 18:02:22