1:原理 调用ffmpeg 执行转换
即:先把amr 下载到服务器 调用 ffmpeg -i 转换生成MP3 文件 通过二进制流的形式
ajax点击播放异步转换并且生成流通过audio的src属性在web端播放,同时删除后台的amr和mp3文件,此功能是在后台cms 中实现,也可以独立部署转换。
注意:在本地开发时 不管是linux 系列 还是windows系列 一定要安装ffmpeg 工具 即通过控制台可以转换成功。
直接贴代码:
public class AmrToMp3 {
public static void main(String[] args){
AmrToMp3.convertToMp3(args[0], args[1]);
}
public static boolean convertToMp3(String amrFile, String mp3File) {
Process process = null;
try{
File mp3 = new File(mp3File);
if(mp3.exists()){
mp3.delete();
}
process =Runtime.getRuntime().exec("ffmpeg -i " + amrFile + " " + mp3File);
process.waitFor();
}catch (Exception ex){
}finally {
process.destroy();
}
return false;
}
}
/**
* amr 文件转换MP3
*
* @param url
* @param req
* @return
*/
public static String amrSwitchToMp3(String url, HttpServletRequest req) {
try {
OSSObject oos = UploadImageUtils.getFile(url); //阿里存储 具体根据自己的需要
if (oos == null) {
return null;
}
InputStream fis = oos.getObjectContent();
String filePath = "/";
String filen = url.substring(url.lastIndexOf("/") + 1, url.length());
filen = filen.replaceAll(".amr", "");
String realPathDir = req.getSession().getServletContext()
.getRealPath(filePath);
File saveFile = new File(realPathDir);
if (!saveFile.exists())
saveFile.mkdirs();
/** 获取文件的后缀* */
String suffixAmr = ".amr";
String suffixMp3 = ".mp3";
String srcNameEnd = filen + suffixAmr;// 构建文件名称
String targetNameEnd = filen + suffixMp3;// 构建文件名称
/** 拼成完整的文件保存路径加文件* */
String srcName = realPathDir + srcNameEnd;
String targetName = realPathDir + targetNameEnd;
try {
getFileFromInputStream(fis, srcName);
boolean result = AmrToMp3.convertToMp3(srcName, targetName);
File source = new File(srcName);
if (source != null && source.exists()) source.delete();
if (result) {
return targetName;
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* amr 文件转换MP3
*
* @param target
* @param req
* @param resp
* @return
*/
public static boolean getMp3Resp(String target, HttpServletRequest req, HttpServletResponse resp) {
try {
File targetFile = new File(target);
InputStream f = new BufferedInputStream(new FileInputStream(targetFile));
byte[] buffer = new byte[f.available()];
f.read(buffer);
f.close();
resp.addHeader("Content-Disposition", "attachment;filename="+target+".mp3");
resp.addHeader("Content-Length", "" + targetFile.length());
OutputStream ous = new BufferedOutputStream(resp.getOutputStream());
resp.setContentType("application/octet-stream");
ous.write(buffer);
ous.flush();
ous.close();
if (targetFile != null && targetFile.exists()) targetFile.delete();
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 从流中写出文件
*
* @param inStream
* @param imageFileStr
* @throws Exception
*/
public static void getFileFromInputStream(InputStream inStream, String imageFileStr) throws Exception {
//new一个文件对象用来保存图片,默认保存当前工程根目录
File imageFile = new File(imageFileStr);
//创建输出流
FileOutputStream out = new FileOutputStream(imageFile);
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
//创建一个Buffer字符串
byte[] buffer = new byte[1024];
//每次读取的字符串长度,如果为-1,代表全部读取完毕
int len = 0;
//使用一个输入流从buffer里把数据读取出来
while ((len = inStream.read(buffer)) != -1) {
//用输出流往buffer里写入数据,中间参数代表从哪个位置开始读,len代表读取的长度
out.write(buffer, 0, len);
}
//关闭输入流
inStream.close();
//关闭输出流
out.close();
}
控制层的调用:
/**
* 转换语音
*/
@RequestMapping("/amrToMp3")
public
@ResponseBody
Object amrToMp3(@RequestParam(value = "url", required = false) String url,
HttpServletRequest req, HttpServletResponse resp) {
MsgBean msg = new MsgBean();
if (StringUtils.isBlank(url)) {
msg.setFailure(1, "视频播放地址不存在!");
return msg.returnMsg();
}
if (!url.contains("amr")) {
msg.setFailure(1, "视频文件有问题,无法播放!");
return msg.returnMsg();
}
String result = FileUtils.amrSwitchToMp3(url, req);
if (result != null && !"".equals(result)) {
msg.put("url", result);
} else {
msg.setFailure(1, "视频文件地址出错,无法播放!");
return msg.returnMsg();
}
return msg.returnMsg();
}
/**
* 播放语音
*/
@RequestMapping("/playMp3")
public
@ResponseBody
Object playMp3(@RequestParam(value = "url", required = false) String url,
HttpServletRequest req, HttpServletResponse resp) {
if (StringUtils.isBlank(url)) {
return null;
}
return FileUtils.getMp3Resp(url, req, resp);
}
前端js
function amrToMp3(id,url,btn){
var path = "${BasePath}/chatReport/amrToMp3?url=" + url;
$.ajax({
type: "POST",
url: path,
datatype: "json",
success: function (data) {
if (data.errno == 1) {
alert(data.errdesc);
} else {
play(id,data.url,btn);
}
},
error: function () {
alert("操作出错,请联系管理员!");
}
});
}
function play(id,url,btn){
var audio = document.getElementById('audio_'+id);
if(btn.innerHTML=="播放"){
audio.src="${BasePath}/chatReport/playMp3?url=" + url;
}
playOrPaused(audio,btn);
var is_playFinish= setInterval(function(){
if(audio.ended){
// btn.innerHTML=="暂停"
}
//callback(audio,btn);
window.clearInterval(is_playFinish);
},1);
}
function callback(audio,btn){
// audio.play();
playOrPaused(audio,btn);
}
function playOrPaused(id,obj){
if(id.paused){
id.play();
obj.name="";
// obj.innerHTML='暂停';
return;
}
id.pause();
obj.innerHTML='播放';
}
HTML代码:
2: 线上安装ffmpeg工具 centos redhat
(一)安装编译环境
#yum install -y automake autoconf libtool gcc gcc-c++
(二)安装所需程序库的RPM包到 centos(因为centos自带的库中没有ffmpeg包,这里相当于是扩展)
#rpm -Uhv http://apt.sw.be/redhat/el5/en/i386/rpmforge/RPMS/rpmforge-release-0.3.6-1.el5.rf.i386.rpm
如果这一步失败可以将地址“http://apt.sw.be/redhat/el5/en/i386/rpmforge/RPMS/rpmforge-release-0.3.6-1.el5.rf.i386.rpm ”下载到电脑,然后直接运行下面的也可以
#rpm -Uhv rpmforge-release-0.3.6-1.el5.rf.i386.rpm
共享一个RPM包下载链接
(三)安装 Install ffmpeg 等模块
yum -y install ffmpeg ffmpeg-devel
方法二、此方法有时不太好用
1.安装前准备
vi /etc/yum.repos.d/ffmpeg.repo
[dag]
name=Dag RPM Repository for Red Hat Enterprise Linux
baseurl=http://apt.sw.be/redhat/el$releasever/en/$basearch/dag
gpgcheck=0
enabled=1
2.安装ffmpeg
yum -y install ffmpeg ffmpeg-devel
注意:网上好多安装 诸如此类 参考即可 要求安装最新版本各个交叉编译比较繁琐 其实低版本即可
—————————————-华丽的分割线—————————————–
FFmpeg在Linux下的安装
在Redhat 9.0成功安装了ffmpeg,现记录如下。
1、下载ffmpeg。
http://download.chinaunix.net/download.php?id=5532&ResourceID=2990
我是在这个网址上下载ffmpeg-0.4.9-p20051120.tar.bz2,看网上有人用的是svn下载,但是我的机子中没有svn客户端,然后就在网上搜索,下载了这个版本。如果利用svn可以下载ffmpeg最新的版本。
svn checkout svn://svn.mplayerhq.hu/ffmpeg/trunk ffmpeg
2、解压
tar xvfj ffmpeg-0.4.9-p20051120.tar.bz2
得到解压后的目录是ffmpeg-0.4.9-p20051120,名字太长,利用mv命令改为ffmpeg
mv ffmpeg-0.4.9-p20051120.tar.bz2 ffmpeg
3、配置
./configure --enable-shared --prefix=/usr/local/ffmpeg
其中:--enable-shared 是允许其编译产生动态库,在以后的编程中要用到这个几个动态库。--prefix设置的安装目录。
4、编译并安装
make
make install
5、安装之后在/usr/local/ffmpeg会看到有三个目录
lib 动态链接库位置
include 编程要用到头文件
bin 执行文件所在的目录
6、为了以后方便编程,我们把lib中的三个链接库libavcodec.so libavformat.so libavutil.so复制到/usr/lib下。把include目录下的ffmpeg目录复制到/usr/include下。
执行bin目录下的ffplay,可以去播放音频或者视频文件。例如播放1.mp3
./ffplay 1.mp3
另外,bin目录下还有两个文件:ffmpeg和ffserver
ffmpeg是一个很好的视频和音频的格式转化工具。网上有很多它的说明文档。
如果不想生成ffserver,只要在./configure的时候加--disable-ffserver即可。
7、编程
如果写了一个test.c文件,要包含ffmpeg的头文件,可以这样写:
#include <ffmpeg/avcodec.h>
编译:gcc -o test test.c -lavformat -lavcodec -lavtuil (前提是有第6步的操作)
如果没有第6部的操作,则编译的时候如下:
gcc -o test test.c -I/usr/local/ffmpeg/include -L/usr/local/ffmpeg/lib -lavformat
-lavcodec -lavtuil
说明:-I是指明需要的头文件所在的文件,-L是指明动态库所在的目录,后面三个是指明需要的动态库。
编译成功之后,执行的时候还是需要动态库的支持,还是要把那三个动态库文件复制到/usr/lib或者/lib中,不然执行的时候会说找不到动态库链接。还有一个方法可以解决这个问题,就是把/usr/local/ffmpeg/lib这个目录加入到/etc/ld.so.config中,然后执行ldconfig,或者重启电脑,这样执行的时候系统就可以从/usr/local/ffmpeg/lib这个目录下去找这三个动态库文件了。
以上的方式是采用动态库编译ffmpeg的,如果在configure的时候不加上--enable-shared的,则采用静态链接的方式,不会生成那三个动态库。同时生成的ffplay、ffmpeg的执行文件也比较的大,因为他们不需要动态库的支持,就可以执行。但是不利于再次开发,所以我采用动态链接的方式。configure中还有很多的选项,可以通过./configure --help查看,也可以直接查看configure文件。这在配置的时候很重要。