前话 


怎样播放amr音频?这个问题让我好烦恼,在网上找了一些资料,quicktime插件虽然可以播放amr格式的音频,但是不满足项目的要求,html5也不能播放amr格式的音频。后来想到将amr音频转成其他HTML5支持的格式不久行了,后来在网上找到JAVE能转换音频和视频,但是我在转换的过程中老是报如下的异常:

it.sauronsoftware.jave.EncoderException.EncoderException:Duration: N/A, bitrate: N/A

上面报的异常让我摸不着头脑,不知道是什么意思,后来经过研究 JAVE的源代码发现 JAVAE内部其实是使用 FFMPEG来进行转换,其实就是用java来调用ffmpeg.exe来进行转换(windows下是ffmpeg.exe文件,linux下是ffmpeg文件),然后通过解析转换过程中的输出语句来获取一些信息。后来我自己在window8下通过命令行来进行转换,能转换成功,而且支持的格式也很多。通过仔细的研究转换过程中输出的语句,我终于找到了产生上面异常的原因:在音频或视频的转换过程中,JAVAE有一段通过正则表达式来获取时长,开始时间和比特率的代码,而该正则表达式不能匹配到。
Duration: N/A, bitrate: N/A,而JAVE的这段代码(在it.sauronsoftware.jave.Encoder#public void encode(File source, File target, EncodingAttributes attributes, EncoderProgressListener listener) 中):

if (step == 0) {if (line.startsWith("WARNING: ")) {if (listener != null) {listener.message(line);}} else if (!line.startsWith("Output #0")) {throw new EncoderException(line);} else {step++;}
}

从上面的代码可以看出如果是第0步解析到的某行输出不是以 Output #0开头,那么就抛出异常,实际上此时这行的值为Duration: N/A, bitrate: N/A,所以就抛出了如上的异常,从这里也可以看出JAVE是有BUG的:如果通过FFMPEG获取不到时长、开始时间和比特率,那么就会抛出异常,修改上面的配置正则表达式就能修复上面的BUG。实际上JAVE已经很久没维护了,下面进行amr音频格式转换就不使用JAVE,我自己简单的封装一下,可以根据实际的需求进行处理。

实现过程


本文是将amr文件转成mp3文件,然后输出到浏览器,思路:通过过滤器拦截以amr结尾的请求,对请求的路径进行处理,获取到文件所在的真实位置,如果文件不存在则让请求通过,如果存在则找同名的mp3文件,如果同名的mp3文件不存在则将amr转成mp3文件,并以相同的名字以mp3为后缀存储。设置相应的类型为MP3的MIME类型,读取mp3文件并输出。

package cn.zq.amrplay.web.filter;import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import cn.zq.amrplay.util.AudioUtils;/*** <p>此过滤器用来拦截所有以amr后缀结尾的请求,并转换成mp3流输出,输出<strong>MIME</strong>类型为audio/mpeg。</p>* @author Riccio Zhang**/
public class Amr2Mp3Filter implements Filter{/*** mp3扩展名对应的MIME类型,值为"audio/mpeg"*/public final static String MP3_MIME_TYPE = "audio/mpeg";public void init(FilterConfig filterConfig) throws ServletException {}public void destroy() {}public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain)throws IOException, ServletException {HttpServletRequest  request;HttpServletResponse response;try {request = (HttpServletRequest) req;response = (HttpServletResponse) resp;} catch (ClassCastException e) {throw new ServletException("non-HTTP request or response");}String requstURI = request.getRequestURI();String contextPath = request.getContextPath();String resPath = requstURI;//去掉requstURI中contextPath部分和参数部分if(contextPath.length() > 0) {resPath = resPath.substring(contextPath.length());}int index = 0;if((index = resPath.lastIndexOf("?")) != -1) {resPath = resPath.substring(0, index);}String resRealPath = req.getServletContext().getRealPath(resPath);String mp3ResRealPath = resRealPath.replaceFirst(".amr$", ".mp3");File mp3File = new File(mp3ResRealPath);if(!mp3File.exists()) {File amrFile = new File(resRealPath);if(!amrFile.exists()) {filterChain.doFilter(request, response);return;}AudioUtils.amr2mp3(amrFile.getAbsolutePath(), mp3File.getAbsolutePath());}response.setContentLength((int)mp3File.length());response.setContentType(MP3_MIME_TYPE);InputStream in = new FileInputStream(mp3File);OutputStream out = response.getOutputStream();try {byte[] buf = new byte[1024];int len = -1;while((len = in.read(buf)) != -1) {out.write(buf, 0, len);}} finally {try {in.close();} catch (Exception e) {e.printStackTrace();}out.flush();}}}

上面过滤器的实现与上面的思路是吻合的。

音频转换的工具类:

package cn.zq.amrplay.util;import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;public class AudioUtils {/*** ffmpeg.exe文件所在的路径*/private final static String FFMPEG_PATH;static {FFMPEG_PATH = AudioUtils.class.getResource("ffmpeg.exe").getFile();}/*** 将一个amr文件转换成mp3文件* @param amrFile * @param mp3File * @throws IOException */public static void amr2mp3(String amrFileName, String mp3FileName) throws IOException {Runtime runtime = Runtime.getRuntime();Process process = runtime.exec(FFMPEG_PATH + " -i "+amrFileName+" -ar 8000 -ac 1 -y -ab 12.4k " + mp3FileName);InputStream in = process.getErrorStream();BufferedReader br = new BufferedReader(new InputStreamReader(in));try {String line = null;while((line = br.readLine())!=null) {System.out.println(line);}if(process.exitValue() != 0 ) {//如果转换失败,这里需要删除这个文件(因为有时转换失败后的文件大小为0)new File(mp3FileName).delete();throw new RuntimeException("转换失败!");}} finally {//为了避免这里抛出的异常会覆盖上面抛出的异常,这里需要用捕获异常。try {in.close();} catch (Exception e) {e.printStackTrace();}}}
}

上面的工具类 amr2mp3方法,通过 java.lang.Runtime类来执行 ffmpeg.exe文件,在其后加上一系列的参数了(这个命令类似:ffmpeg -i f:\2.mp3 -ar 8000 -ac 1 -ab 12.2k f:\2.amr),并通过 process.getErrorStream() (注意:process.getInputStream()并不能读取到任何输出,这有点奇怪,却要通过错误流才能读取到输出)方法通过流来读取转换过程中的输出,将其包装成了 BufferedReader以便每次读取一行,上面只是简单的讲输出打印到了控制台,最后通过判断程序退出值来判断是否转换成功,如果以退出值等于0则表示转换成功,否则抛出异常,删除mp3文件,最后关闭流。

下面简单说明下ffmpeg的几个命令参数:

  • -i :指定输入文件
  • -ar : 指定sampling rate(采样率),它的单位是HZ
  • -ac:指定声道,1表示双声道,0表示单声道
  • -ab:指定转换后的比特率

PS: 写到这里我才发现,这个工具类有点问题,由于项目代码是提前上传的,请将项目代码里的工具类替换为上面的代码。

过滤器配置:

  <filter><filter-name>Amr2mp3Filter</filter-name><filter-class>cn.zq.amrplay.web.filter.Amr2Mp3Filter</filter-class></filter><filter-mapping><filter-name>Amr2mp3Filter</filter-name><url-pattern>*.amr</url-pattern></filter-mapping>

看一下效果:

资源链接:


  • 本文示例代码下载地址:http://download.csdn.net/detail/qq791967024/9194647
  • JAVE官网地址:http://www.sauronsoftware.it/projects/jave/(有下载地址,官方文档和例子)
  • JAVE源码和jar包下载地址一:http://www.sauronsoftware.it/projects/jave/download.php?PHPSESSID=cgoi3vth901u5bsnemkej1h7p0(官方下载地址,速度非常慢)
  • JAVE源码和jar包下载地址二:http://sourceforge.net/projects/jave/files/1.0.2/(下载速度比较快)
  • ffmpeg官网地址:http://www.ffmpeg.org/(有windows,linux,MAC三个版本,还有一些文档,不过全是英文看起来有点费劲)
  • ffmpeg中文资源一:http://bbs.chinavideo.org/archiver/?fid-10.html
  • ffmpeg中文资源二:http://blog.csdn.net/hemingwang0902/article/details/4382429(这系列的文章还不错,不过有些不适合我们看)

使用servlet过滤器播放amr音频相关推荐

  1. Web端播放 .amr音频文件,企业微信会话存档语音文件

    前言:amr格式是微信上的语音格式,比如企业微信会话存档语音文件保存时就会遇到,由于html标签都不支持amr格式的语音文件,因此采用如下开源项目: https://github.com/BenzLe ...

  2. HTML + js 播放amr音频文件

    将amr文件转化成base64字符串,用js转换成音频播放 js文件下载链接: https://pan.baidu.com/s/1kWsLOc3 密码: 2ca5 链接: https://pan.ba ...

  3. android播放amr音频文件格式,iOS 播放不了android的amr文件

    AMR AMR全称Adaptive Multi-Rate,自适应多速率编码,主要用于移动设备的音频(手机打电话),压缩比比较大,但相对其他的压缩格式质量比较差,由于多用于人声,通话,效果还是很不错的. ...

  4. vue 微信录音倒计时_vue的微信语音功能,录音+对接口返回amr音频播放-Go语言中文社区...

    vue的微信语音功能,录音+对接口返回amr音频播放 最近的新项目需要调用微信的录音功能,但是后台又不给音频转码,无奈之下就踏上了研究前端音频编码器这东西. 参考的GitHub仓库--Recorder ...

  5. 网页开发之amr音频的播放

    mp3格式播放大家都知道,amr格式就陌生了,至少我之前没有做过 amr格式文件播放出来的声音音质比mp3差,主要应用于手机铃声和手机录音,目的是为了给手机用户节省流量.大部分主流的音视频播放器都支持 ...

  6. 纯前端解码、播放、录音、编码 AMR 音频,无须服务器支持

    纯前端解码.播放.录音.编码 AMR 音频,无须服务器支持,基于amr.js 和 RecorderJs. 特性 方便的 API 实现解码.播放.录音.编码 AMR 文件. 支持 url 和 blob ...

  7. audio标签无法播放amr格式音频解决方案(benz-amr-recorder)

    遇到此问题的情形: 单位开发app采用的Hybrid混合开发模式,有些列表页,详情页都是H5页面,我这边的框架是vue写的.最近一个项目中涉及到了视频和音频的展示和播放,因为app有安卓端和ios端, ...

  8. html audio 播放amr,vue.js实现audio播放amr格式音频

    纯前端解码.播放.录音.编码 AMR 音频,无须服务器支持,基于 [amr.js] 注意:由于使用了 amr.js 做编码和解码,因此 js 文件(压缩后,未 gzip)接近 500 KB,使用前请考 ...

  9. h5原生audio播放amr格式的音频

    h5不能播放amr格式的样式,需要进行转码,在下已知的方法有两种 一.引入 js 文件 <script type="text/javascript" src="./ ...

最新文章

  1. php 上传 类 代码,php 文件上传类代码
  2. 重构当当网交易系统!
  3. 吴裕雄 python 神经网络——TensorFlow 花瓣分类与迁移学习(1)
  4. Visual Studio 生成项目前自动关闭在运行的程序
  5. 如何理解IIS 7的两种应用程序池的管道模式(Managed Pipeline Mode)
  6. 子网掩码和网关的关系
  7. Linux系统下安装卸载jdk
  8. 功利性学习:别陷入勤奋陷阱
  9. BZOJ 2668: [cqoi2012]交换棋子
  10. 配置Server Side TAF
  11. python最简单的账号密码验证_Python之简单的用户名密码验证
  12. android多图拼接长图并合理显示
  13. 2020手机的像素密度ppi排行_5g手机排行榜最新2020年11月5g手机性价比排行榜
  14. Pygame(三)画圆
  15. 11.21的自动锁屏 ios_iPhone11 的新手小技巧
  16. 冰盾ARP防火墙V1.0 Build 80122
  17. php中文拼音模糊,两种php中文字符转拼音问题解决方法
  18. 读东野圭吾《白夜行》有感
  19. Jenkins无法启动:com.michelin.cio.hudson.plugins.rolestrategy.RoleBasedAuthorizationStrategy
  20. n76e003引脚图_新唐推出N76E003高规格低管脚1T 8051单片机

热门文章

  1. c++软件开发面试旋极面试题_北京旋极信息技术股份有限公司2015招聘
  2. PC机插入麦克风后没有说话没有声音
  3. Windows10开机音乐替换
  4. 基于layui后台html模板免费下载
  5. dolphinscheduler海豚调度是什么?
  6. 使用Qt5.7.0 VS2015版本生成兼容XP的可执行程序
  7. ARM指令寻址方式及RealView MDK开发环境ARM汇编程序实践
  8. Spectra Logic的数据备份和归档解决方案推动企业磁带销量增长
  9. 通过码云来学习Git的进阶技能(文末附福利!)
  10. 以太坊数字资产的发行和流通:以太坊上的数字资产定义、ERC 20代币合约标准、ERC 20标准接口、ERC 721代币合约标准、