1、JavaCV实现将视频以帧方式抽取
## JavaCV实现将视频以帧方式抽取```java
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;import static org.bytedeco.javacpp.opencv_core.IplImage;
import static org.bytedeco.javacpp.opencv_core.cvReleaseImage;
import static org.bytedeco.javacpp.opencv_imgcodecs.cvLoadImage;
import static org.bytedeco.javacpp.opencv_imgcodecs.cvSaveImage;
import static org.bytedeco.javacpp.opencv_imgproc.cvSmooth;public class JavaCV {// the image's path;final static String imagePath = "/home/lance/abc.jpg/";// the vedio's path and filename;final static String vedioPath = "/home/lance/target-a/";final static String vedioName = "origin-a.mp4";public static void main(String[] args) throws Exception {smooth(imagePath);grabberFFmpegImage(vedioPath + vedioName, vedioPath, vedioName, 30);}// the method of compress image;public static void smooth(String fileName) {IplImage iplImage = cvLoadImage(fileName);if (iplImage != null) {cvSmooth(iplImage, iplImage);cvSaveImage(fileName, iplImage);cvReleaseImage(iplImage);}}// grab ffmpegImage from vedio;public static void grabberFFmpegImage(String filePath, String fileTargetPath, String fileTargetName, int grabSize) throws Exception{FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);ff.start();for (int i = 0; i < grabSize; i++){Frame frame = ff.grabImage();doExecuteFrame(frame, filePath, fileTargetName, i);}ff.stop();}// grab frame from vedio;public static void doExecuteFrame(Frame frame, String targetFilePath, String targetFileName, int index) {if ( frame == null || frame.image == null) {return;}Java2DFrameConverter converter = new Java2DFrameConverter();String imageMat = "jpg";String fileName = targetFilePath + File.pathSeparator + targetFileName + "_" + index + "." + imageMat;BufferedImage bi = converter.getBufferedImage(frame);File output = new File(fileName);try{ImageIO.write(bi, imageMat, output);} catch (IOException e) {e.printStackTrace();}}
}
2、javaCV视频取
GitHub路径:
https://github.com/chenhua0915/FetchVideoFrameUtil.git
pom文件中的Maven配置:
<!-- https://mvnrepository.com/artifact/org.bytedeco/javacv-platform 视频取帧-->
<dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><version>1.4.4</version>
</dependency>
实例代码:
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;/*** Created with IDEA* 视频取帧,可设置间隔秒数或获取所有帧数** @Author Chensj* @Date 2018/4/2 14:29* @Description* @Version 1.0*/
public class FetchVideoFrameUtil {// 主函数public static void main(String[] args){try {String picPath = "D:\\demo\\pic\\"; // 提取得每帧图片存放位置String videoPath = "D:\\demo1.mp4"; // 原视频文件路径int second = 0; // 每隔多少帧取一张图,一般高清视频每秒 20-24 帧,根据情况配置,如果全部提取,则将second设为 0 即可// 开始视频取帧流程FetchVideoFrameUtil.fetchPic(new File(videoPath),picPath,second);} catch (Exception e) {e.printStackTrace();}}/*** 获取指定视频的帧并保存为图片至指定目录* @param file 源视频文件* @param picPath 截取帧的图片存放路径* @throws Exception*/public static void fetchPic(File file, String picPath,int second) throws Exception{FFmpegFrameGrabber ff = new FFmpegFrameGrabber(file); // 获取视频文件System.out.println(FetchVideoFrameUtil.getVideoTime(file)); // 显示视频长度(秒/s)ff.start(); // 调用视频文件播放int length = ff.getLengthInAudioFrames(); //视频帧数长度System.out.println(ff.getFrameRate());int i = 0; // 图片帧数,如需跳过前几秒,则在下方过滤即可Frame frame = null;int count = 0;while (i < length) {frame = ff.grabImage(); // 获取该帧图片流System.out.print(i + ",");if(frame!=null && frame.image!=null) {System.out.println(i);writeToFile(frame, picPath, count,second); // 生成帧图片count++;}i++;}ff.stop();}/**** @param frame // 视频文件对象* @param picPath // 图片存放路径* @param count // 当前取到第几帧* @param second // 每隔多少帧取一张,一般高清视频每秒 20-24 帧,根据情况配置,如果全部提取,则将second设为 0 即可*/public static void writeToFile(Frame frame, String picPath, int count, int second){if (second == 0) {// 跳过间隔取帧判断} else if (count % second != 0){ // 提取倍数,如每秒取一张,则: second = 20return;}File targetFile = new File(picPath + count + ".jpg");System.out.println("创建了文件:" + picPath + count + ".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) {e.printStackTrace();}}/*** 获取视频时长,单位为秒* @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;}
}
3、Java从视频内截取指定时间的图
此例子可用于:视频内截取某一帧作为封面图(可指定时间)、需要视频内某张图用作表情包。。。
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;public class VideoUtil {public static void main(String[] args) {try {getImgFromVideo("D:\\ffmpeg\\ffmpeg2016\\bin\\ffmpeg.exe", "d:\\ys\\StoryBrooke.mp4", "d:\\ys\\lain.jpg", 204, 140, 0, 0, 26);} catch (Exception e) {e.printStackTrace();}}/*** 获取指定时间内的图片* @param ffmpegPath (ffmpeg路径)* @param videoPath (视频路径)* @param imgPath (图片存放路径)* @param width (图片宽度)* @param height (图片高度)* 以下为需要指定的时间* @param hour* @param min* @param sec* @return*/public static boolean getImgFromVideo(String ffmpegPath, String videoPath, String imgPath, int width,int height, int hour, int min, float sec) {try {ProcessBuilder processBuilder = new ProcessBuilder(ffmpegPath, "-y","-i", videoPath, "-vframes", "1", "-ss", hour + ":" + min+ ":" + sec, "-f", "mjpeg", "-s", width + "*" + height,"-an", imgPath);Process process = processBuilder.start();InputStream stderr = process.getErrorStream();InputStreamReader isr = new InputStreamReader(stderr);BufferedReader br = new BufferedReader(isr);while ((br.readLine()) != null);process.waitFor();if (br != null)br.close();if (isr != null)isr.close();if (stderr != null)stderr.close();} catch (Exception e) {e.printStackTrace();return false;}return true;}
}
4、Javacv截取视频图片
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;import static org.bytedeco.javacpp.opencv_core.IplImage;
import static org.bytedeco.javacpp.opencv_core.cvReleaseImage;
import static org.bytedeco.javacpp.opencv_imgcodecs.cvLoadImage;
import static org.bytedeco.javacpp.opencv_imgcodecs.cvSaveImage;
import static org.bytedeco.javacpp.opencv_imgproc.cvSmooth;public class JavaCV {// the image's path;final static String imagePath = "/home/lance/abc.jpg/";// the vedio's path and filename;final static String vedioPath = "/home/lance/target-a/";final static String vedioName = "origin-a.mp4";public static void main(String[] args) throws Exception {smooth(imagePath);grabberFFmpegImage(vedioPath + vedioName, vedioPath, vedioName, 30);}// the method of compress image;public static void smooth(String fileName) {IplImage iplImage = cvLoadImage(fileName);if (iplImage != null) {cvSmooth(iplImage, iplImage);cvSaveImage(fileName, iplImage);cvReleaseImage(iplImage);}}// grab ffmpegImage from vedio;public static void grabberFFmpegImage(String filePath, String fileTargetPath, String fileTargetName, int grabSize) throws Exception{FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(filePath);ff.start();for (int i = 0; i < grabSize; i++){Frame frame = ff.grabImage();doExecuteFrame(frame, filePath, fileTargetName, i);}ff.stop();}// grab frame from vedio;public static void doExecuteFrame(Frame frame, String targetFilePath, String targetFileName, int index) {if ( frame == null || frame.image == null) {return;}Java2DFrameConverter converter = new Java2DFrameConverter();String imageMat = "jpg";String fileName = targetFilePath + File.pathSeparator + targetFileName + "_" + index + "." + imageMat;BufferedImage bi = converter.getBufferedImage(frame);File output = new File(fileName);try{ImageIO.write(bi, imageMat, output);} catch (IOException e) {e.printStackTrace();}}
}