java 通过ffmpeg 访问网络图片
时间:2021-08-17
本文章向大家介绍java 通过ffmpeg 访问网络图片,主要包括java 通过ffmpeg 访问网络图片使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
参考:https://www.cnblogs.com/chenbinaiqiuyu/p/12736814.html
你可能用到的原因!!!
1 我使用存储oss,存储图片/视频。
而oss没有提供图片/视频的详细信息,比如视频时长等等!
2 你只是想访问网络图片并解析,而不想下载。
3 有诸如这种需求
下面直接说方法。
一,首先pom导入架包
1 jave-core 必须引入
2 下面的只需要引入一个对应系统的就可以了。
<!-- jave 核心依赖 --> <dependency> <groupId>ws.schild</groupId> <artifactId>jave-core</artifactId> <version>2.4.6</version> </dependency> <!-- 根据不同操作系统引入不同FFmpeg包 --> <!-- window32位 FFmpeg --> <dependency> <groupId>ws.schild</groupId> <artifactId>jave-native-win32</artifactId> <version>2.4.6</version> </dependency> <!-- window64位 FFmpeg --> <dependency> <groupId>ws.schild</groupId> <artifactId>jave-native-win64</artifactId> <version>2.4.6</version> </dependency> <!-- linux64位 FFmpeg --> <dependency> <groupId>ws.schild</groupId> <artifactId>jave-native-linux64</artifactId> <version>2.4.6</version> </dependency> <!-- macos64位 FFmpeg --> <dependency> <groupId>ws.schild</groupId> <artifactId>jave-native-osx64</artifactId> <version>2.4.6</version> </dependency>
二,创建文件
看一下包名和位置!重要!不要修改!
三,FFmpegFileInfo 代码
主要拷贝 MultimediaInfo 并修改getInfo方法
package ws.schild.jave; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.util.StringTokenizer; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @description : * @auther Tyler * @date 2021/8/17 */ public class FFmpegFileInfo { private final static Log LOG = LogFactory.getLog(MultimediaObject.class); /** * This regexp is used to parse the ffmpeg output about the size of a video * stream. */ private static final Pattern SIZE_PATTERN = Pattern.compile( "(\\d+)x(\\d+)", Pattern.CASE_INSENSITIVE); /** * This regexp is used to parse the ffmpeg output about the frame rate value * of a video stream. */ private static final Pattern FRAME_RATE_PATTERN = Pattern.compile( "([\\d.]+)\\s+(?:fps|tbr)", Pattern.CASE_INSENSITIVE); /** * This regexp is used to parse the ffmpeg output about the bit rate value * of a stream. */ private static final Pattern BIT_RATE_PATTERN = Pattern.compile( "(\\d+)\\s+kb/s", Pattern.CASE_INSENSITIVE); /** * This regexp is used to parse the ffmpeg output about the sampling rate of * an audio stream. */ private static final Pattern SAMPLING_RATE_PATTERN = Pattern.compile( "(\\d+)\\s+Hz", Pattern.CASE_INSENSITIVE); /** * This regexp is used to parse the ffmpeg output about the channels number * of an audio stream. */ private static final Pattern CHANNELS_PATTERN = Pattern.compile( "(mono|stereo|quad)", Pattern.CASE_INSENSITIVE); /** * The locator of the ffmpeg executable used by this extractor. */ private final FFMPEGLocator locator; private File inputFile; /** * It builds an extractor using a {@link DefaultFFMPEGLocator} instance to * locate the ffmpeg executable to use. * * @param input Input file for creating MultimediaObject */ public FFmpegFileInfo(File input) { this.locator = new DefaultFFMPEGLocator(); this.inputFile = input; } public File getFile() { return this.inputFile; } public void setFile(File file) { this.inputFile = file; } /** * It builds an extractor with a custom {@link FFMPEGLocator}. * * @param input Input file for creating MultimediaObject * @param locator The locator picking up the ffmpeg executable used by the * extractor. */ public FFmpegFileInfo(File input, FFMPEGLocator locator) { this.locator = locator; this.inputFile = input; } /** * Returns a set informations about a multimedia file, if its format is * supported for decoding. * * @return A set of informations about the file and its contents. * @throws InputFormatException If the format of the source file cannot be * recognized and decoded. * @throws EncoderException If a problem occurs calling the underlying * ffmpeg executable. */ public MultimediaInfo getInfo(String url) throws InputFormatException, EncoderException { FFMPEGExecutor ffmpeg = locator.createExecutor(); ffmpeg.addArgument("-i"); ffmpeg.addArgument(url); try { ffmpeg.execute(); } catch (IOException e) { throw new EncoderException(e); } try { RBufferedReader reader = new RBufferedReader(new InputStreamReader(ffmpeg .getErrorStream())); return parseMultimediaInfo(inputFile, reader); } finally { ffmpeg.destroy(); } } /** * Private utility. It parses the ffmpeg output, extracting informations * about a source multimedia file. * * @param source The source multimedia file. * @param reader The ffmpeg output channel. * @return A set of informations about the source multimedia file and its * contents. * @throws InputFormatException If the format of the source file cannot be * recognized and decoded. * @throws EncoderException If a problem occurs calling the underlying * ffmpeg executable. */ private MultimediaInfo parseMultimediaInfo(File source, RBufferedReader reader) throws InputFormatException, EncoderException { Pattern p1 = Pattern.compile("^\\s*Input #0, (\\w+).+$\\s*", Pattern.CASE_INSENSITIVE); Pattern p2 = Pattern.compile( "^\\s*Duration: (\\d\\d):(\\d\\d):(\\d\\d)\\.(\\d\\d).*$", Pattern.CASE_INSENSITIVE); Pattern p3 = Pattern.compile( "^\\s*Stream #\\S+: ((?:Audio)|(?:Video)|(?:Data)): (.*)\\s*$", Pattern.CASE_INSENSITIVE); Pattern p4 = Pattern.compile( "^\\s*Metadata:", Pattern.CASE_INSENSITIVE); MultimediaInfo info = null; try { int step = 0; while (true) { String line = reader.readLine(); LOG.debug("Output line: " + line); if (line == null) { break; } switch (step) { case 0: { String token = source.getAbsolutePath() + ": "; if (line.startsWith(token)) { String message = line.substring(token.length()); throw new InputFormatException(message); } Matcher m = p1.matcher(line); if (m.matches()) { String format = m.group(1); info = new MultimediaInfo(); info.setFormat(format); step++; } break; } case 1: { Matcher m = p2.matcher(line); if (m.matches()) { long hours = Integer.parseInt(m.group(1)); long minutes = Integer.parseInt(m.group(2)); long seconds = Integer.parseInt(m.group(3)); long dec = Integer.parseInt(m.group(4)); long duration = (dec * 10L) + (seconds * 1000L) + (minutes * 60L * 1000L) + (hours * 60L * 60L * 1000L); info.setDuration(duration); step++; } else { // step = 3; } break; } case 2: { Matcher m = p3.matcher(line); Matcher m4 = p4.matcher(line); if (m.matches()) { String type = m.group(1); String specs = m.group(2); if ("Video".equalsIgnoreCase(type)) { VideoInfo video = new VideoInfo(); StringTokenizer st = new StringTokenizer(specs, ","); for (int i = 0; st.hasMoreTokens(); i++) { String token = st.nextToken().trim(); if (i == 0) { video.setDecoder(token); } else { boolean parsed = false; // Video size. Matcher m2 = SIZE_PATTERN.matcher(token); if (!parsed && m2.find()) { int width = Integer.parseInt(m2 .group(1)); int height = Integer.parseInt(m2 .group(2)); video.setSize(new VideoSize(width, height)); parsed = true; } // Frame rate. m2 = FRAME_RATE_PATTERN.matcher(token); if (!parsed && m2.find()) { try { float frameRate = Float .parseFloat(m2.group(1)); video.setFrameRate(frameRate); } catch (NumberFormatException e) { LOG.info("Invalid frame rate value: " + m2.group(1), e); } parsed = true; } // Bit rate. m2 = BIT_RATE_PATTERN.matcher(token); if (!parsed && m2.find()) { int bitRate = Integer.parseInt(m2 .group(1)); video.setBitRate(bitRate*1000); parsed = true; } } } info.setVideo(video); } else if ("Audio".equalsIgnoreCase(type)) { AudioInfo audio = new AudioInfo(); StringTokenizer st = new StringTokenizer(specs, ","); for (int i = 0; st.hasMoreTokens(); i++) { String token = st.nextToken().trim(); if (i == 0) { audio.setDecoder(token); } else { boolean parsed = false; // Sampling rate. Matcher m2 = SAMPLING_RATE_PATTERN .matcher(token); if (!parsed && m2.find()) { int samplingRate = Integer.parseInt(m2 .group(1)); audio.setSamplingRate(samplingRate); parsed = true; } // Channels. m2 = CHANNELS_PATTERN.matcher(token); if (!parsed && m2.find()) { String ms = m2.group(1); if ("mono".equalsIgnoreCase(ms)) { audio.setChannels(1); } else if ("stereo" .equalsIgnoreCase(ms)) { audio.setChannels(2); } else if ("quad" .equalsIgnoreCase(ms)) { audio.setChannels(4); } parsed = true; } // Bit rate. m2 = BIT_RATE_PATTERN.matcher(token); if (!parsed && m2.find()) { int bitRate = Integer.parseInt(m2 .group(1)); audio.setBitRate(bitRate*1000); parsed = true; } } } info.setAudio(audio); } } else // if (m4.matches()) { // Stay on level 2 } /* else { step = 3; } */ break; } default: break; } if (line.startsWith("frame=")) { reader.reinsertLine(line); break; } } } catch (IOException e) { throw new EncoderException(e); } if (info == null) { throw new InputFormatException(); } return info; } }
四,测试
测试代码:
String url="https://10years-qa.oss-cn-hangzhou.aliyuncs.com/234.mp4"; File mediaFile = new File(url); FFmpegFileInfo ffmpegFileInfo = new FFmpegFileInfo(mediaFile); MultimediaInfo info = null; info = ffmpegFileInfo.getInfo(url); long duration = info.getDuration();
效果:
原文地址:https://www.cnblogs.com/hanjun0612/p/15152292.html
- python 序列化数据:pickle与json ,dumps与loads
- golang继承,和多态
- python 利用random生成验证码与MD5码加密过程
- Java内部类的继承
- Java继承类中static成员函数的重写
- Search for a range寻找上下界-Leetcode
- Basic Calculator 基本计算器-Leetcode
- python yield函数深入浅出理解
- 十分钟搞定 Tensorflow 服务
- datapump跨平台升级迁移的总结 (r8笔记第77天)
- Java中isAssignableFrom()方法与instanceof()方法用法
- 与Ajax同样重要的jQuery(1)
- Java中Class类详解、用法及泛化
- python 函数编程的位置参数、默认参数、关键字参数以及函数的递归
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- PHP中常见的密码处理方式和建议总结
- php+Ajax处理xml与json格式数据的方法示例
- python3 循环读取excel文件并写入json操作
- PHP根据key删除数组中指定的元素
- PHP JWT初识及其简单示例
- PHP正则判断一个变量是否为正整数的方法
- php5.5使用PHPMailer-5.2发送邮件的完整步骤
- 详细对比php中类继承和接口继承
- 解决Keras的自定义lambda层去reshape张量时model保存出错问题
- 解决Keras中Embedding层masking与Concatenate层不可调和的问题
- 浅谈keras使用预训练模型vgg16分类,损失和准确度不变
- 关于tf.matmul() 和tf.multiply() 的区别说明
- python中执行smtplib失败的处理方法
- PHP+Ajax简单get验证操作示例
- Python matplotlib读取excel数据并用for循环画多个子图subplot操作