博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
javaCV - 视频截帧,清晰度调整,转gif,视频转音频
阅读量:5066 次
发布时间:2019-06-12

本文共 5879 字,大约阅读时间需要 19 分钟。

  最近有视频处理的需求,自己调研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

你可能感兴趣的文章
Hello China操作系统STM32移植指南(一)
查看>>
cocos2dx CCEditBox
查看>>
VC++2012编程演练数据结构《8》回溯法解决迷宫问题
查看>>
第一阶段冲刺06
查看>>
WIN下修改host文件并立即生效
查看>>
十个免费的 Web 压力测试工具
查看>>
ckeditor 粘贴后去除html标签
查看>>
面试题
查看>>
51Nod:活动安排问题之二(贪心)
查看>>
EOS生产区块:解析插件producer_plugin
查看>>
数据库框架的log4j日志配置
查看>>
lintcode-easy-Remove Element
查看>>
mysql 根据地图 坐标 查询 周边景区、酒店
查看>>
mysql重置密码
查看>>
jQuery轮 播的封装
查看>>
一天一道算法题--5.30---递归
查看>>
switchcase的用法
查看>>
React.js 小书 Lesson15 - 实战分析:评论功能(二)
查看>>
Java基础03 构造器与方法重载
查看>>
nginx ------反向代理和负载均衡
查看>>