目录
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>video</groupId>
<artifactId>ffmpeg</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>ffmpeg</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 根据自己的的电脑系统选择 -->
<javacpp.platform.dependencies>linux-x86_64</javacpp.platform.dependencies>
<!-- <javacpp.platform.android-arm>android-arm</javacpp.platform.android-arm>
<javacpp.platform.android-arm64>android-arm64</javacpp.platform.android-arm64>
<javacpp.platform.android-x86>android-x86</javacpp.platform.android-x86>
<javacpp.platform.android-x86_64>android-x86_64</javacpp.platform.android-x86_64>
<javacpp.platform.ios-arm>ios-arm</javacpp.platform.ios-arm>
<javacpp.platform.ios-arm64>ios-arm64</javacpp.platform.ios-arm64>
<javacpp.platform.ios-x86>ios-x86</javacpp.platform.ios-x86>
<javacpp.platform.ios-x86_64>ios-x86_64</javacpp.platform.ios-x86_64>
<javacpp.platform.linux-armhf>linux-armhf</javacpp.platform.linux-armhf>
<javacpp.platform.linux-arm64>linux-arm64</javacpp.platform.linux-arm64>
<javacpp.platform.linux-ppc64le>linux-ppc64le</javacpp.platform.linux-ppc64le>
<javacpp.platform.linux-x86>linux-x86</javacpp.platform.linux-x86>
<javacpp.platform.linux-x86_64>linux-x86_64</javacpp.platform.linux-x86_64>
<javacpp.platform.macosx-x86_64>macosx-x86_64</javacpp.platform.macosx-x86_64>
<javacpp.platform.windows-x86>windows-x86</javacpp.platform.windows-x86>
<javacpp.platform.windows-x86_64>windows-x86_64</javacpp.platform.windows-x86_64> -->
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
<relativePath />
<!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- 视频处理 -->
<!-- https://mvnrepository.com/artifact/org.bytedeco/javacv -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.4.3</version>
<!-- <exclusions>
<exclusion>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions> -->
</dependency>
<!-- https://mvnrepository.com/artifact/org.bytedeco/javacpp -->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>1.4.3</version>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>opencv</artifactId>
<version>3.4.3-1.4.3</version>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>opencv</artifactId>
<version>3.4.3-1.4.3</version>
<classifier>${javacpp.platform.dependencies}</classifier>
</dependency>
<!-- https://mvnrepository.com/artifact/org.bytedeco.javacpp-presets/ffmpeg -->
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>ffmpeg</artifactId>
<version>4.0.2-1.4.3</version>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>ffmpeg</artifactId>
<version>4.0.2-1.4.3</version>
<classifier>${javacpp.platform.dependencies}</classifier>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
SpringApplication.java
package video.ffmpeg;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication
public class App extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
Controller.java
package video.ffmpeg;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.scheduling.annotation.Async;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import util.FFmpeg;
@RequestMapping("/video")
@RestController
public class VideoController {
/**
* 根据URL获取domain
* @param url
* @return
*/
public static String getDomainForUrl(String url){
String domainUrl = null;
if (url == null) {
return null;
} else {
Pattern p = Pattern.compile("(?<=http://|\\.)[^.]*?\\.(com|cn|net|org|biz|info|cc|tv)",Pattern.CASE_INSENSITIVE);
Matcher matcher = p.matcher(url);
while(matcher.find()){
domainUrl = matcher.group();
}
return domainUrl;
}
}
//获取视频封面图
@RequestMapping("getFramImage")
@Async
public void getFramImage(String url, HttpServletRequest request, HttpServletResponse response) throws Exception {
if(StringUtils.isEmpty(url)) {
return;
}
InputStream inputStream = FFmpeg
.fetchFrame(url);
long length = inputStream.available();
// 输出流
byte[] bytes = new byte[1024];
OutputStream outputStream = response.getOutputStream();
long count = 0;
while (count < length) {
int len = inputStream.read(bytes, 0, 1024);
count += len;
outputStream.write(bytes, 0, len);
}
outputStream.flush();
}
}
Util
package util;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.util.ObjectUtils;
public class FFmpeg {
public static InputStream fetchFrame(String videofile) throws Exception {
return fetchFrame(videofile,null);
}
// 参数:视频路径和缩略图保存路径
public static InputStream fetchFrame(String videofile, String framefile) throws Exception {
long start = System.currentTimeMillis();
// File targetFile = new File(framefile);
FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videofile);
ff.start();
int length = ff.getLengthInFrames();
int i = 0;
Frame f = null;
while (i < length) {
// 去掉前5帧,避免出现全黑的图片,依自己情况而定
f = ff.grabImage();
if ((i > 5) && (f.image != null)) {
break;
}
i++;
}
// ImageIO.write(FrameToBufferedImage(f), "jpg", targetFile);
BufferedImage old = FrameToBufferedImage(f);
int owidth = old.getWidth();
int oheight = old.getHeight();
// 对截取的帧进行等比例缩放
int width = 400;
int height = (int) (((double) width / owidth) * oheight);
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
bi.getGraphics().drawImage(old.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);
// ff.flush();
bi.getGraphics().dispose();
ff.stop();
//BufferedImage 转 InputStream
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageOutputStream imageOutput = ImageIO.createImageOutputStream(byteArrayOutputStream);
ImageIO.write(bi, "png", imageOutput);
if(!ObjectUtils.isEmpty(framefile)) {
//ImageIO.write(bi, "jpg", targetFile);
}
System.out.println(System.currentTimeMillis() - start);
InputStream inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
return inputStream;
}
public static BufferedImage FrameToBufferedImage(Frame frame) {
// 创建BufferedImage对象
Java2DFrameConverter converter = new Java2DFrameConverter();
BufferedImage bufferedImage = converter.getBufferedImage(frame);
return bufferedImage;
}
/**
* @param args
*/
public static void main(String[] args) throws Exception {
try {
} catch (Exception e) {
// TODO: handle exception
}
}
}