MAC OS下使用JAVE将amr转mp3的坑


由于项目需求,需要将android手机上的录音文件上传到后台,可是在android上的录音都是amr格式的,在mac上无法播放。直接android上转码又不太好实现。于是这个工作交给后端来实现。


JAVE是基于ffmpeg的很强大的转码工具。下载地址 http://www.sauronsoftware.it/projects/jave/download.php

下载了最新的1.0.2版本,加载到工程中。调用方法:

    private boolean convertAmr2MP3(File src, File target) {
        AudioAttributes audio = new AudioAttributes();
        audio.setCodec("libmp3lame");
        Encoder encoder = new Encoder();
        EncodingAttributes attrs = new EncodingAttributes();
        attrs.setFormat("mp3");
        attrs.setAudioAttributes(audio);
        try {
            encoder.encode(src, target, attrs);
            return true;
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InputFormatException e) {
            e.printStackTrace();
        } catch (EncoderException e) {
            e.printStackTrace();
        }
        return false;
    }

发现报错:

it.sauronsoftware.jave.InputFormatException
	at it.sauronsoftware.jave.Encoder.parseMultimediaInfo(Encoder.java:659)
	at it.sauronsoftware.jave.Encoder.encode(Encoder.java:840)
	at it.sauronsoftware.jave.Encoder.encode(Encoder.java:713)
	at com.music.read.MusicFileParser.convertAmr2MP3(MusicFileParser.java:256)
	at com.music.read.MusicFileParser.loadFile(MusicFileParser.java:75)
	at com.music.read.MusicFileParser.access$000(MusicFileParser.java:24)
	at com.music.read.MusicFileParser$1.run(MusicFileParser.java:43)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

继续到官网找原因:

Using an alternative ffmpeg executable
JAVE is not pure Java: it acts as a wrapper around an ffmpeg (http://ffmpeg.mplayerhq.hu/) executable. ffmpeg is an open source and free software project entirely written in C, so its executables cannot be easily ported from a machine to another. You need a pre-compiled version of ffmpeg in order to run JAVE on your target machine. The JAVE distribution includes two pre-compiled executables of ffmpeg: a Windows one and a Linux one, both compiled for i386/32 bit hardware achitectures. This should be enough in most cases. If it is not enough for your specific situation, you can still run JAVE, but you need to obtain a platform specific ffmpeg executable. Check the Internet for it. You can even build it by yourself getting the code (and the documentation to build it) on the official ffmpeg site. Once you have obtained a ffmpeg executable suitable for your needs, you have to hook it in the JAVE library. That's a plain operation. JAVE gives you an abstract class called it.sauronsoftware.jave.FFMPEGLocator. Extend it. All you have to do is to define the following method:

public java.lang.String getFFMPEGExecutablePath()
This method should return a file system based path to your custom ffmpeg executable.

Once your class is ready, suppose you have called it MyFFMPEGExecutableLocator, you have to create an alternate encoder that uses it instead of the default locator:

Encoder encoder = new Encoder(new MyFFMPEGExecutableLocator())
You can use the same procedure also to switch to other versions of ffmpeg, even if you are on a platform covered by the executables bundled in the JAVE distribution.

Anyway be careful and test ever your application: JAVE it's not guaranteed to work properly with custom ffmpeg executables different from the bundled ones.

在官方文档上看了这一段,大意就是说要去ffmpeg的官网下载对应版本的ffmpeg。然后需要自己创建一个类去继承FFMPEGLocator,实现抽象方法,将ffmpeg的路径传JAVE

我下载的是这个MAC版

MAC OS下使用JAVE将amr转mp3的坑_第1张图片


使用类加载器,获取ffmpeg的真实路经

public class MyFFMPEGExecute extends FFMPEGLocator {
    protected String getFFMPEGExecutablePath() {

        String path = MyFFMPEGExecute.class.getResource("/res/ffmpeg").getPath();

        return path;
    }
}

调用方法改为:

    private boolean convertAmr2MP3(File src, File target) {
        AudioAttributes audio = new AudioAttributes();
        audio.setCodec("libmp3lame");
        Encoder encoder = new Encoder(new MyFFMPEGExecute());
        EncodingAttributes attrs = new EncodingAttributes();
        attrs.setFormat("mp3");
        attrs.setAudioAttributes(audio);
        try {
            encoder.encode(src, target, attrs);
            return true;
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InputFormatException e) {
            e.printStackTrace();
        } catch (EncoderException e) {
            e.printStackTrace();
        }
        return false;
    }

运行之后仍然报错:

it.sauronsoftware.jave.EncoderException: Stream mapping:
	at it.sauronsoftware.jave.Encoder.encode(Encoder.java:863)
	at it.sauronsoftware.jave.Encoder.encode(Encoder.java:713)
	at com.music.read.MusicFileParser.convertAmr2MP3(MusicFileParser.java:256)
	at com.music.read.MusicFileParser.loadFile(MusicFileParser.java:75)
	at com.music.read.MusicFileParser.access$000(MusicFileParser.java:24)
	at com.music.read.MusicFileParser$1.run(MusicFileParser.java:43)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

这下就尴尬了,都是都是按照要求来实现的啊?怎么就不行呢?

看来还是得,后来找到一个更新版本的jave的jar包。JAVE官网最新的版本发布日期是2009年!所以可能是这个原因


加入新的jar包后重新编译运行,仍然报错。但这此报的异常又变了,感觉有希望

Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 8 more


从异常来看,最新的jave依赖了commons-logging,加上这个:

   
            commons-logging
            commons-logging
            1.2
        


再次编译运行,这次就没有再报错了:

Dec 29 10:44:57  java[2994] : CGAffineTransformInvert: singular matrix.
Dec 29, 2017 10:45:13 AM it.sauronsoftware.jave.Encoder parseMultimediaInfo
WARNING: Output line: ffmpeg version 3.4.1-tessus Copyright (c) 2000-2017 the FFmpeg developers
Dec 29, 2017 10:45:13 AM it.sauronsoftware.jave.Encoder parseMultimediaInfo
WARNING: Output line:   built with Apple LLVM version 8.0.0 (clang-800.0.42.1)
Dec 29, 2017 10:45:13 AM it.sauronsoftware.jave.Encoder parseMultimediaInfo
WARNING: Output line:   configuration: --cc=/usr/bin/clang --prefix=/opt/ffmpeg --extra-version=tessus --enable-avisynth --enable-fontconfig --enable-gpl --enable-libass --enable-libbluray --enable-libfreetype --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopus --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libvidstab --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzmq --enable-libzvbi --enable-version3 --pkg-config-flags=--static --disable-ffplay
Dec 29, 2017 10:45:13 AM it.sauronsoftware.jave.Encoder parseMultimediaInfo
WARNING: Output line:   libavutil      55. 78.100 / 55. 78.100
Dec 29, 2017 10:45:13 AM it.sauronsoftware.jave.Encoder parseMultimediaInfo
WARNING: Output line:   libavcodec     57.107.100 / 57.107.100

看,对应的MP3文件已经生成了。


可以正常播放,音质还不错。除了能转amr还可以转其其它的很多格式。

在网上搜来搜去,都是转载别人文章,而且就是简单的几行调用代码。很少有人写相关的总结,所以决定写个入坑过程,给真正需要的朋友。


最后,附上最新的jave的jar文件以及MAC版的ffmpeg下载地址:点击打开链接


你可能感兴趣的:(MAC OS下使用JAVE将amr转mp3的坑)