Java视频截图 ffmpeg opencv

1.引入依赖
截图主要用ffmpeg和opencv

<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacv</artifactId>
    <version>1.5</version>
    <exclusions>
        <exclusion>
        	<!-- 去除不需要的jar包 -->
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>*</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>ffmpeg</artifactId>
    <version>4.1.3-1.5</version>
</dependency>
<!-- 此处引用的是包含所有Linux环节的jar包,根据自己的环境选择对应的依赖就好,没必要这么多。以下opencv的依赖与此处相似 -->
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>ffmpeg</artifactId>
    <version>4.1.3-1.5</version>
    <classifier>linux-x86_64</classifier>
</dependency>

<dependency>
    <groupId>org.bytedeco.javacpp-presets</groupId>
    <artifactId>opencv</artifactId>
    <version>4.0.1-1.4.4</version>
</dependency>
<!-- 环境 -->
<dependency>
    <groupId>org.bytedeco.javacpp-presets</groupId>
    <artifactId>opencv</artifactId>
    <version>4.0.1-1.4.4</version>
    <classifier>linux-x86_64</classifier>
</dependency>

例如需要在Windows环境运行该程序,则引用对应的依赖

<dependency>
    <groupId>org.bytedeco.javacpp-presets</groupId>
    <artifactId>ffmpeg</artifactId>
    <version>4.1.3-1.5</version>
    <classifier>windows-x86_64</classifier>
</dependency>
<dependency>
    <groupId>org.bytedeco.javacpp-presets</groupId>
    <artifactId>opencv</artifactId>
    <version>4.0.1-1.4.4</version>
    <classifier>windows-x86_64</classifier>
</dependency>

2.使用
截取视频第6帧的图片,返回图片流

/**
 * 根据视频流截取第 6 帧的图片
 * @param videoFile 视频流
 * @throws Exception
 */
private InputStream fetchFrame(InputStream videoFile) throws Exception{

    FFmpegFrameGrabber fFmpegFrameGrabber = new FFmpegFrameGrabber(videoFile);
    fFmpegFrameGrabber.start();
    int length = fFmpegFrameGrabber.getLengthInFrames();
    int index = 0;
	Frame frame = null;
	while (index < length){
		frame = fFmpegFrameGrabber.grabImage();
		if (index > 5 && frame.image != null) {
			break;
		}
		index++;
	}
	Java2DFrameConverter converter = new Java2DFrameConverter();
	BufferedImage bufferedImage = converter.getBufferedImage(frame);

	ByteArrayOutputStream os = new ByteArrayOutputStream();
	ImageIO.write(bufferedImage, "jpg", os);
	fFmpegFrameGrabber.close();
	return new ByteArrayInputStream(os.toByteArray());
}

3.将视频和图片上传到阿里云OSS上

/**
 * 视频文件上传
 * 仅支持inux-x86_64 环境
 */
@Override
public String uploadVideo(String tempPath,MultipartFile file)throws Exception{
        //文件名前缀
        String prefix=merchant==null?String.format("%04d",0):String.format("%04d",merchant.getMerchantId());
        String videoUrl=AliyunOssUtil.uploadFile(file.getInputStream(),AliyunOssUtil.generateNewFileName(file.getOriginalFilename(),prefix,""), "");
        String videoPoster=AliyunOssUtil.uploadFile(fetchFrame(file.getInputStream()),AliyunOssUtil.generateNewFileName("",prefix,".jpg"),"");
        return new ResultObject(XXXX)).toJSONString();
}
public class AliyunOssUtil {

    private static Logger logger  =  LoggerFactory.getLogger(AliyunOssUtil.class);

    private static final String ENDPOINT = "xxxxxxxxx";
    
    public static String ACCESS_URL;
    
    private static String BUCKET;
    
    private static final String ACCESS_KEY_ID = "xxxxxxxxxxxxxxxxxxxxxx";
    
    private static final String ACCESS_KEY_SECRET = "xxxxxxxxxxxxxxxxxxxxxxxxx";
    
    static {
    	if ("idc".equals(CommonUtil.getServerMode())) {
    		ACCESS_URL = "xxxxxxxxxxxxxxxxxxxxx";
    	    BUCKET = "xxxxxxxxxxxxxxxxxxxxxx";
    	} else {
    		ACCESS_URL = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
    		BUCKET = "xxxxxxxxxxxxxxxxxxx";
    	}
    }
    
    /**
     * 生成新的文件名
     * 
     * @param originalFileName 原始的文件名
     * @param prefix 前缀
     * @param suffix 后缀
     * @return
     */
    public static String generateNewFileName(String originalFileName, String prefix, String suffix) {
    	//随机生成的字符串
    	String generateStr = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()) + RandomUtil.generateRandomNumber(5);
    	//文件类型后缀
    	String fileTypeStr = "";
    	int fileTypeIndex = originalFileName.lastIndexOf(".");
    	if (fileTypeIndex >= 0) {
    		fileTypeStr = originalFileName.substring(fileTypeIndex);
    	}
    	return CommonUtil.getServerMode().substring(0, 1) + prefix + generateStr + suffix + fileTypeStr;
    }
    
    /**
     * 上传文件到OSS
     * 
     * @param file
     * @param fileName
     * @return
     * @throws Exception
     */
    public static String uploadFile(File file, String fileName) throws Exception {
    	return uploadFile(new FileInputStream(file), fileName);
    }
    
    /**
     * 上传文件流到OSS
     * 
     * @param inputStream
     * @param fileName
     * @return
     * @throws Exception
     */
    public static String uploadFile(InputStream inputStream, String fileName) throws Exception {
    	
    	// 创建ClientConfiguration。ClientConfiguration是OSSClient的配置类,可配置代理、连接超时、最大连接数等参数。
    	ClientConfiguration conf = new ClientConfiguration();
    	// 设置OSSClient允许打开的最大HTTP连接数,默认为1024个。
//    	conf.setMaxConnections(200);
    	// 设置Socket层传输数据的超时时间,默认为50000毫秒。
//    	conf.setSocketTimeout(10000);
    	// 设置建立连接的超时时间,默认为50000毫秒。
//    	conf.setConnectionTimeout(10000);
    	// 设置从连接池中获取连接的超时时间(单位:毫秒),默认不超时。
//    	conf.setConnectionRequestTimeout(1000);
    	// 设置连接空闲超时时间。超时则关闭连接,默认为60000毫秒 。
//    	conf.setIdleConnectionTime(10000);
    	// 设置失败请求重试次数,默认为3次。
//    	conf.setMaxErrorRetry(5);
    	// 设置是否支持将自定义域名作为Endpoint,默认支持。
//    	conf.setSupportCname(true);
    	// 设置是否开启二级域名的访问方式,默认不开启。
//    	conf.setSLDEnabled(true);
    	// 设置连接OSS所使用的协议(HTTP/HTTPS),默认为HTTP。
//    	conf.setProtocol(Protocol.HTTP);
    	// 设置用户代理,指HTTP的User-Agent头,默认为aliyun-sdk-java。
//    	conf.setUserAgent("aliyun-sdk-java");
    	// 设置代理服务器端口。
//    	conf.setProxyHost("<yourProxyHost>");
    	// 设置代理服务器验证的用户名。
//    	conf.setProxyUsername("<yourProxyUserName>");
    	// 设置代理服务器验证的密码。
//    	conf.setProxyPassword("<yourProxyPassword>");
    	
    	// 创建OSSClient实例
    	OSSClient ossClient = new OSSClient(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET, conf);
    	
    	// 创建上传文件的元信息,可以通过文件元信息设置HTTP header
    	ObjectMetadata meta = new ObjectMetadata();
//    	String md5 = BinaryUtil.toBase64String(BinaryUtil.calculateMd5(content.getBytes()));
    	// 开启文件内容MD5校验。开启后OSS会把您提供的MD5与文件的MD5比较,不一致则抛出异常。
//    	meta.setContentMD5(md5);
    	// 指定上传的内容类型。内容类型决定浏览器将以什么形式、什么编码读取文件。如果没有指定则根据文件的扩展名生成,如果没有扩展名则为默认值application/octet-stream。
//    	meta.setContentType("text/plain");
    	// 设置内容被下载时的名称。
//    	meta.setContentDisposition("Download File Name");
    	// 设置上传文件的长度。如超过此长度,则会被截断,为设置的长度。如不足,则为上传文件的实际长度。
//    	meta.setContentLength(content.length());
    	// 设置内容被下载时网页的缓存行为。
//    	meta.setCacheControl("Download Action");
    	// 设置缓存过期时间,格式是格林威治时间(GMT)。
//    	meta.setExpirationTime(DateUtil.parseIso8601Date("2022-10-12T00:00:00.000Z"));
    	// 设置内容被下载时的编码格式。
//    	meta.setContentEncoding("utf-8");
    	// 设置header。
//    	meta.setHeader("<yourHeader>", "<yourHeaderValue>");
    	
    	// 上传文件流
    	ossClient.putObject(BUCKET, fileName, inputStream, meta);
    	
    	// 关闭OSSClient
    	ossClient.shutdown();
    	
    	return ACCESS_URL + URLEncoder.encode(fileName, "utf-8");
    }

	/**
	 * 上传文件流到OSS
	 * 若上传到BUCKET下的子目录,则在原有的文件名加上前缀,如:video/视频名称.mp4
	 * @param inputStream
	 * @param fileName
	 * @return
	 * @throws Exception
	 */
	public static String uploadFile(InputStream inputStream, String fileName, String subdirectory) throws Exception {
		ClientConfiguration conf = new ClientConfiguration();
		OSSClient ossClient = new OSSClient(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET, conf);
		ObjectMetadata meta = new ObjectMetadata();
		ossClient.putObject(BUCKET, subdirectory + fileName, inputStream, meta);
		ossClient.shutdown();
		return ACCESS_URL + subdirectory + URLEncoder.encode(fileName, "utf-8");

	}

	//BUCKET下的子目录
    public static void deleteVideoFile(String keyFile){
		ClientConfiguration conf = new ClientConfiguration();
		String fileNameTemp = keyFile.substring(0, keyFile.indexOf("?"));
		String fileVideoName = fileNameTemp.substring(fileNameTemp.lastIndexOf("/video") + 1);
		String fileImageName = keyFile.substring(keyFile.lastIndexOf("/video") + 1);
		OSSClient ossClient = new OSSClient(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET, conf);
		ossClient.deleteObject(BUCKET,  fileVideoName);
		ossClient.deleteObject(BUCKET,  fileImageName);

	}
}

若上传到BUCKET下的子目录,则在原有的文件名加上前缀,如:video/视频名称.mp4

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值