amr转mp3 linux
2015-02-11 16:50:33 zhelong111 阅读数 64

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
* 将amr文件转为mp3格式文件
* 【在windows、linux、mac通用可行的解决方案】
* 在web项目中只需将ffmpeg命令放到和执行命令的程序同一个目录,调用命令:ffmpeg -i src.amr dst.mp3
* @author bruse
*
*/
public class FFmpeg {

public static boolean amrToMp3(String localPath, String targetFilePath) {

try {

System.out.println("************** ffmpeg ****************");

java.lang.Runtime rt = Runtime.getRuntime();
String command = "/Users/bruse/Desktop/ffmpeg -i " + localPath + " " + targetFilePath;

System.out.println("/Users/bruse/Desktop/ffmpeg exec command = " + command);

Process proc = rt.exec(command);
InputStream stderr = proc.getErrorStream();
InputStreamReader isr = new InputStreamReader(stderr);
BufferedReader br = new BufferedReader(isr);
String line = null;
StringBuffer sb = new StringBuffer();
while ((line = br.readLine()) != null)
sb.append(line);

System.out.println("ffmpeg Process errorInfo: " + sb.toString());

int exitVal = proc.waitFor();
System.out.println("ffmpeg Process exitValue: " + exitVal);

return true;
} catch (Exception e) {
System.out.println("ffmpeg exec cmd Exception " + e.toString());
}
return false;
}

public static void main(String[] args) {
String path1 = "/Users/bruse/Desktop/527732_RA8NRoCNXQcrAKOju7zXXTgXHbHJnt4qXaeSSftbzBaXGnsxT49br2e-H4HMlTp4.amr";
String path2 = "/Users/bruse/Desktop/bb.mp3";
amrToMp3(path1, path2);
}

}

其中ffmpeg命令文件,从官网下载:
http://ffmpeg.org/download.html
2019-06-17 15:11:00 qq_35773649 阅读数 27

1.下载对应的工具

ffmpeg下载链接:http://ffmpeg.org/download.html

yasm下载链接:http://www.linuxfromscratch.org/blfs/view/svn/general/yasm.html

lame下载接:https://sourceforge.net/projects/lame/files/lame/

建议都下载最新的版本~

把下载的文件放在要安装的目录里

2.安装

2.1安装lame:

  •  tar -zxf lame-3.100.tar.gz
  • cd lame-3.100
  • ./configure
  • make
  • make install2

 

2.2安装yasm:

  • tar -zxf yasm-1.3.0.tar.gz
  • cd yasm-1.3.0
  • sed -i 's#) ytasm.*#)#' Makefile.in
  • ./configure
  • make
  • make install

2.3安装ffmpeg:

  •  tar -jxf ffmpeg-3.4.tar.bz2
  • cd ffmpeg-3.4
  • ./configure --enable-shared --enable-libmp3lame
  • make
  • make install

3.配置调整

  •  vim/etc/ld.so.conf
  • 输入 i
  • 往后添加一行 /usr/local/lib
  • 然后按esc  :wq保存退出
  • 保存后执行命令 :ldconfig 重加载配置文件

4.测试是否成功:

 /usr/local/ffmpeg-4.1/ffmpeg  -i /usr/wwwroot/sesame/answer/media/7CalDud5qzoDfLv0AMMvYhOhzVfMJ8TknuA8O5bpmS3LbO4PwJeFmldWjF5NQ9R3.amr /usr/wwwroot/sesame/answer/media/7CalDud5qzoDfLv0AMMvYhOhzVfMJ8TknuA8O5bpmS3LbO4PwJeFmldWjF5NQ9R3.mp3

解释下:/usr/local/ffmpeg-4.1/ffmpeg安装路径 

              -i是执行命令

            /usr/local/ffmpeg-4.1/ffmpeg  -i 原文件存放地址  转码后存放地址

参考: https://www.cnblogs.com/lsdb/p/7787547.html

2017-09-22 23:25:00 weixin_30390075 阅读数 3

 

根据帖子: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包的源代码已经贴上了。

不想手动的同学可以直接下载:

链接: https://pan.baidu.com/s/1c2FAp8k    密码: fmx3

该帖子属于原创帖子:转载请贴原帖子的地址,谢谢!

 

转载于:https://www.cnblogs.com/fennudexiaofan/p/7577671.html

2012-01-19 21:37:53 tq02ksu 阅读数 34
for i in *.wma ; do
mplayer -ao pcm:file="${i%wma}wav" "$i" &&
lame -h "${i%wma}wav" "${i%wma}mp3" &&
rm -f "${i%wma}wav"
done
2018-10-20 17:26:42 weixin_34195364 阅读数 84

作为一名技术宅男,没事就上掘金来淘宝,在这学习了很多东西,也一直想开个博客,写写自己的东西,一方面就当是笔记,另一方面也可以作为他人学习的前进的一种参考,本着这样的想法今天来开启我的第一篇博客之路,俗话说前人栽树后人乘凉,我们受益于前人,亦让后人得益于我们,废话不多说了让我们开启转码吧,在此郑重说明:所写内容均来自与实战,可借鉴,有问题可与本人联系,共同探讨,一起进步.

需求背景简介

在一个特定的场景之下,pc端管理后台可以为场景上传一个默认的语音讲解,然后在app端,用户可以为听场景的讲解也可以单独为场景配音,上传通过之后,会在用户端展示供他人播放。 **

难点解刨

录音上传很简单,但是在上传后会发现Android的录音默认是amr格式的,audio标签不能播放,为了兼容性决定将音频的格式统一成MP3。将pc端上传的音频一并处理,并计算音频的时长。

实战

鉴于此想法,开启填坑之路。 度娘了一些博客,基本都是指向了JAVe.jar,官网:www.sauronsoftware.it/projects/ja… ,想着有希望了,但点击下载才发现最后的一个版本是2009,已经快十年都没更新升级了,然后又看了一下文档介绍:Installation and requirements In order to use JAVE in your Java application, you have to add the file jave-1.0.jar in your application CLASSPATH. JAVE runs on a Java Runtime Environment J2SE v.1.4 or later.JAVE includes and uses a ffmpeg executable built for Windows and Linux operating systems on i386/32 bit hardware platforms. In order to run JAVE on other platforms you have to replace the built-in ffmpeg executable with another one suitable for your needs. This is very simple, once you have built your own ffmpeg binaries. The operation is described in the "Using an alternative ffmpeg executable" section., 大意就是说安装JAVE的Java 1.4以上版本,仅仅支持32位的Windows and Linux。这一点非常的坑,不可能为了转码将linux以及windows都换成32位的,但是继续又说到根据需要用二进制文件ffmpeg 替换一下,就可以在不同环境下使用了,这个好像可以解决;注意这一句‘Using an alternative ffmpeg executable’,点进去后可以看到,

这一段说的就很清楚了,jave并不是纯java写的,真正干活的是ffmpeg这个c语言写的,这下清楚了,原来是官方是只提供了32位的ffmpeg可执行文件,我们需要干的就是弄一个64位的可执行文件就可以搞定了,然后继承FFMPEGLocator 类,实现里边的方法在创建新的编码器就可以,点开上边的网址http://ffmpeg.mplayerhq.hu/,,来到ffmpeg的官网点击下载看到

看到linux 好开心,再看最后一行,32位64位静态编译是什么鬼,点进去看一看

卧槽,安装说明,毫不犹豫进去看看

我的乖乖,静态编译安装,二进制的,美太太,然后按照说明一路执行命令就可以了,执行完成后就可以得到一个64位二进制文件ffmpeg,然后将ffmpeg拷贝出来放在Java项目中就可以了。最主要的事情完成了。偷笑一下。 再次回到JAVE的官网继续看,拉到文档底部,可以看到 Examples,然后剔除不要的(只需转码),基本就剩下:

File source = new File("source.amr");
File target = new File("target.mp3");
AudioAttributes audio = new AudioAttributes();
audio.setCodec("libmp3lame");
EncodingAttributes attrs = new EncodingAttributes();
attrs.setFormat("mp3");
attrs.setAudioAttributes(audio);
Encoder encoder = new Encoder();
encoder.encode(source, target, attrs);
复制代码

现在一目了然,根据官方文档只需替换用Encoder encoder = new Encoder(new MyFFMPEGExecutableLocator())就可以在linux64上使用了。同时windows也可以使用原来的编码器。也就是说只需要在不同的环境下切换编码器就可以了。这样就可以完美的解决windows以及linux下的音频转码问题了。

提示:如果在linux上依然不能成功,请给ffmpeg的相关执行权限

声明:本人第一次写博客,有不当的地方还请海涵,有不明白的问题可以留言,不喜勿喷,请学会尊重别人。

[Linux] Play MP3

阅读数 1

Linux mp3乱码问题

阅读数 1

WMA to MP3 in Linux

阅读数 19

[Linux] Play MP3

阅读数 29

[Linux] Play MP3

阅读数 34

没有更多推荐了,返回首页