java如何截取视频帧

1. ffmpeg截取视频

ffmpeg是 处理视频流 合成视频和音频的处理包,可以通过java Command管道通信执行命令的方式来实现视频的截取

这个需要预先安装ffmpeg软件,了解它的一些基础命令,如果截取视频 如何合成视频音频等等,

下面是个拼接命令截取视频的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
* 截取视频图片
* @param videoPath
* @param ffmpegPath
* @return
*/
public static void videoCatchImg(String videoPath, String ffmpegPath) {
File file = new File(videoPath);
if (!file.exists()) {
System.err.println("路径[" + videoPath + "]对应的视频文件不存在!");
return ;
}
List<String> commands = new java.util.ArrayList<String>();
commands.add(ffmpegPath);
//输入文件
commands.add("-i");
commands.add(videoPath);
//输出文件若存在可以覆盖
commands.add("-y");
//指定图片编码格式
commands.add("-f");
commands.add("image2");
//设置截取视频第3秒时的画面
commands.add("-ss");
commands.add("3");
//截取的图片路径
commands.add(videoPath.substring(0, videoPath.lastIndexOf(".")) + "_cover.jpg");
System.out.println("commands:"+commands);
try {
ProcessBuilder builder = new ProcessBuilder();
builder.command(commands);
builder.start();
} catch (Exception e) {
e.printStackTrace();
}
return;
}

2.使用javacv

JavaCV是对各种常用计算机视觉库的封装后的一组jar包,其中封装了FFmpeg、OpenCV等计算机视觉编程人员常用库的接口,可以通过其中的Utility类方便的在包括Android在内的Java平台上调用这些接口。其中使用最多的应该就是FFmpeg了。

最开始Javacv是googlecode下面的一个项目,后来迁移到了github,因此JavaCV相关的包名也由com.googlecode.javacv改为org.bytedeco.javacv。目前最新版本是 1.3.3。项目地址:https://github.com/bytedeco/javacv

普通直接引入javacv包太大,之前我引入之后直接大了400M, 后续我使用 网上看到一篇文章,只引入需要的包 只用ffmpeg 并只导入相关平台适配,调整到只有40MB大小下面是引入包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
<!--  截取视频第一帧 -->
<!-- 视频帧截取 -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.4.1</version>
<exclusions>
<exclusion>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>flycapture</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>libdc1394</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>libfreenect</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>libfreenect2</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>librealsense</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>videoinput</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>artoolkitplus</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>artoolkitplus</artifactId>
</exclusion>
<exclusion>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>flandmark</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>opencv</artifactId>
<version>3.4.1-${javacpp.version}</version>
<classifier>linux-x86_64</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>ffmpeg</artifactId>
<version>3.4.2-${javacpp.version}</version>
<classifier>linux-x86_64</classifier>
</dependency>

<!-- <dependency>-->
<!-- <groupId>org.bytedeco</groupId>-->
<!-- <artifactId>javacv-platform</artifactId>-->
<!-- <version>1.4.1</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.bytedeco</groupId>-->
<!-- <artifactId>javacv</artifactId>-->
<!-- <version>1.4.1</version>-->
<!-- </dependency>-->
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* 截取视频第几帧的图片
*
* @param videoInputStream 视频流
* @param framePos 获取第几帧
* @param os 输出流
* @return 图片的相对路径 例:pic/1.png
*/
public static void getVideoCoverByInputStream(InputStream videoInputStream, int framePos, OutputStream os) throws Exception {
FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoInputStream);
ff.start();
int ffLength = ff.getLengthInFrames();
Frame f;
int i = 0;
while (i < ffLength) {
f = ff.grabFrame();
//截取第几帧
if ((i > framePos) && (f.image != null)) {
//执行截图并放入指定位置
doExecuteFrame(f, os);
break;
}
i++;
}
ff.stop();
IOUtils.closeQuietly(videoInputStream);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 截取缩略图
*
* @param f Frame
* @param os 对外outputStream
*/
private static void doExecuteFrame(Frame f, OutputStream os) {
String imagemat = "png";
if (null == f || null == f.image) {
return;
}
Java2DFrameConverter converter = new Java2DFrameConverter();
BufferedImage bi = converter.getBufferedImage(f);
try {
ImageIO.write(bi, imagemat, os);
} catch (IOException e) {
e.printStackTrace();
}
}