Java视频抽帧
ffmpeg.exe 全能,啥视频都可以抽帧呦,亲测可用,支持h265、h264、mkv、mp4
FFmpegFrameGrabber支持跨平台~
1. h264视频抽帧,支持windows
2. h265视频抽帧,支持windows、linux
3. 格式转换,h265转mp4原理
- 调用ffmpeg.exe
- 调用FFmpegFrameGrabber
运行结果如下图:
4. h265转mp4、mkv转mp4、h265转h264 源码如下
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacpp.avcodec;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
/*************************************
*Class Name: VideoUtils
*Description: <视频抽帧类>
*@author: Seminar
*@create: 2021/1/28
*@since 1.0.0
*************************************/
@Slf4j
public class VideoConverter {
/**
* ffmpeg -i test.h265 G7.mp4
*
* @param videoPath 视频原始路径
* @param targetPath 目标视频类型及路径
* @throws IOException
*/
public static void ffmpegConvert2Mp4(String videoPath, String targetPath) throws IOException {
String path = System.getProperty("user.dir") + File.separator + "frameExtract" + File.separator + "ffmpeg.exe";
ProcessBuilder processBuilder = new ProcessBuilder(path, "-y",
"-i", videoPath,
targetPath);
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
StringBuilder processOutput = new StringBuilder();
try (BufferedReader processOutputReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));) {
String readLine;
while ((readLine = processOutputReader.readLine()) != null) {
processOutput.append(readLine + System.lineSeparator());
}
process.waitFor();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (process != null) {
process.destroy();
}
}
String[] str = processOutput.toString().trim().split("\n");
String[] res = new String[3];
System.arraycopy(str, str.length - 3, res, 0, 3);
log.info("ffmpegConvert2Mp4 res: {}", String.join("\n", Arrays.asList(res)));
}
/**
* 转换h265视频文件为mp4
*
* @param file
* @return
*/
public static void ffmpegFrameGrabberConvertToMp4(File file, String targetVideoPath) {
FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber(file);
Frame captured_frame = null;
FFmpegFrameRecorder recorder = null;
try {
frameGrabber.start();
recorder = new FFmpegFrameRecorder(targetVideoPath, frameGrabber.getImageWidth(), frameGrabber.getImageHeight(), frameGrabber.getAudioChannels());
// 原始视频格式
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H265); //avcodec.AV_CODEC_ID_H264 //AV_CODEC_ID_MPEG4
// 期望视频格式
recorder.setFormat("mp4");// 此处设置不同格式,可转不同格式数据
recorder.setFrameRate(frameGrabber.getFrameRate());
//recorder.setSampleFormat(frameGrabber.getSampleFormat()); //
recorder.setSampleRate(frameGrabber.getSampleRate());
recorder.setAudioChannels(frameGrabber.getAudioChannels());
recorder.setFrameRate(frameGrabber.getFrameRate());
recorder.start();
while ((captured_frame = frameGrabber.grabFrame()) != null) {
try {
recorder.setTimestamp(frameGrabber.getTimestamp());
recorder.record(captured_frame);
} catch (Exception e) {
}
}
recorder.stop();
recorder.release();
frameGrabber.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
String videoPath = "D:\\project\\frame-extract\\doc\\20xxxxx.h265";
String targetVideoPath = videoPath.substring(0, videoPath.lastIndexOf(".") + 1).concat("mp4");
// ffmpeg.exe转换
ffmpegConvert2Mp4(videoPath, targetVideoPath);
// FFmpegFrameGrabber 转换
File file = new File(videoPath);
targetVideoPath = videoPath.substring(0, videoPath.lastIndexOf(".")).concat("_FFmpegFrameGrabber.").concat("mp4");
ffmpegFrameGrabberConvertToMp4(file, targetVideoPath);
}
}
5. h265视频播放
可以用potplayer