Java环境:
注意:以下转码兼容所有Android,iOS.网络上找的关于ffmpeg转mp4,只能兼容部分Android,iOS根本播放不了。
我这里有三个ffmpeg.exe文件版本。网络找下下载对应版本,根据ffmpeg大小不同具有不同的功能。
第1个: ffmpeg.exe 有7.57M大小,在32位系统转mp4标准输出 代码如下(代码为一段一段的转,转完后,再去转其它的):不能合成amr的音视频。需要将amr转为mp3,再合成。
合成前先将amr 转mp3
List<String> commend = new ArrayList<String>();
commend.add("c:\\ffmpeg\\ffmpeg");
commend.add("-i");
commend.add("c:/ffmpeg/input/20160316133058.amr");
commend.add("c:\\ffmpeg\\output\\Auuuu.mp3");
将wmv转成mp4
List<String> commend = new ArrayList<String>();
commend.add("c:\\ffmpeg\\ffmpeg");
commend.add("-i");
//commend.add("c:/ffmpeg/input/courseA.mp4");
commend.add("c:/ffmpeg/input/A.wmv");
commend.add("-ab");
commend.add("192");
commend.add("-acodec");
//commend.add("aac");
commend.add("libfaac");
commend.add("-ac");
commend.add("2");
commend.add("-ar");
commend.add("44100");
commend.add("-qscale");
commend.add("4");
commend.add("-r");
commend.add("29.97");
commend.add("-s");
commend.add("800x480");
commend.add("-y");
commend.add("c:\\ffmpeg\\output\\ACK.mp4");
将音频和视频合成mp4
List<String> commend = new ArrayList<String>();
commend.add("c:\\ffmpeg\\ffmpeg");
commend.add("-i");
commend.add("c:/ffmpeg/input/courseC.mp4");
commend.add("-i");
commend.add("c:/ffmpeg/output/Auuuu.mp3");
commend.add("-ab");
commend.add("192");
commend.add("-acodec");
//commend.add("aac"); 在32位系统下不能使用aac.在64位系统下才能使用aac
commend.add("libfaac"); //32位系统下使用,64位不能用。
commend.add("-ac");
commend.add("2");
commend.add("-ar");
commend.add("44100");
commend.add("-qscale");
commend.add("4");
commend.add("-r");
commend.add("29.97");
commend.add("-s");
commend.add("800x480");
commend.add("-y");
commend.add("c:\\ffmpeg\\output\\ACKKPPPP.mp4");
第2个: ffmpeg.exe 有33.1M大小,在32位系统转mp4标准输出 代码同上:
List<String> commend = new ArrayList<String>();
//使用
commend.add("c:\\ffmpeg\\ffmpeg");
//commend.add("-i");
//commend.add("c:/ffmpeg/input/courseA.mp4");
//commend.add("c:/ffmpeg/output/Auuuu.mp4");
commend.add("-i");
commend.add("c:/ffmpeg/input/courseC.mp4");
commend.add("-i");
commend.add("c:/ffmpeg/input/20160316133058.amr"); //------如果想合成amr和mp4,需要把以下红色注释掉。否则只能将amr先转mp3,再来合成。(不需要注释下面红色部分。),
commend.add("-ab");
commend.add("192");
//commend.add("-acodec");
//commend.add("aac");
//commend.add("libfaac");
commend.add("-ac");
commend.add("2");
commend.add("-ar");
commend.add("44100");
commend.add("-qscale");
commend.add("4");
commend.add("-r");
commend.add("29.97");
commend.add("-s");
commend.add("800x480");
commend.add("-y");
commend.add("-vcodec");
commend.add("libx264");
commend.add("c:\\ffmpeg\\output\\ACKKPPPP.mp4");
List<String> commend = new ArrayList<String>();
commend.add("c:\\ffmpeg\\ffmpeg");
commend.add("-i");
//commend.add("c:/ffmpeg/input/courseA.mp4");
commend.add("c:/ffmpeg/input/C.wmv");
commend.add("-ab");
commend.add("192");
commend.add("-acodec");
commend.add("aac"); //--------wmv转mp4这里,必须使用这个。
//commend.add("libfaac");
commend.add("-ac");
commend.add("2");
commend.add("-ar");
commend.add("44100");
commend.add("-qscale");
commend.add("4");
commend.add("-r");
commend.add("29.97");
commend.add("-s");
commend.add("800x480");
commend.add("-y");
commend.add("c:\\ffmpeg\\output\\courseC.mp4");
第3个:ffmpeg.exe 有37.3大小,是64位的,只能在64位系统上面运行。代码如下:
List<String> commend = new ArrayList<String>();
//commend.add("c:\\ffmpeg\\ffmpeg");
/*commend.add("-i");
//commend.add("c:/ffmpeg/input/courseA.mp4");
commend.add("c:/ffmpeg/output/Auuuu.mp4");*/
/* 目前项目中采用的一种方法 */
List<String> commend = new ArrayList<String>();
commend.add("c:\\ffmpeg\\ffmpeg");
commend.add("-i");
commend.add("c:/ffmpeg/input/courseC.mp4");
commend.add("-i");
commend.add("c:/ffmpeg/input/20160316133058.amr");
commend.add("-ab");
commend.add("192");
commend.add("-acodec");
commend.add("aac"); //--------64位ffmpeg时 请用这个格式转。
//commend.add("libfaac"); --------32位ffmpeg时,请用这个格式转。
commend.add("-ac");
commend.add("2");
commend.add("-ar");
commend.add("44100");
commend.add("-qscale");
commend.add("4");
commend.add("-r");
commend.add("29.97");
commend.add("-s");
commend.add("800x480");
commend.add("-y");
commend.add("-vcodec");
commend.add("libx264");
commend.add("c:\\ffmpeg\\output\\ACKKLMOPLLL.mp4");
以下为完整的代码:
流程是:Servlet接收上传的amr文件。并将ffmpeg路径和音频路径,视频路径转到这个类下面执行。
--------------Servlet ----------------
package com.victoria.controller;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import .URLDecoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import com.victoria.dao.DaoFactory;
import com.victoria.dao.MediaDao;
import com.victoria.entity.Media;
import com.victoria.manager.MediaManager;
import com.victoria.utils.DateTimeUtil;
/**
*
* MediaService.java
*
* @version : 1.1
*
* @author : 苏若年 <a href="mailto:DennisIT@">发送邮件</a>
*
* @since : 1.0 创建时间: 2013-2-08 下午02:24:47
*
* TODO : class MediaService.java is used for ...
*
*/
public class MediaServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
MediaDao mediaDao = DaoFactory.getMediaDao();
ServletContext sctx = this.getServletContext();
//获得保存文件的路径
String audiosPath = sctx.getRealPath("audios");
String videosPath = sctx.getRealPath("videos");
String dataPath = DateTimeUtil.getYMDFormat();
String savePath = ""; //mp4保存路径
String fileName = ""; //上传的文件名
audiosPath = audiosPath + File.separator + dataPath;
Map<String, String> map = new HashMap<String, String>();
//创建音频保存路径
File audiosFile = new File(audiosPath);
if (!audiosFile.exists()) {
audiosFile.mkdir();
}
//创建视频保存路径
videosPath = videosPath + File.separator + dataPath;
File videosFile = new File(videosPath);
if (!videosFile.exists()) {
videosFile.mkdir();
}
String uri = request.getRequestURI();
String path = uri.substring(uri.lastIndexOf("/"));
if (uri.indexOf(".") != -1) {
path = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
}
//System.out.println("path: "+ System.getProperties().getProperty(""));
if("/uploadFile".equals(path)){
//提供解析时的一些缺省配置
DiskFileItemFactory factory = new DiskFileItemFactory();
//创建一个解析器,分析InputStream,该解析器会将分析的结果封装成一个FileItem对象的集合
//一个FileItem对象对应一个表单域
ServletFileUpload sfu = new ServletFileUpload(factory);
try {
Media media = new Media();
List<FileItem> items = sfu.parseRequest(request);
boolean flag = false; //转码成功与否的标记
for(int i=0; i<items.size(); i++){
FileItem item = items.get(i);
//要区分是上传文件还是普通的表单域
if(!item.isFormField()){//isFormField()为true,表示这不是文件上传表单域
//上传文件
//获得文件名
fileName = item.getName();
System.out.println("---------------上传文件名:"+fileName+"-----------------");
long size = item.getSize();
if((fileName == null || "".equals(fileName)) && size == 0){
continue;
}
fileName = URLDecoder.decode(fileName, "UTF-8");
//System.out.println("上传文件" + item.getName());
//在某些操作系统上,item.getName()方法会返回文件的完整名称,即包括路径
String mp3 = audiosPath + File.separator + DateTimeUtil.getYMDHMS();
String fileType = "";
if (fileName.indexOf(".")!=-1) {
fileType = fileName.substring(fileName.lastIndexOf(".")); //截取文件格式
mp3 += fileType;
}
//待转码的文件
File uploadFile = new File(mp3);
item.write(uploadFile);
System.out.println("--------------mp3:"+mp3+"--------------");
if(item.getSize()>500*1024*1024){
map.put("state", "0");
}
//String mediaPicPath = basePath + "/images" +File.separator+ serialName + ".jpg"; //设置上传视频截图的保存路径
// 获取配置的转换工具(ffmpeg.exe)的存放路径
String ffmpegPath = getServletContext().getRealPath("/tools/ffmpeg.exe");
System.out.println("--------------ffmpegPath:"+ffmpegPath+"--------------");
String[] arr = null;
if (fileName.indexOf(File.separator)!=-1) {
//如果文件名带完整路径 包括 斜杠的。进行截取
String wei = fileName.substring(fileName.lastIndexOf(File.separator)+1, fileName.lastIndexOf("."));
arr = wei.split("-");
media.setImei(wei.substring(0, wei.lastIndexOf("-")));
media.setCid(arr[arr.length-1]);
if ("course1".equals(arr[arr.length-1])){
} else {
}
} else {
//如果文件名是不带路径的
String wei = fileName.substring(0, fileName.lastIndexOf("."));
arr = wei.split("-");
media.setImei(wei.substring(0, wei.lastIndexOf("-")));
media.setCid(arr[arr.length-1]);
System.out.println("imei:"+media.getImei()+"Cid:"+arr[arr.length-1]);
if ("course1".equals(arr[1])){
} else {
}
}
String codcFilePath = videosPath +File.separator+ media.getCid() +"-" + DateTimeUtil.getYMDHMS() + ".mp4";//设置转换为flv格式后文件的保存路径
//用于保存mp4最终路径
savePath = "/videos/" + dataPath + "/" + media.getCid() +"-" +DateTimeUtil.getYMDHMS() + ".mp4";
media.setSrc("/audios/" + dataPath + "/" + DateTimeUtil.getYMDHMS() + fileType);
media.setDest(savePath);
media.setUptime(DateTimeUtil.getYMDHMSFormat());
//转码
ffmpegPath = ffmpegPath.replaceAll("\\\\","/");
codcFilePath = codcFilePath.replaceAll("\\\\","/");
String uploadFilePath = uploadFile.getAbsolutePath().replaceAll("\\\\","/");
flag = mediaDao.executeCodecs(ffmpegPath, uploadFilePath, codcFilePath, media.getCid());
}
}
if(flag){
//转码成功,向数据表中添加该视频信息
//mediaDao.saveMedia(media);
//MediaManager.getInstance().addMedia(media);
map.put("state", "1");
map.put(media.getCid(), savePath);
} else {
map.put("state", "0");
}
//request.setAttribute("message", message);
//request.getRequestDispatcher("media_upload.jsp").forward(request,response);
//response.sendRedirect(request.getContextPath()+ "/index.jsp?success=modify");
} catch (Exception e) {
e.printStackTrace();
map.put("state", "0");
throw new ServletException(e);
} finally {
//response.getOutputStream().write();
response.setCharacterEncoding("UTF-8");
response.getWriter().print(JSONObject.fromObject(map));
}
}
if("/queryAll".equals(path)){
List<Media> mediaList;
try {
mediaList = mediaDao.queryALlMedia(0,5);
request.setAttribute("mediaList", mediaList);
request.getRequestDispatcher("media_list.jsp").forward(request, response);
} catch (Exception e) {
e.printStackTrace();
}
}
if("/play".equals(path)){
String idstr = request.getParameter("id");
int mediaId = -1;
Media media = null;
if(null!=idstr){
mediaId = Integer.parseInt(idstr);
}
try {
media = mediaDao.queryMediaById(mediaId);
} catch (Exception e) {
e.printStackTrace();
}
request.setAttribute("media", media);
request.getRequestDispatcher("media_player.jsp").forward(request, response);
}
}
}
补充代码(在项目中因为语音识别apk不能和系统自带的录音调用接口同时使用,导致 我只能用语音识别apk去生成pcm格式文件):
因为pcm格式不能和视频直接合成,需要先转换为amr音频文件或wav文件后,才能和视频合成。代码如下:
//ffmpeg -f s16le -ar 8000 -ac 2 -i out.pcm -ar 44100 -ac 2 out.wav ---- 可用
//ffmpeg -i file.wav -f s16le -acodec pcm_s16le file.pcm ----- 没测
//ffmpeg -f s16le -ar 44.1k -ac 2 -i file.pcm file.wav ----- 没测
// ffmpeg -y -ac 2 -ar 44100 -f s16le -i output.pcm -acodec libmp3lame -ab 128k a.mp3 ----- 不能用
List<String> commend = new ArrayList<String>();
/*commend.add("c:\\ffmpeg\\ffmpeg");
commend.add("-f");
commend.add("s16le");
commend.add("-ar");
commend.add("8000");
commend.add("-ac");
commend.add("2");
commend.add("-i");
commend.add("c:\\ffmpeg\\input\\863925029959719-courseA.pcm");
commend.add("-ar");
commend.add("44100");
commend.add("-ac");
commend.add("2");
commend.add("c:\\ffmpeg\\output\\vvvvvvvvv.wav");*/
//ffmpeg -i testwav.wav -ar 8000 -ab 12.2k audio.amr -----不能用
//ffmpeg -i test.wav -acodec libamr_nb -ab 12.2k -ar 8000 -ac 1 wav2amr.amr -----不能用
//ffmpeg.exe -i PA003.wav -ar 8000 -ab 12.2k -ac 1 target.amr 此方法验证通过
commend.add("c:\\ffmpeg\\ffmpeg");
commend.add("-i");
commend.add("c:\\ffmpeg\\output\\vvvvvvvvv.wav");
//commend.add("-acodec");
//commend.add("libamr_nb");
commend.add("-ab");
commend.add("12.2k");
commend.add("-ar");
commend.add("8000");
commend.add("-ac");
commend.add("1");
commend.add("c:\\ffmpeg\\output\\audio.amr");
Java环境:
注意:以下转码兼容所有Android,iOS.网络上找的关于ffmpeg转mp4,只能兼容部分Android,iOS根本播放不了。
我这里有三个ffmpeg.exe文件。
第1个: ffmpeg.exe 有7.57M大小,在32位系统转mp4标准输出 代码如下(代码为一段一段的转,转完后,再去转其它的):不能合成amr的音视频。需要将amr转为mp3,再合成。
合成前先将amr 转mp3
|
将wmv转成mp4
|
将音频和视频合成mp4
|
第2个: ffmpeg.exe 有33.1M大小,在32位系统转mp4标准输出 代码同上:
|
|
第3个:ffmpeg.exe 有37.3大小,是64位的,只能在64位系统上面运行。代码如下:
|
以下为完整的代码:
流程是:Servlet接收上传的amr文件。并将ffmpeg路径和音频路径,视频路径转到这个类下面执行。
--------------Servlet ----------------
|
package com.victoria.dao;
import java.util.List;
import com.victoria.entity.Media;
/**
*
* MediaDao.java
*
* @version : 1.1
*
* @author : 苏若年 <a href="mailto:DennisIT@">发送邮件</a>
*
* @since : 1.0 创建时间: 2013-2-07 上午10:19:54
*
* TODO : interface MediaDao.java is used for ...
*
*/
public interface MediaDao {
/**
* 视频转码
* @param ffmpegPath 转码工具的存放路径
* @param upFilePath 用于指定要转换格式的文件,要截图的视频源文件
* @param codcFilePath 格式转换后的的文件保存路径
* @param mediaPicPath 截图保存路径
* @return
* @throws Exception
*/
public boolean executeCodecs(String ffmpegPath,String upFilePath, String codcFilePath, String cid)throws Exception;
/**
* 保存文件
* @param media
* @return
* @throws Exception
*/
public boolean saveMedia(Media media) throws Exception;
/**
* 查询本地库中所有记录的数目
* @return
* @throws Exception
*/
public int getAllMediaCount()throws Exception;
/**
* 带分页的查询
* @param firstResult
* @param maxResult
* @return
*/
public List<Media> queryALlMedia(int firstResult, int maxResult)throws Exception;
/**
* 根据Id查询视频
* @param id
* @return
* @throws Exception
*/
public Media queryMediaById(int id)throws Exception;
}
----------MediaDaoImpl 处理类---------------
|
补充代码(在项目中因为语音识别apk不能和系统自带的录音调用接口同时使用,导致 我只能用语音识别apk去生成pcm格式文件):
因为pcm格式不能和视频直接合成,需要先转换为amr音频文件或wav文件后,才能和视频合成。代码如下:
|
















