我是一个Java程序员,需要用代码创建高清视频,素材为文本、图片和mp3,我该如何写代码

创建高清视频的任务可以使用 FFmpeg 工具来完成。FFmpeg 是一个非常强大的多媒体处理工具,支持视频和音频的编码、解码、转码、流媒体等操作。你可以通过 Java 调用 FFmpeg 命令行工具来实现你的需求。

以下是一个示例代码,展示如何使用 Java 调用 FFmpeg 来创建高清视频,素材包括文本、图片和 MP3 音频文件。

1. 安装 FFmpeg

首先,确保你已经在系统上安装了 FFmpeg。你可以从 FFmpeg 官方网站 下载并安装。

2. 编写 Java 代码

以下是一个示例代码,展示如何使用 Java 调用 FFmpeg 创建高清视频:

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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class VideoCreator {

public static void createVideo(String imagePath, String audioPath, String outputPath, String text) {
long startTime = System.currentTimeMillis();

// 创建一个临时文件来保存文本内容
String tempTextFile = "temp_text.txt";
try (FileWriter writer = new FileWriter(tempTextFile)) {
writer.write("drawtext=fontfile=arial.ttf:text='" + text + "':x=(w-text_w)/2:y=(h-text_h)/2:fontsize=24:fontcolor=white");
} catch (Exception e) {
e.printStackTrace();
return;
}

// 构建 ffmpeg 命令
List<String> command = new ArrayList<>();
command.add("ffmpeg");
command.add("-y"); // 覆盖输出文件
command.add("-r"); // 帧率
command.add("10");
command.add("-f"); // 输入格式
command.add("image2");
command.add("-loop"); // 循环播放图片
command.add("1");
command.add("-i"); // 图片输入
command.add(imagePath);
command.add("-i"); // 音频输入
command.add(audioPath);
command.add("-vf"); // 视频过滤器
command.add("subtitles=" + tempTextFile); // 添加文本
command.add("-s"); // 输出分辨率
command.add("1920x1080");
command.add("-pix_fmt"); // 像素格式
command.add("yuvj420p");
command.add("-t"); // 持续时间
command.add(getAudioDuration(audioPath)); // 获取音频时长
command.add("-vcodec"); // 视频编码器
command.add("libx264");
command.add(outputPath); // 输出文件路径

// 执行命令
executeCommand(command);

long endTime = System.currentTimeMillis();
long durationMs = endTime - startTime;
String formattedDuration = formatDuration(durationMs);
System.out.println("耗时: " + formattedDuration);
}

private static void executeCommand(List<String> command) {
try {
ProcessBuilder processBuilder = new ProcessBuilder(command);
Process process = processBuilder.start();

// 读取标准输出
Thread outputThread = new Thread(() -> {
try (BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String s;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
} catch (Exception e) {
e.printStackTrace();
}
});

// 读取标准错误
Thread errorThread = new Thread(() -> {
try (BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
String s;
while ((s = stdError.readLine()) != null) {
System.err.println(s);
}
} catch (Exception e) {
e.printStackTrace();
}
});

// 启动线程
outputThread.start();
errorThread.start();

// 等待线程完成
outputThread.join();
errorThread.join();

// 等待进程完成
int exitCode = process.waitFor();
System.out.println("Process exited with code: " + exitCode);

} catch (Exception e) {
e.printStackTrace();
}
}

private static String getAudioDuration(String audioPath) {
// 这里返回一个示例时长,实际应用中需要获取真实的音频时长
return "278"; // 例如 278 秒
}

private static String formatDuration(long durationMs) {
long hours = durationMs / (1000 * 60 * 60);
long minutes = (durationMs % (1000 * 60 * 60)) / (1000 * 60);
long seconds = (durationMs % (1000 * 60)) / 1000;

return String.format("%02d:%02d:%02d", hours, minutes, seconds);
}

public static void main(String[] args) {
String imagePath = "path/to/your/image.jpg";
String audioPath = "path/to/your/audio.mp3";
String outputPath = "path/to/your/output_video.mp4";
String text = "这是一个示例文本";

createVideo(imagePath, audioPath, outputPath, text);
}
}

3. 代码解释

  1. 创建临时文本文件

    1
    2
    3
    4
    5
    6
    7
    String tempTextFile = "temp_text.txt";
    try (FileWriter writer = new FileWriter(tempTextFile)) {
    writer.write("drawtext=fontfile=arial.ttf:text='" + text + "':x=(w-text_w)/2:y=(h-text_h)/2:fontsize=24:fontcolor=white");
    } catch (Exception e) {
    e.printStackTrace();
    return;
    }
    • 创建一个临时文件 temp_text.txt,用于保存文本内容。
    • 使用 drawtext 过滤器将文本添加到视频中。
  2. 构建 FFmpeg 命令

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    List<String> command = new ArrayList<>();
    command.add("ffmpeg");
    command.add("-y"); // 覆盖输出文件
    command.add("-r"); // 帧率
    command.add("10");
    command.add("-f"); // 输入格式
    command.add("image2");
    command.add("-loop"); // 循环播放图片
    command.add("1");
    command.add("-i"); // 图片输入
    command.add(imagePath);
    command.add("-i"); // 音频输入
    command.add(audioPath);
    command.add("-vf"); // 视频过滤器
    command.add("subtitles=" + tempTextFile); // 添加文本
    command.add("-s"); // 输出分辨率
    command.add("1920x1080");
    command.add("-pix_fmt"); // 像素格式
    command.add("yuvj420p");
    command.add("-t"); // 持续时间
    command.add(getAudioDuration(audioPath)); // 获取音频时长
    command.add("-vcodec"); // 视频编码器
    command.add("libx264");
    command.add(outputPath); // 输出文件路径
    • 构建 FFmpeg 命令,包括输入图片、音频、文本、输出分辨率、像素格式、持续时间和视频编码器。
  3. 执行命令

    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
    private static void executeCommand(List<String> command) {
    try {
    ProcessBuilder processBuilder = new ProcessBuilder(command);
    Process process = processBuilder.start();

    // 读取标准输出
    Thread outputThread = new Thread(() -> {
    try (BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
    String s;
    while ((s = stdInput.readLine()) != null) {
    System.out.println(s);
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    });

    // 读取标准错误
    Thread errorThread = new Thread(() -> {
    try (BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()))) {
    String s;
    while ((s = stdError.readLine()) != null) {
    System.err.println(s);
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    });

    // 启动线程
    outputThread.start();
    errorThread.start();

    // 等待线程完成
    outputThread.join();
    errorThread.join();

    // 等待进程完成
    int exitCode = process.waitFor();
    System.out.println("Process exited with code: " + exitCode);

    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    • 使用 ProcessBuilder 执行 FFmpeg 命令。
    • 读取标准输出和标准错误,并启动线程处理这些输出。
  4. 获取音频时长

    1
    2
    3
    4
    private static String getAudioDuration(String audioPath) {
    // 这里返回一个示例时长,实际应用中需要获取真实的音频时长
    return "278"; // 例如 278 秒
    }
    • 返回一个示例时长,实际应用中需要获取真实的音频时长。
  5. 格式化耗时

    1
    2
    3
    4
    5
    6
    7
    private static String formatDuration(long durationMs) {
    long hours = durationMs / (1000 * 60 * 60);
    long minutes = (durationMs % (1000 * 60 * 60)) / (1000 * 60);
    long seconds = (durationMs % (1000 * 60)) / 1000;

    return String.format("%02d:%02d:%02d", hours, minutes, seconds);
    }
    • 将毫秒时间转换为时分秒格式。

4. 运行代码

将上述代码保存为 VideoCreator.java,然后编译并运行。确保 imagePathaudioPathoutputPath 路径正确。

通过这种方式,你可以使用 Java 调用 FFmpeg 创建高清视频,素材包括文本、图片和 MP3 音频文件。


http://coderdream.github.io/2024/11/06/FFmpeg入门2/
作者
CoderDream
发布于
2024年11月6日
许可协议