Java截取视频首帧并旋转正向
package test; import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet; import javax.imageio.ImageIO; import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter; public class VideoTest { public static String image_type="jpg";
public static String file_type="mp4"; public static void main(String[] args) {
String videofile="C:/xmqtest/test视频.mp4";//或网络视频地址
String framefileDir="C:/xmqtest/";
String targetFilePath=fetchFrame(videofile,framefileDir);
} /**
* 获取指定视频的帧并保存为图片至指定目录
* @param videofile 源视频文件路径
* @param framefile 截取帧的图片存放路径
* @throws Exception
*/
public static String fetchFrame(String videofile, String framefileDir){
try{
int startIndex=videofile.lastIndexOf('/');
String fileName;
if(startIndex==-1){
fileName=videofile.substring(videofile.lastIndexOf('\\')+1, videofile.lastIndexOf('.'));
}else{
fileName=videofile.substring(startIndex+1, videofile.lastIndexOf('.')+1);
}
String targetFileName=framefileDir+fileName+image_type;
File targetFile=createFile(targetFileName);
FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videofile);
ff.start();
String rotate_old=ff.getVideoMetadata("rotate");//视频旋转角度,可能是null
int length = ff.getLengthInFrames();
int i = 0;
Frame f = null;
while (i < length) {
// 过滤前5帧,避免出现全黑的图片,依自己情况而定
f = ff.grabFrame();
if ((i > 5) && (f.image != null)) {
break;
}
i++;
}
// IplImage img = f.image;
int owidth = f.imageWidth;
int oheight = f.imageHeight;
// 对截取的帧进行等比例缩放
int width = 300;//生成图片宽度为300px
int height = (int) (((double) width / owidth) * oheight);
Java2DFrameConverter converter = new Java2DFrameConverter();
BufferedImage fecthedImage = converter.getBufferedImage(f);
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
bi.getGraphics().drawImage(fecthedImage.getScaledInstance(width, height, Image.SCALE_SMOOTH),
0, 0, null);
ImageIO.write(bi, image_type, targetFile);
ff.stop();
//有需要旋转
if(rotate_old!=null && !rotate_old.isEmpty()){
int rotate=Integer.parseInt(rotate_old);
rotatePhonePhoto(targetFileName,rotate);
}
return targetFileName;
}catch(Exception e){
e.printStackTrace();
}
return null;
}/***
* 创建文件,目录不存在则先创建目录在创建文件
* @param destFileName
* @return
*/
public static File createFile(String destFileName) {
try {
File file = new File(destFileName);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
file.createNewFile();
return file;
} catch (IOException e) {
e.printStackTrace();
return null;
}
} /**
* 删除单个文件
*/
public static void deleteFile(String sPath) {
File file = new File(sPath);
if (file.isFile() && file.exists()) {
file.delete();
}
} /**
* 旋转照片
*
* @return
*/
public static String rotatePhonePhoto(String fullPath, int angel) {
BufferedImage src;
try {
src = ImageIO.read(new File(fullPath));
int src_width = src.getWidth(null);
int src_height = src.getHeight(null); int swidth = src_width;
int sheight = src_height; if (angel == 90 || angel == 270) {
swidth = src_height;
sheight = src_width;
}
Rectangle rect_des = new Rectangle(new Dimension(swidth, sheight));
BufferedImage res = new BufferedImage(rect_des.width, rect_des.height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = res.createGraphics();
g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);
g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);
g2.drawImage(src, null, null);
ImageIO.write(res,image_type, new File(fullPath));
} catch (Exception e) {
e.printStackTrace();
}
return fullPath; }
}
说明点:
1、加入依赖,经测试两个依赖在windows环境,linux环境下正常使用。如果本地windows环境正常但是在linux下失败,请使用以下依赖。
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.4.3</version>
</dependency> <dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>ffmpeg-platform</artifactId>
<version>4.0.2-1.4.3</version>
</dependency> 2、针对iphone手机视频等需要进行首帧图片旋转,否则出现首帧图片横着的情况。如代码部分:
String rotate_old=ff.getVideoMetadata("rotate");//视频旋转角度,可能是null
Java截取视频首帧并旋转正向的更多相关文章
- vue 截取视频第一帧
最近自己写项目,在项目中涉及功能点又截取视频帧的点:需求澄清:移动端封面展示,平台上传图片(多张上传)取第一张上传图片为封面图:如上传视频则截取视频第一帧作为封面图: 实现思路:h5 video标签 ...
- php ffmpeg截取视频第一帧保存为图片的方法
php ffmpeg截取视频第一帧保存为图片的方法 <pre> $xiangmupath = $this->getxiangmupath(); $filename = 'chengs ...
- 使用javacv 截取视频指定帧节
个人博客 地址:https://www.wenhaofan.com/article/20190407105818 引入依赖 <dependency> <groupId>org. ...
- Java截取视频文件缩略图
/** * 截取视频第0帧的图片 */public static void videoImage(String filePath, String fileName,int widthdist, int ...
- java获取视频的第一帧
//------------maven配置文件--------------- <dependency> <groupId>org.bytedeco</groupId> ...
- 【Java SE】使用Javacv截取视频图片
[Java Web开发学习]使用Javacv截取视频图片 转载:https://www.cnblogs.com/yangchongxing/p/9482935.html github地址:https: ...
- 用java实现给图片增加图片水印或者文字水印(也支持视频图像帧添加水印)
javaCV图像处理系列: javaCV图像处理之1:实时视频添加文字水印并截取视频图像保存成图片,实现文字水印的字体.位置.大小.粗度.翻转.平滑等操作 javaCV图像处理之2:实时视频添加图片水 ...
- java获取视频播第一帧
FFMPEG 功能很强大,做视频必备的软件.大家可通过 http://ffmpeg.org/ 了解.Windows版本的软件,可通过 http://ffmpeg.zeranoe.com/builds/ ...
- python opencv 按一定间隔截取视频帧
前言关于opencvOpenCV 是 Intel 开源计算机视觉库 (Computer Version) .它由一系列 C 函数和少量 C++ 类构成,实现了图像处理和计算机视觉方面的很多通用算法. ...
随机推荐
- C++系统学习之六:函数
1.函数基础 典型的函数定义包括:返回类型.函数名.由0个或多个形参组成的列表以及函数体. 2.参数传递 形参初始化的机理和变量初始化一样. 有两种方式:引用传递和值传递 2.1 传值参数 当形参是非 ...
- PAT 乙级 1009
题目 题目地址:PAT 乙级 1009 题解 本题本身属于比较简单的字符串操作题,但是因为对于string的操作和函数不熟悉导致本题做起来很费劲,需要加强对于string类以及相关方法的理解和熟练程度 ...
- [OpenJudge] 2727 仙岛寻药
2727:仙岛求药 查看 提交 统计 提问 总时间限制: 1000ms 内存限制: 65536kB 描述 少年李逍遥的婶婶病了,王小虎介绍他去一趟仙灵岛,向仙女姐姐要仙丹救婶婶.叛逆但孝顺的李逍遥闯进 ...
- 2018-10-09中国裁判文书网爬虫vl5x和DocID分析
本来是想要抓取食药监的药品数据,看到js加密很繁琐,调了一个星期没有结果,想看看其他类似网站的js加密情况,发现裁判文书网的加密好像不是太复杂,经过两天的分析和编写,基本把vl5x加密和DocID解密 ...
- php数据查询之基础查询
---恢复内容开始--- 数据查询语言(Data Query Language) 基本查询 语法形式: select [all | distinct ] 字段或者表达式列表 [from子句] [whe ...
- shell-note-1-基础篇
1. Shell is a program written in C. It provides an interface for users to access to the service of o ...
- python基础学习笔记——collections模块
在内置数据类型(dict.list.set.tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter.deque.defaultdict.namedtuple和Ord ...
- struts 乱码
在进行struts开发的过程中,总也是出现很多的乱码问题 ,但归根到底,也只是以下三种情况: ㈠页面显示中文乱码 ㈡传递参数中文乱码 ㈢国际化资源文件乱码 下面就这三中情况介绍怎么在具体项目中处理这些 ...
- Visual Studio 2013 中使用断点
你可能已经很熟悉Visual Studio中的断点的基本功能.你在编辑器里代码的侧边点击,创建一个红色的圆点,然后运行应用程序,线程走到你所点的代码处停下,你可以用调试窗口查看代码状态. 你可能不熟悉 ...
- 关于面试总结-SQL经典面试题
关于面试总结6-SQL经典面试题 前言 用一条SQL 语句查询xuesheng表每门课都大于80 分的学生姓名,这个是面试考sql的一个非常经典的面试题 having和not in 查询 xueshe ...