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
    评论
### 回答1: Java本身不提供对视频和音频的处理功能,但可以使用第三方库来实现去除视频文件中的声音。常用的库是Xuggler和JAVE(Java Audio Video Encoder),它们都支持通过Java代码调用FFmpeg。以下是使用Xuggler的示例代码: ```java import com.xuggle.mediatool.IMediaReader; import com.xuggle.mediatool.IMediaWriter; import com.xuggle.mediatool.ToolFactory; import com.xuggle.xuggler.ICodec; public class RemoveAudioFromVideo { public static void main(String[] args) { String inputFilePath = "input.mp4"; String outputFilePath = "output.mp4"; IMediaReader mediaReader = ToolFactory.makeReader(inputFilePath); IMediaWriter mediaWriter = ToolFactory.makeWriter(outputFilePath, mediaReader); mediaReader.addListener(mediaWriter); mediaWriter.setForceInterleave(true); mediaWriter.addVideoStream(0, 0, ICodec.ID.CODEC_ID_H264, mediaReader.getContainer().getStream(0).getFrameRate().getDouble()); mediaWriter.addAudioStream(1, 0, 0, 0, 0); while (mediaReader.readPacket() == null) ; } } ``` 这段代码使用Xuggler读取输入文件,并将视频流写入到输出文件中,同时添加一个空音频流,从而达到去除视频文件中声音的目的。需要注意的是,Xuggler已经停止维护,如果需要更高级的功能,建议使用FFmpegJava接口或其他第三方库。 ### 回答2: Java本身没有提供直接去除视频文件中声音的功能,需要借助外部库或工具来实现此功能。FFmpeg是一个功能强大的音视频处理工具,可以用于处理和编辑音视频文件,包括去除视频中的声音。然而,Java并不直接集成FFmpeg,因此无法直接使用FFmpeg去除视频文件中的声音。 要使用Java去除视频文件中的声音,可以借助其他的Java库或框架来实现。一种方法是使用JavaCV库,它是一个基于JavaOpenCVFFmpeg的接口库,可以让Java程序调用FFmpeg的功能。在使用JavaCV时,你可以调用FFmpeg的命令行参数来去除视频文件中的声音。 另一种方法是使用Java自带的音视频处理库,如javax.sound.sampled库来处理音频,然后使用Java形库如JavaFX来处理视频。可以使用这些库读取原始的视频文件和音频文件,然后分离音频轨道和视频轨道,再将分离出的视频轨道合成成一个新的视频文件,从而达到去除视频文件中声音的效果。 总结来说,Java本身没有直接提供去除视频文件中声音的功能,但可以借助其他的Java库或工具来实现此功能,如JavaCV库或javax.sound.sampled库等。 ### 回答3: 在Java中,不使用FFmpeg去除视频文件中的声音是有一定的难度的。因为Java自带的库并没有提供直接处理视频文件的功能。但是,仍然可以通过其他方式来实现去除视频文件中声音的功能。 一种方法是使用Java提供的ProcessBuilder类来执行命令行操作。可以使用该类执行FFmpeg的命令行命令,通过命令行参数来实现去除视频文件中声音的功能。比如可以调用FFmpeg的命令行工具,使用“-an”参数来指定不提取音频流。这样执行命令后,会生成一个没有声音的新视频文件。 另一种方法是使用第三方Java库来处理视频文件。虽然Java本身没有支持直接处理视频文件的功能,但是有一些第三方Java库可以实现视频处理的功能,并可以实现去除声音的操作。例如,可以使用Xuggler库或者JavaCV库来处理视频文件。这些库提供了对FFmpeg的封装,可以在Java中调用FFmpeg的功能,包括去除视频文件中的声音。 无论使用哪种方法,都需要先确保系统中已经安装了FFmpeg,并正确设置了环境变量。然后,在Java代码中调用相应的命令行或者第三方库的函数,传入视频文件路径和相应的参数,即可实现去除视频文件中声音的功能。 需要注意的是,由于FFmpeg是一个强大的多媒体处理工具,其命令行参数众多,使用起来可能需要一定的学习和理解成本。同时,对于大文件或者复杂的视频文件,去除声音可能会消耗较长的时间和系统资源。因此,在实际应用中,需要根据具体情况选择最合适的方法来去除视频文件中的声音。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值