123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- package com.iden.common.util;
- import com.iden.common.enums.TimeoutOption;
- import net.bramp.ffmpeg.FFmpeg;
- import net.bramp.ffmpeg.FFmpegExecutor;
- import net.bramp.ffmpeg.FFprobe;
- import net.bramp.ffmpeg.builder.FFmpegBuilder;
- import org.bytedeco.javacpp.avcodec;
- import org.bytedeco.javacv.*;
- import org.bytedeco.javacv.Frame;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import javax.imageio.ImageIO;
- import javax.swing.*;
- import java.awt.*;
- import java.awt.image.BufferedImage;
- import java.io.File;
- import java.util.*;
- import java.util.List;
- /**
- * 视频工具
- *
- * @author
- */
- public class VideoUtil {
- private static final int SECOND = 50;
- private static final Logger logger = LoggerFactory.getLogger(VideoUtil.class);
- /**
- * 获取指定视频的帧并保存为图片至指定目录
- *
- * @param videoFile 源视频文件
- * @param saveFile 截取帧的图片存放路径
- * @throws Exception
- */
- public static List<File> fetchPic(File videoFile, String saveFile, int second) throws Exception {
- java.util.List<File> files = new ArrayList<>();
- FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoFile);
- ff.start();
- int lenght = ff.getLengthInAudioFrames();
- System.out.println(ff.getFrameRate());
- int i = 0;
- Frame frame = null;
- while (i < lenght) {
- // 过滤前5帧,避免出现全黑的图片,依自己情况而定
- frame = ff.grabImage();
- if (i >= (int) (ff.getFrameRate() * second) && frame.image != null) {
- System.out.print(i + ",");
- if (frame != null && frame.image != null) {
- System.out.println(i);
- String fileName = String.valueOf(System.currentTimeMillis()) + i;
- files.add(writeToFile(frame, saveFile, fileName));
- }
- second++;
- }
- i += second;
- }
- ff.stop();
- return files;
- }
- private static List<Integer> getList(int count, int length) {
- if (count > length) {
- count = length;
- }
- // System.out.println(length);
- // System.out.println(count);
- int total = (int) (length / count);
- List<Integer> list = new ArrayList<>();
- for (int i = 0; i < count; i++) {
- list.add(i * total);
- System.out.println(i * total);
- }
- return list;
- }
- public static List<File> fetchPicByCount(File videoFile, String saveDir, int count) throws Exception {
- java.util.List<File> files = new ArrayList<>();
- FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoFile);
- ff.start();
- // 此视频时长(s/秒)
- Long duration = ff.getLengthInTime() / (1000 * 1000);
- System.out.println("duration==" + duration);
- // 视频总帧数
- int frameLength = ff.getLengthInFrames();
- System.out.println("length==" + frameLength);
- List<Integer> list = getList(count, frameLength);
- System.out.println("ff.getFrameRate() == " + ff.getFrameRate());
- int i = 0;
- Frame frame = null;
- while (i < frameLength) {
- frame = ff.grabImage();
- if (list.contains(i)) {
- if (frame != null && frame.image != null) {
- System.out.println(i);
- String fileName = String.valueOf(System.currentTimeMillis()) + i;
- files.add(writeToFile(frame, saveDir, fileName));
- }
- }
- i++;
- }
- ff.stop();
- return files;
- }
- public static Long fetchAllPic(File videoFile, String saveDir, Date shootEndTime) throws Exception {
- Long endTime = shootEndTime.getTime() ;
- java.util.List<File> files = new ArrayList<>();
- FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoFile);
- ff.start();
- // 此视频时长(ms/毫秒秒)
- Long duration = ff.getLengthInTime() / 1000;
- System.out.println("duration==" + duration);
- Long beginTime = endTime - duration;
- // 视频总帧数
- int frameLength = ff.getLengthInFrames();
- System.out.println("length==" + frameLength);
- //帧率(1秒多少帧)
- double framRate = ff.getFrameRate();
- int i = 0;
- Frame frame = null;
- while (i < frameLength) {
- frame = ff.grabImage();
- if (frame != null && frame.image != null) {
- Double time = beginTime + (i * (1000/framRate));
- String fileName = DateUtils.formatToDateStr(new Date(time.longValue()),"yyyyMMddHHmmss") + "_" + UUID.randomUUID().toString();
- files.add(writeToFile(frame, saveDir, fileName));
- }
- i++;
- }
- ff.stop();
- return duration;
- }
- private static File writeToFile(Frame frame, String saveDir, String fileName) throws Exception {
- File saveDirFile = new File(saveDir);
- if(!saveDirFile.exists()) {
- saveDirFile.mkdirs();
- }
- File targetFile = new File(saveDir + File.separator + fileName + ".jpg");
- String imgSuffix = "jpg";
- Java2DFrameConverter converter = new Java2DFrameConverter();
- BufferedImage srcBi = converter.getBufferedImage(frame);
- int owidth = srcBi.getWidth();
- int oheight = srcBi.getHeight();
- // 对截取的帧进行等比例缩放
- int width = 800;
- int height = (int) (((double) width / owidth) * oheight);
- BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
- bi.getGraphics().drawImage(srcBi.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);
- try {
- ImageIO.write(bi, imgSuffix, targetFile);
- } catch (Exception e) {
- throw new Exception( "截帧失败");
- }
- return targetFile;
- }
- /**
- * 获取视频时长,单位为秒
- *
- * @param file
- * @return 时长(s)
- */
- public static Long getVideoTime(File file) {
- Long times = 0L;
- try {
- FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file);
- ff.start();
- times = ff.getLengthInTime() / (1000 * 1000);
- ff.stop();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return times;
- }
- /**
- * 视频截取
- * @param videoFile
- * @throws Exception
- */
- public static void cut(File videoFile, File outputFile) throws Exception{
- boolean isStart = true;// 该变量建议设置为全局控制变量,用于控制录制结束
- FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(videoFile);
- // // 微秒 大概为设置时间的两倍
- // grabber.setOption(TimeoutOption.RW_TIMEOUT.getKey(), "10000000");
- // rtsp 默认udp 丢包 改为tcp
- // grabber.setOption("rtsp_transport", "tcp");
- grabber.start();
- //好多视频熟悉可以获取后打印 示例几个
- System.out.println("ImageWidth:" + grabber.getImageWidth());
- System.out.println("ImageHeight:" + grabber.getImageHeight());
- System.out.println("AudioChannels:" + grabber.getAudioChannels());
- System.out.println("Format:" + grabber.getFormat());
- FrameRecorder recorder = new FFmpegFrameRecorder(outputFile, grabber.getImageWidth(), grabber.getImageHeight(),grabber.getAudioChannels());
- recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); // avcodec.AV_CODEC_ID_H264,编码
- recorder.setFormat("flv");//封装格式,如果是推送到rtmp就必须是flv封装格式
- recorder.setFrameRate( grabber.getFrameRate());
- recorder.start();//开启录制器
- long startTime=0;
- long videoTS=0;
- CanvasFrame frame = new CanvasFrame("camera", CanvasFrame.getDefaultGamma() / grabber.getGamma());
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- frame.setAlwaysOnTop(true);
- Frame rotatedFrame= null;
- while (frame.isVisible() && (rotatedFrame = grabber.grabFrame()) != null) {
- rotatedFrame = grabber.grabFrame();
- frame.showImage(rotatedFrame);
- if (startTime == 0) {
- startTime = System.currentTimeMillis();
- }
- videoTS = 1000 * (System.currentTimeMillis() - startTime);
- recorder.setTimestamp(videoTS);
- recorder.record(rotatedFrame);
- Thread.sleep(40);
- }
- frame.dispose();
- recorder.stop();
- recorder.release();
- grabber.stop();
- }
- /**
- * 视频截取
- * @param videoFile
- * @throws Exception
- */
- public static void cut2(File videoFile, File outputFile) throws Exception{
- boolean isStart = true;// 该变量建议设置为全局控制变量,用于控制录制结束
- FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(videoFile);
- // // 微秒 大概为设置时间的两倍
- // grabber.setOption(TimeoutOption.RW_TIMEOUT.getKey(), "10000000");
- // rtsp 默认udp 丢包 改为tcp
- // grabber.setOption("rtsp_transport", "tcp");
- grabber.start();
- //好多视频熟悉可以获取后打印 示例几个
- System.out.println("ImageWidth:" + grabber.getImageWidth());
- System.out.println("ImageHeight:" + grabber.getImageHeight());
- System.out.println("AudioChannels:" + grabber.getAudioChannels());
- System.out.println("Format:" + grabber.getFormat());
- FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFile, grabber.getImageWidth(), grabber.getImageHeight(),grabber.getAudioChannels());
- recorder.setFrameRate(grabber.getFrameRate());
- recorder.setAudioBitrate(grabber.getAudioBitrate());
- recorder.setSampleRate(grabber.getSampleRate());
- // recorder.setGopSize(2);
- recorder.setFormat("mp4");
- recorder.setAudioCodecName("aac");
- recorder.setVideoCodec(grabber.getVideoCodec());
- recorder.start();
- Frame frame = null;
- //如果想截取规定时间段视频 请看系列文章二
- while (isStart) {
- frame = grabber.grabFrame();
- if(frame != null){
- recorder.record(frame);
- }
- }
- recorder.stop();
- recorder.release();
- grabber.stop();
- grabber.release();
- }
- public void cut3() throws Exception{
- FFmpeg ffmpeg = new FFmpeg("/path/to/ffmpeg");
- FFprobe ffprobe = new FFprobe("/path/to/ffprobe");
- FFmpegBuilder builder = new FFmpegBuilder()
- .setInput("input.mp4") // Filename, or a FFmpegProbeResult
- .overrideOutputFiles(true) // Override the output if it exists
- .addOutput("output.mp4") // Filename for the destination
- .setFormat("mp4") // Format is inferred from filename, or can be set
- .setTargetSize(250_000) // Aim for a 250KB file
- .disableSubtitle() // No subtiles
- .setAudioChannels(1) // Mono audio
- .setAudioCodec("aac") // using the aac codec
- .setAudioSampleRate(48_000) // at 48KHz
- .setAudioBitRate(32768) // at 32 kbit/s
- .setVideoCodec("libx264") // Video using x264
- .setVideoFrameRate(24, 1) // at 24 frames per second
- .setVideoResolution(640, 480) // at 640x480 resolution
- .setStrict(FFmpegBuilder.Strict.EXPERIMENTAL) // Allow FFmpeg to use experimental specs
- .done();
- FFmpegExecutor executor = new FFmpegExecutor(ffmpeg, ffprobe);
- // Run a one-pass encode
- executor.createJob(builder).run();
- // Or run a two-pass encode (which is better quality at the cost of being slower)
- executor.createTwoPassJob(builder).run();
- }
- public static void main(String[] args) {
- try {
- //getList(10,113);
- File file = new File("e:/20211223123223_76639ced-6400-11ec-b8f9-fa163e4e1e9f.mp4");
- // List<File> files = VideoUtil.fetchPicByCount(file, "E:/223", 100);
- // System.out.println(files.get(0).getName());
- // System.out.println(VideoUtil.getVideoTime(file));
- Date shootEndTime = DateUtils.strToDate("20211223123223","yyyyMMddHHmmss");
- // fetchAllPic(file,"E:/223",shootEndTime);
- // cut3(file,new File("e:/a.mp4"));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
|