javaCV - 视频截帧,清晰度调整,转gif,视频转音频

it2022-05-05  133

  最近有视频处理的需求,自己调研javaCV。

  官网没有详细的API,各种轮子翻遍了也没找到几个有用的,以下是自己整理一些视频处理功能:截取视频指定帧生成gif,将图片旋转指定度,截取视频指定帧保存为指定格式的图片(图片保存在视频同文件夹下),调整视频清晰度(只能降低)视频转音频

  先上代码。

package com.richinfo.media.utils;import com.madgag.gif.fmsware.AnimatedGifEncoder;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;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStream;/** * @author */public class VideoUtils {/** * 截取视频指定帧生成gif * * @param videofile 视频文件 * @param startFrame 开始帧 * @param frameCount 截取帧数 * @param frameRate 帧频率(默认:3) * @param margin 每截取一次跳过多少帧(默认:3) * @throws java.io.IOException 截取的长度超过视频长度 */ public static void buildGif(String videofile, int startFrame, int frameCount, Integer frameRate, Integer margin) throws IOException {if (margin == null) { margin = 3; }if (frameRate == null) { frameRate = 3; } FileOutputStream targetFile = new FileOutputStream(videofile.substring(0, videofile.lastIndexOf(".")) + ".gif"); FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videofile); Java2DFrameConverter converter = new Java2DFrameConverter(); ff.start();try {if (startFrame > ff.getLengthInFrames() & (startFrame + frameCount) > ff.getLengthInFrames()) {throw new RuntimeException("视频太短了"); } ff.setFrameNumber(startFrame); AnimatedGifEncoder en = new AnimatedGifEncoder(); en.setFrameRate(frameRate); en.start(targetFile);for (int i = 0; i < frameCount; i++) { en.addFrame(converter.convert(ff.grabImage())); ff.setFrameNumber(ff.getFrameNumber() + margin); } en.finish(); } finally { ff.stop(); ff.close(); } }/** * 将图片旋转指定度 * * @param bufferedimage 图片 * @param degree 旋转角度 * @return */ public static BufferedImage rotateImage(BufferedImage bufferedimage, int degree) {// 得到图片宽度。 int w = bufferedimage.getWidth();// 得到图片高度。 int h = bufferedimage.getHeight();// 得到图片透明度。 int type = bufferedimage.getColorModel().getTransparency();// 空的图片。 BufferedImage img;// 空的画笔。 Graphics2D graphics2d; (graphics2d = (img = new BufferedImage(w, h, type)) .createGraphics()).setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);// 旋转,degree是整型,度数,比如垂直90度。 graphics2d.rotate(Math.toRadians(degree), w / 2, h / 2);// 从bufferedimagecopy图片至img,0,0是img的坐标。 graphics2d.drawImage(bufferedimage, 0, 0, null); graphics2d.dispose();// 返回复制好的图片,原图片依然没有变,没有旋转,下次还可以使用。 return img; }/** * 截取视频指定帧保存为指定格式的图片(图片保存在视频同文件夹下) * * @param videofile 视频地址 * @param imgSuffix 图片格式 * @param indexFrame 第几帧(默认:5) * @throws Exception */ public static void fetchFrame(String videofile, String imgSuffix, Integer indexFrame) throws Exception {if (indexFrame == null) { indexFrame = 5; } Integer suffixIndex = videofile.lastIndexOf("."); File targetFile = new File((suffixIndex != -1 ? videofile.substring(0, suffixIndex) : videofile) + imgSuffix);try (FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videofile); OutputStream outputStream = new FileOutputStream(targetFile)) { ff.start(); ff.setFrameNumber(indexFrame); Frame f = ff.grabImage(); Java2DFrameConverter converter = new Java2DFrameConverter(); BufferedImage fecthedImage = converter.getBufferedImage(f); ImageIO.write(fecthedImage, "jpg", outputStream); } }public static void main(String[] args) {try {fetchFrame("C:\\Users\\Desktop\\b9aef3a28becab2e9e3c544caf70bfde.mp4", ".jpg", 100);buildGif("C:\\Users\\Desktop\\b9aef3a28becab2e9e3c544caf70bfde.mp4", 50, 10, 3, 50); } catch (Exception e) { e.printStackTrace(); } }} package com.richinfo.media.utils;import lombok.SneakyThrows;import org.apache.commons.io.IOUtils;import org.bytedeco.javacpp.avcodec;import org.bytedeco.javacv.CanvasFrame;import org.bytedeco.javacv.FFmpegFrameGrabber;import org.bytedeco.javacv.FFmpegFrameRecorder;import org.bytedeco.javacv.Frame;import javax.swing.*;/** * @author * @create */public class Test {private static boolean isStart = true;@SneakyThrows public static void main(String[] args) {frameRecord("C:\\Users\\Desktop\\b9aef3a28becab2e9e3c544caf70bfde.mp4", "C:\\Users\\Desktop\\b9aef3a28becab2e9e3c544caf70bf602.mp4"); }public static void frameRecord(String inputFile, String outputFile)throws Exception, org.bytedeco.javacv.FrameRecorder.Exception {// 获取视频源 FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile); grabber.setOption("rtsp_transport", "tcp");// //速度// grabber.setFrameRate(30);// //码率// grabber.setVideoBitrate(3000000); // 流媒体输出地址,分辨率(长,高),是否录制音频(0:不录制/1:录制) FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFile, 2);// recorder.setFrameRate(30); recorder.setVideoBitrate(720 * 576);//编码格式 recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); //avcodec.AV_CODEC_ID_H264 //AV_CODEC_ID_MPEG4 recordByFrame(grabber, recorder); }private static void recordByFrame(FFmpegFrameGrabber grabber, FFmpegFrameRecorder recorder)throws Exception, org.bytedeco.javacv.FrameRecorder.Exception {try {// 建议在线程中使用该方法 grabber.start();// CanvasFrame canvas = new CanvasFrame("摄像头");//新建一个窗口// canvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// canvas.setAlwaysOnTop(true); recorder.setImageHeight(grabber.getImageHeight()); recorder.setImageWidth(grabber.getImageWidth()); recorder.start();long t1 = System.currentTimeMillis(); Frame frame = null;while (isStart && (frame = grabber.grabFrame()) != null) {long t2 = System.currentTimeMillis();if (t2 - t1 > 2 * 60 * 60 * 1000) {break; } else {//视频转音频 grabber.grabSamples(); recorder.record(frame);//TODO your work }//canvas.showImage(grabber.grab());//获取摄像头图像并放到窗口上显示, 这里的Frame frame=grabber.grab(); frame是一帧视频图像 } recorder.stop(); grabber.stop(); } finally { IOUtils.closeQuietly(recorder); IOUtils.closeQuietly(grabber); } }}相关依赖:

转载于:https://www.cnblogs.com/afei-li/p/10643049.html

相关资源:视频文件转GIF工具(FreeVideoToGif)下载

最新回复(0)