由于项目需求,需要从上传的音视频文件中获取到对应的时长展示,苦苦找寻,终于完成了需求,固记录下此以供日后学习巩固。(参考网址放在最后)
第一步,在pom.xml中加入ws.schild的相关依赖
<dependency>
<groupId>ws.schild</groupId>
<artifactId>jave-all-deps</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>ws.schild</groupId>
<artifactId>jave-core</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>ws.schild</groupId>
<artifactId>jave-nativebin-win64</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>ws.schild</groupId>
<artifactId>jave-nativebin-linux64</artifactId>
<version>2.5.1</version>
</dependency>
第二步,在main.java下创建包ws.schild.jave,创建此包的目的是为了与jave的jar包同路径,从而可以使用相关的方法。
第三步,由于jave中的MultimediaObject类不符合目前关于url的需求,所以在java下新建一个类FfmpegFileInfo,复制jave中的MultimediaObject类中的内容到FfmpegFileInfo然后进行改造。
需要改造的有以下几个地方:
1)有些没用到,但还是有点小强迫,所以一并改了
public FfmpegFileInfo(File input) {
this.locator = new DefaultFFMPEGLocator();
this.inputFile = input;
}
public FfmpegFileInfo(URL input) {
this.locator = new DefaultFFMPEGLocator();
this.inputURL = input;
}
public FfmpegFileInfo(File input, FFMPEGLocator locator) {
this.locator = locator;
this.inputFile = input;
}
2)修改getInfo类,主要是改为传入url的方式,删除掉其他无用的代码
public MultimediaInfo getInfo(String url) throws InputFormatException, EncoderException {
FFMPEGExecutor ffmpeg = this.locator.createExecutor();
ffmpeg.addArgument("-i");
ffmpeg.addArgument(url);
try {
ffmpeg.execute();
} catch (IOException var7) {
throw new EncoderException(var7);
}
MultimediaInfo var3;
try {
RBufferedReader reader = new RBufferedReader(new InputStreamReader(ffmpeg.getErrorStream()));
var3 = this.parseMultimediaInfo(this.inputFile, reader);
} finally {
ffmpeg.destroy();
}
return var3;
}
3)注释掉会引起报错的代码行
// Matcher m;
// String token;
第四步,根据自己的需求调用,其中的fileUrl是去掉了问号后的地址,后面还用了一个方法将秒数转换成分钟:秒的格式输出。(附带一个时:分:秒的方法)可根据自己需要使用。
public String getAudioDuration(AudioFile audioFile) {
String duration = "";
if(!ObjectUtils.isEmpty(audioFile.getFileUrl())){
try {
String fileUrl = audioFile.getFileUrl().split("\\?")[0];
File mediaFile = new File(fileUrl);
FfmpegFileInfo ffmpegFileInfo = new FfmpegFileInfo(mediaFile);
MultimediaInfo multimediaInfo = null;
multimediaInfo = ffmpegFileInfo.getInfo(fileUrl);
Long sec = multimediaInfo.getDuration() / 1000;
duration = getMinSecTime(sec);
audioFile.setDuration(duration);
audioFileMapper.updateById(audioFile);
} catch (EncoderException e) {
e.printStackTrace();
}
return duration;
}else {
return null;
}
}
附上修改后的FfmpegFileInfo类
public class FfmpegFileInfo {
private static final Log LOG = LogFactory.getLog(MultimediaObject.class);
private static final Pattern SIZE_PATTERN = Pattern.compile("(\\d+)x(\\d+)", 2);
private static final Pattern FRAME_RATE_PATTERN = Pattern.compile("([\\d.]+)\\s+(?:fps|tbr)", 2);
private static final Pattern BIT_RATE_PATTERN = Pattern.compile("(\\d+)\\s+kb/s", 2);
private static final Pattern SAMPLING_RATE_PATTERN = Pattern.compile("(\\d+)\\s+Hz", 2);
private static final Pattern CHANNELS_PATTERN = Pattern.compile("(mono|stereo|quad)", 2);
private final FFMPEGLocator locator;
private File inputFile;
private URL inputURL;
public FfmpegFileInfo(File input) {
this.locator = new DefaultFFMPEGLocator();
this.inputFile = input;
}
public FfmpegFileInfo(URL input) {
this.locator = new DefaultFFMPEGLocator();
this.inputURL = input;
}
public File getFile() {
return this.inputFile;
}
public URL getURL() {
return this.inputURL;
}
public void setFile(File file) {
this.inputFile = file;
}
public void setUR(URL input) {
this.inputURL = input;
}
public boolean isURL() {
return this.inputURL != null;
}
public FfmpegFileInfo(File input, FFMPEGLocator locator) {
this.locator = locator;
this.inputFile = input;
}
public MultimediaInfo getInfo(String url) throws InputFormatException, EncoderException {
FFMPEGExecutor ffmpeg = this.locator.createExecutor();
ffmpeg.addArgument("-i");
ffmpeg.addArgument(url);
try {
ffmpeg.execute();
} catch (IOException var7) {
throw new EncoderException(var7);
}
MultimediaInfo var3;
try {
RBufferedReader reader = new RBufferedReader(new InputStreamReader(ffmpeg.getErrorStream()));
var3 = this.parseMultimediaInfo(this.inputFile, reader);
} finally {
ffmpeg.destroy();
}
return var3;
}
private MultimediaInfo parseMultimediaInfo(File source, RBufferedReader reader) throws InputFormatException, EncoderException {
Pattern p1 = Pattern.compile("^\\s*Input #0, (\\w+).+$\\s*", 2);
Pattern p2 = Pattern.compile("^\\s*Duration: (\\d\\d):(\\d\\d):(\\d\\d)\\.(\\d\\d).*$", 2);
Pattern p3 = Pattern.compile("^\\s*Stream #\\S+: ((?:Audio)|(?:Video)|(?:Data)): (.*)\\s*$", 2);
Pattern p4 = Pattern.compile("^\\s*Metadata:", 2);
MultimediaInfo info = null;
try {
int step = 0;
while(true) {
String line = reader.readLine();
LOG.debug("Output line: " + line);
if (line == null) {
break;
}
// Matcher m;
String type;
switch(step) {
case 0:
String token = source + ": ";
if (line.startsWith(token)) {
String message = line.substring(token.length());
throw new InputFormatException(message);
}
Matcher m = p1.matcher(line);
if (m.matches()) {
type = m.group(1);
info = new MultimediaInfo();
info.setFormat(type);
++step;
}
break;
case 1:
m = p2.matcher(line);
if (m.matches()) {
long hours = (long)Integer.parseInt(m.group(1));
long minutes = (long)Integer.parseInt(m.group(2));
long seconds = (long)Integer.parseInt(m.group(3));
long dec = (long)Integer.parseInt(m.group(4));
long duration = dec * 10L + seconds * 1000L + minutes * 60L * 1000L + hours * 60L * 60L * 1000L;
info.setDuration(duration);
++step;
}
break;
case 2:
m = p3.matcher(line);
p4.matcher(line);
if (m.matches()) {
type = m.group(1);
String specs = m.group(2);
StringTokenizer st;
int i;
// String token;
boolean parsed;
Matcher m2;
int bitRate;
if ("Video".equalsIgnoreCase(type)) {
VideoInfo video = new VideoInfo();
st = new StringTokenizer(specs, ",");
for(i = 0; st.hasMoreTokens(); ++i) {
token = st.nextToken().trim();
if (i == 0) {
video.setDecoder(token);
} else {
parsed = false;
m2 = SIZE_PATTERN.matcher(token);
if (!parsed && m2.find()) {
bitRate = Integer.parseInt(m2.group(1));
int height = Integer.parseInt(m2.group(2));
video.setSize(new VideoSize(bitRate, height));
parsed = true;
}
m2 = FRAME_RATE_PATTERN.matcher(token);
if (!parsed && m2.find()) {
try {
float frameRate = Float.parseFloat(m2.group(1));
video.setFrameRate(frameRate);
} catch (NumberFormatException var22) {
LOG.info("Invalid frame rate value: " + m2.group(1), var22);
}
parsed = true;
}
m2 = BIT_RATE_PATTERN.matcher(token);
if (!parsed && m2.find()) {
bitRate = Integer.parseInt(m2.group(1));
video.setBitRate(bitRate * 1000);
parsed = true;
}
}
}
info.setVideo(video);
} else if ("Audio".equalsIgnoreCase(type)) {
AudioInfo audio = new AudioInfo();
st = new StringTokenizer(specs, ",");
for(i = 0; st.hasMoreTokens(); ++i) {
token = st.nextToken().trim();
if (i == 0) {
audio.setDecoder(token);
} else {
parsed = false;
m2 = SAMPLING_RATE_PATTERN.matcher(token);
if (!parsed && m2.find()) {
bitRate = Integer.parseInt(m2.group(1));
audio.setSamplingRate(bitRate);
parsed = true;
}
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;
}
m2 = BIT_RATE_PATTERN.matcher(token);
if (!parsed && m2.find()) {
bitRate = Integer.parseInt(m2.group(1));
audio.setBitRate(bitRate * 1000);
parsed = true;
}
}
}
info.setAudio(audio);
}
}
}
if (line.startsWith("frame=")) {
reader.reinsertLine(line);
break;
}
}
} catch (IOException var23) {
throw new EncoderException(var23);
}
if (info == null) {
throw new InputFormatException();
} else {
return info;
}
}
}
1)分:秒格式方法
/**
* 根据秒数转换成分钟加秒模式(00:00)
*
* @param time 秒数
*
* @return 分:秒格式时间
*/
private String getMinSecTime(Long time){
String mSec = "";
String mMin = "";
//秒数
Long sec = time % 60;
//分钟数
Long min = (time - sec) / 60;
//如果秒数没超过10就在它前面加个0
if(sec < 10){
mSec = "0" + sec;
}else {
mSec = String.valueOf(sec);
}
//如果分钟数没超过10就在它前面加个0
if(min < 10){
mMin = "0" + min;
}else {
mMin = String.valueOf(min);
}
String result = mMin + ":" + mSec;
return result;
}
2)时:分:秒格式方法
/**
* 根据秒数转换成小时:分钟:秒模式(00:00:00)
*
* @param time 秒数
*
* @return 小时:分:秒格式时间
*/
private String getHourMinSecTime(Long time){
Long h = time / 3600;
Long m = (time % 3600) / 60;
Long s = time % 60;
String result = "";
if(h > 0){
result = (h < 10 ? ("0" + h) : h) + ":";
}
result += (m < 10 ? ("0" + m) : m) + ":";
result += (s < 10 ? ("0" + s) : s);
return result;
}