问题分析:
在进行视频合并时,若第一个视频是没有音频的,则后续合并出来的视频也是没有音频的
处理方案:
给没有音频的视频增加一个空白的音频轨道
示例:
步骤1:检测视频是否有音轨
首先,使用FFmpegFrameGrabber来检测视频文件是否包含音轨。
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FrameGrabber.Exception;
public static boolean hasAudioTrack(String videoFilePath)
{
try(FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(videoFilePath))
{
grabber.start();
int audioChannels = grabber.getAudioChannels();
grabber.stop();
return audioChannels > 0;
}
catch(Exception e)
{
e.printStackTrace();
return false;
}
}
步骤2:为没有音轨的视频添加空白音轨
如果视频没有音轨,可以使用FFmpegFrameRecorder来添加一个空白音轨。这需要创建一个空的音频帧,并在处理视频帧的同时,周期性地插入这个空的音频帧。
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameRecorder.Exception;
public static void addBlankAudioTrack(String inputPath, String outputPath)
{
try(FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputPath); FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputPath, grabber.getImageWidth(), grabber.getImageHeight()))
{
grabber.start();
recorder.setFormat(grabber.getFormat());
recorder.setSampleRate(44100); // 设置音频采样率
recorder.setAudioChannels(1); // 设置音频通道数
recorder.start();
Frame frame;
while((frame = grabber.grab()) != null)
{
recorder.record(frame);
if(frame.image != null)
{ // 插入空白音频帧
Frame audioFrame = new Frame();
audioFrame.samples = new float[1][44100];
recorder.recordSamples(audioFrame.samples);
}
}
recorder.stop();
grabber.stop();
}
catch(Exception e)
{
e.printStackTrace();
}
}
步骤3:合并视频
现在,你已经有了一个方法来为没有音轨的视频添加空白音轨,接下来是合并视频的步骤。假设你已经有了一个包含多个视频文件的列表,你可以遍历这个列表,为每个视频添加空白音轨(如果需要的话),然后将它们合并成一个视频。
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import java.util.List;
public class VideoMerger {
public static void mergeVideos(List<String> inputVideoPaths, String outputPath) {
FFmpegFrameRecorder recorder = null;
try {
// 初始化recorder,假设所有视频的分辨率和格式都是相同的
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputVideoPaths.get(0));
grabber.start();
recorder = new FFmpegFrameRecorder(outputPath, grabber.getImageWidth(), grabber.getImageHeight(), grabber.getAudioChannels());
recorder.setFormat(grabber.getFormat());
recorder.setFrameRate(grabber.getFrameRate());
recorder.start();
grabber.stop();
// 遍历所有视频文件
for (String videoPath : inputVideoPaths) {
grabber = new FFmpegFrameGrabber(videoPath);
grabber.start();
Frame frame;
// 读取所有帧并写入输出视频
while ((frame = grabber.grabFrame()) != null) {
recorder.record(frame);
}
grabber.stop();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (recorder != null) {
try {
recorder.stop();
recorder.release();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
List<String> videosToMerge = List.of("video1.mp4", "video2.mp4"); // 你的视频路径列表
String outputPath = "mergedVideo.mp4"; // 输出路径
mergeVideos(videosToMerge, outputPath);
}
}