根据帖子:http://blog.csdn.net/z313731418/article/details/50218341 的提示,在linux安装ffmpeg,确实在linux下使用命令可以将amr转成mp3,并且可以进行播放,不过使用编译的jave-1.0.2.jar进行转化的时候,目录下生成了mp3文件并没有变大反而变小(windows下转码会变大,不过代码会报错,不过转化的mp3是可以播放的),发现mp3不能正常播放。项目代码抛出异常如下:
经过项目组的老大的指引:
使用反编译软件查看了该jar的源代码,查找 “Stream mapping:(linux下出现的)” 和 “Duration: N/A, bitrate: N/A(windows下出现)”对应的源代码如下:
原因分析:
可以确定的一点最后都是拼接成命令:/tmp/jave-1/ffmpeg -i 源文件路径 -f mp3 -y 输出路径 让amr变成mp3
都抛出异常,不过windows下的文件确实转化成功,并且可以播放。根据转化之后的mp3文件的大小判断,可能是异常处理导致写入文件操作被迫中断了。
综合这些分析之后,决定对源代码的异常处理进行修改,重新修改jar包再进行打包。
解决方案:
将 public void encode(File source, File target, EncodingAttributes attributes, EncoderProgressListener listener){}这个方法里面的try的处理读取的异常处理代码进行重写
- public void encode(File source, File target, EncodingAttributes attributes, EncoderProgressListener listener) throws IllegalArgumentException,
- InputFormatException,
- EncoderException {
- String formatAttribute = attributes.getFormat();
- Float offsetAttribute = attributes.getOffset();
- Float durationAttribute = attributes.getDuration();
- AudioAttributes audioAttributes = attributes.getAudioAttributes();
- VideoAttributes videoAttributes = attributes.getVideoAttributes();
- if ((audioAttributes == null) && (videoAttributes == null)) {
- throw new IllegalArgumentException("Both audio and video attributes are null");
- }
- target = target.getAbsoluteFile();
- target.getParentFile().mkdirs();
- FFMPEGExecutor ffmpeg = this.locator.createExecutor();
- if (offsetAttribute != null) {
- ffmpeg.addArgument("-ss");
- ffmpeg.addArgument(String.valueOf(offsetAttribute.floatValue()));
- }
- ffmpeg.addArgument("-i");
- ffmpeg.addArgument(source.getAbsolutePath());
- if (durationAttribute != null) {
- ffmpeg.addArgument("-t");
- ffmpeg.addArgument(String.valueOf(durationAttribute.floatValue()));
- }
- if (videoAttributes == null) {
- ffmpeg.addArgument("-vn");
- } else {
- String codec = videoAttributes.getCodec();
- if (codec != null) {
- ffmpeg.addArgument("-vcodec");
- ffmpeg.addArgument(codec);
- }
- String tag = videoAttributes.getTag();
- if (tag != null) {
- ffmpeg.addArgument("-vtag");
- ffmpeg.addArgument(tag);
- }
- Integer bitRate = videoAttributes.getBitRate();
- if (bitRate != null) {
- ffmpeg.addArgument("-b");
- ffmpeg.addArgument(String.valueOf(bitRate.intValue()));
- }
- Integer frameRate = videoAttributes.getFrameRate();
- if (frameRate != null) {
- ffmpeg.addArgument("-r");
- ffmpeg.addArgument(String.valueOf(frameRate.intValue()));
- }
- VideoSize size = videoAttributes.getSize();
- if (size != null) {
- ffmpeg.addArgument("-s");
- ffmpeg.addArgument(String.valueOf(size.getWidth()) + "x" + String.valueOf(size.getHeight()));
- }
- }
- if (audioAttributes == null) {
- ffmpeg.addArgument("-an");
- } else {
- String codec = audioAttributes.getCodec();
- if (codec != null) {
- ffmpeg.addArgument("-acodec");
- ffmpeg.addArgument(codec);
- }
- Integer bitRate = audioAttributes.getBitRate();
- if (bitRate != null) {
- ffmpeg.addArgument("-ab");
- ffmpeg.addArgument(String.valueOf(bitRate.intValue()));
- }
- Integer channels = audioAttributes.getChannels();
- if (channels != null) {
- ffmpeg.addArgument("-ac");
- ffmpeg.addArgument(String.valueOf(channels.intValue()));
- }
- Integer samplingRate = audioAttributes.getSamplingRate();
- if (samplingRate != null) {
- ffmpeg.addArgument("-ar");
- ffmpeg.addArgument(String.valueOf(samplingRate.intValue()));
- }
- Integer volume = audioAttributes.getVolume();
- if (volume != null) {
- ffmpeg.addArgument("-vol");
- ffmpeg.addArgument(String.valueOf(volume.intValue()));
- }
- }
- ffmpeg.addArgument("-f");
- ffmpeg.addArgument(formatAttribute);
- ffmpeg.addArgument("-y");
- ffmpeg.addArgument(target.getAbsolutePath());
- try {
- ffmpeg.execute();
- } catch(IOException e) {
- throw new EncoderException(e);
- }
- try {
- String lastWarning = null;
- long progress = 0L;
- RBufferedReader reader = null;
- reader = new RBufferedReader(new InputStreamReader(ffmpeg.getErrorStream()));
- MultimediaInfo info = parseMultimediaInfo(source, reader);
- long duration;
- long duration;
- if (durationAttribute != null) {
- duration = Math.round(durationAttribute.floatValue() * 1000.0F);
- } else {
- duration = info.getDuration();
- if (offsetAttribute != null) {
- duration = duration - Math.round(offsetAttribute.floatValue() * 1000.0F);
- }
- }
- if (listener != null) {
- listener.sourceInfo(info);
- }
- int step = 0;
- String line;
- while ((line = reader.readLine()) != null) {
- String line;
- if (step == 0) {
- if (line.startsWith("WARNING: ")) {
- if (listener != null) listener.message(line);
- } else {
- if (!line.startsWith("Output #0")) {
- throw new EncoderException(line);
- }
- step++;
- }
- } else if ((step == 1) && (!line.startsWith(" "))) {
- step++;
- }
- if (step == 2) {
- if (!line.startsWith("Stream mapping:")) {
- throw new EncoderException(line);
- }
- step++;
- } else if ((step == 3) && (!line.startsWith(" "))) {
- step++;
- }
- if (step == 4) {
- line = line.trim();
- if (line.length() > 0) {
- Hashtable table = parseProgressInfoLine(line);
- if (table == null) {
- if (listener != null) {
- listener.message(line);
- }
- lastWarning = line;
- } else {
- if (listener != null) {
- String time = (String) table.get("time");
- if (time != null) {
- int dot = time.indexOf('.');
- if ((dot > 0) && (dot == time.length() - 2) && (duration > 0L)) {
- String p1 = time.substring(0, dot);
- String p2 = time.substring(dot + 1);
- try {
- long i1 = Long.parseLong(p1);
- long i2 = Long.parseLong(p2);
- progress = i1 * 1000L + i2 * 100L;
- int perm = (int) Math.round(progress * 1000L / duration);
- if (perm > 1000) {
- perm = 1000;
- }
- listener.progress(perm);
- } catch(NumberFormatException localNumberFormatException) {}
- }
- }
- }
- lastWarning = null;
- }
- }
- }
- }
- if ((lastWarning == null) || (SUCCESS_PATTERN.matcher(lastWarning).matches())) break label1089;
- throw new EncoderException(lastWarning);
- } catch(IOException e) {
- throw new EncoderException(e);
- } finally {
- jsr 6;
- }
- localObject1 = returnAddress;
- ffmpeg.destroy();
- ret;
- label1089: jsr - 9;
- }
- }
上述中的异常处理部分代码进行封装,保证不修改源代码。增加如下方法:
- protected void processErrorOutput(EncodingAttributes attributes, BufferedReader errorReader, File source, EncoderProgressListener listener) throws EncoderException, IOException {
- String lastWarning = null;
- long progress = 0L;
- Float offsetAttribute = attributes.getOffset();
- MultimediaInfo info = parseMultimediaInfo(source, (RBufferedReader)errorReader);
- Float durationAttribute = attributes.getDuration();
- long duration;
- long duration;
- if (durationAttribute != null) {
- duration = Math.round(durationAttribute.floatValue() * 1000.0F);
- }
- else {
- duration = info.getDuration();
- if (offsetAttribute != null) {
- duration -= Math.round(offsetAttribute.floatValue() * 1000.0F);
- }
- }
- if (listener != null) {
- listener.sourceInfo(info);
- }
- int step = 0;
- String line;
- while ((line = errorReader.readLine()) != null) {
- if (step == 0) {
- if (line.startsWith("WARNING: ")) {
- if (listener != null)
- listener.message(line);
- } else {
- if (!line.startsWith("Output #0")) {
- throw new EncoderException(line);
- }
- step++;
- }
- } else if ((step == 1) &&
- (!line.startsWith(" "))) {
- step++;
- }
- if (step == 2) {
- if (!line.startsWith("Stream mapping:")) {
- throw new EncoderException(line);
- }
- step++;
- }
- else if ((step == 3) &&
- (!line.startsWith(" "))) {
- step++;
- }
- if (step == 4) {
- line = line.trim();
- if (line.length() > 0) {
- Hashtable table = parseProgressInfoLine(line);
- if (table == null) {
- if (listener != null) {
- listener.message(line);
- }
- lastWarning = line;
- } else {
- if (listener != null) {
- String time = (String)table.get("time");
- if (time != null) {
- int dot = time.indexOf(46);
- if ((dot > 0) && (dot == time.length() - 2) && (duration > 0L))
- {
- String p1 = time.substring(0, dot);
- String p2 = time.substring(dot + 1);
- try {
- long i1 = Long.parseLong(p1);
- long i2 = Long.parseLong(p2);
- progress = i1 * 1000L + i2 * 100L;
- int perm = (int)Math.round(progress * 1000L / duration);
- if (perm > 1000) {
- perm = 1000;
- }
- listener.progress(perm);
- }
- catch (NumberFormatException e) {
- }
- }
- }
- }
- lastWarning = null;
- }
- }
- }
- }
- if ((lastWarning != null) &&
- (!SUCCESS_PATTERN.matcher(lastWarning).matches()))
- throw new EncoderException(lastWarning);
- }
- }
将encode方法的中相同的代码修改成调用processErrorOutput(attributes, reader, source, listener); 修改之后的源代码:
- public void encode(File source, File target, EncodingAttributes attributes, EncoderProgressListener listener) throws IllegalArgumentException,
- InputFormatException,
- EncoderException {
- FFMPEGExecutor ffmpeg = this.locator.createExecutor();
- setAttributes(attributes, ffmpeg, source, target);
- try {
- ffmpeg.execute();
- } catch(IOException e) {
- throw new EncoderException(e);
- }
- try {
- RBufferedReader reader = new RBufferedReader(new InputStreamReader(ffmpeg.getErrorStream()));
- processErrorOutput(attributes, reader, source, listener);
- } catch(IOException e) {
- throw new EncoderException(e);
- } finally {
- ffmpeg.destroy();
- }
- }
实际上jar包并没有修改啥,只是把异常处理的代码进行抽离成一个方法processErrorOutput而已。
最终实现代码:
- import java.io.BufferedReader;
- import java.io.File;
- import java.io.IOException;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import it.sauronsoftware.jave. * ;
- /**
- * 音频工具类
- */
- public class AudioUtil {
- private static Logger logger = LoggerFactory.getLogger(AudioUtil.class);
- /**
- * Amr格式音频转为Mp3格式
- *
- * @param sourcePath
- * amr格式源路径
- *
- * @param targetPath
- * mp3格式输出路径
- *
- * @example getAmrConversionMp3("D:\\test\\04296548.amr","D:\\test\\04296548.mp3");
- *
- */
- public static void getAmrConversionMp3(String sourcePath, String targetPath) {
- File source = new File(sourcePath);
- File target = new File(targetPath);
- AudioAttributes audio = new AudioAttributes();
- AmrToMp3Encoder encoder = new AmrToMp3Encoder();
- audio.setCodec("libmp3lame");
- EncodingAttributes attrs = new EncodingAttributes();
- attrs.setFormat("mp3");
- attrs.setAudioAttributes(audio);
- try {
- encoder.encode(source, target, attrs);
- } catch(IllegalArgumentException e) {
- e.printStackTrace();
- } catch(InputFormatException e) {
- e.printStackTrace();
- } catch(EncoderException e) {
- e.printStackTrace();
- }
- }
- /**
- * 判断文件是不是amr格式
- *
- * @param fileName 文件名
- * */
- public static boolean isAudioAmr(String fileName) {
- String tmpName = fileName.toLowerCase();
- return tmpName.endsWith(".amr");
- }
- private static class AmrToMp3Encoder extends Encoder {
- protected void processErrorOutput(EncodingAttributes attributes, BufferedReader errorReader, File source, EncoderProgressListener listener) throws EncoderException,
- IOException {
- // 屏蔽默认的错误处理
- try {
- String line;
- while ((line = errorReader.readLine()) != null) {
- logger.debug(line);
- }
- } catch(Exception exp) {
- logger.error("file convert error message process failed. ", exp);
- }
- }
- }
- }
结论:
编写AmrToMp3Encoder类继承Encoder,并重写方法processErrorOutput,将默认的方法里面的异常方法全部屏蔽,通过单元测试发现,在linux下和windows下都不会抛出异常,
而且转化的mp3格式均可以播放。可能真的是这个jar包还存在着bug。该结果是在客观事实中进行求证,如有不对之处,请留下评论,大家一起探讨一下,而且ffmpeg这个文件需要进行替换处理,使用你所在linux环境的ffmpeg。修改jar包的源代码已经贴上了。修改的jar包如果有需要coders可以留下自己的邮箱。
该帖子属于原创帖子:转载请贴原帖子的地址,谢谢!
来源: http://www.cnblogs.com/fennudexiaofan/p/7577671.html