Java环境:
注意:以下转码兼容所有Android,iOS.网络上找的关于ffmpeg转mp4,只能兼容部分Android,iOS根本播放不了。
我这里有三个ffmpeg.exe文件版本。网络找下下载对应版本,根据ffmpeg大小不同具有不同的功能。
第1个: ffmpeg.exe 有7.57M大小,在32位系统转mp4标准输出 代码如下(代码为一段一段的转,转完后,再去转其它的):不能合成amr的音视频。需要将amr转为mp3,再合成。
合成前先将amr 转mp3
Listcommend = new ArrayList ();commend.add("c:\\ffmpeg\\ffmpeg");commend.add("-i");commend.add("c:/ffmpeg/input/20160316133058.amr");commend.add("c:\\ffmpeg\\output\\Auuuu.mp3");
将wmv转成mp4
Listcommend = new ArrayList ();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
Listcommend = new ArrayList ();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位系统下才能使用aaccommend.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标准输出 代码同上:
Listcommend = new ArrayList ();//使用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");
Listcommend = new ArrayList ();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位系统上面运行。代码如下:
Listcommend = new ArrayList ();//commend.add("c:\\ffmpeg\\ffmpeg");/*commend.add("-i");//commend.add("c:/ffmpeg/input/courseA.mp4");commend.add("c:/ffmpeg/output/Auuuu.mp4");*//* 目前项目中采用的一种方法 */List commend = new ArrayList ();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 java.net.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 : 苏若年 发送邮件 * * @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; Mapmap = new HashMap (); //创建音频保存路径 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("os.name")); if("/uploadFile".equals(path)){ //提供解析时的一些缺省配置 DiskFileItemFactory factory = new DiskFileItemFactory(); //创建一个解析器,分析InputStream,该解析器会将分析的结果封装成一个FileItem对象的集合 //一个FileItem对象对应一个表单域 ServletFileUpload sfu = new ServletFileUpload(factory); try { Media media = new Media(); List items = sfu.parseRequest(request); boolean flag = false; //转码成功与否的标记 for(int i=0; i 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 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 ----- 不能用Listcommend = new ArrayList ();/*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
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 java.net.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@163.com">发送邮件</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("os.name")); 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); } } } |
package com.victoria.dao;import java.util.List;import com.victoria.entity.Media;/** * * MediaDao.java * * @version : 1.1 * * @author : 苏若年 发送邮件 * * @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 ListqueryALlMedia(int firstResult, int maxResult)throws Exception; /** * 根据Id查询视频 * @param id * @return * @throws Exception */ public Media queryMediaById(int id)throws Exception;}
----------MediaDaoImpl 处理类---------------
package com.victoria.dao.impl; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import com.victoria.dao.MediaDao; import com.victoria.entity.Media; import com.victoria.utils.CommandUtil; public class MediaDaoImpl implements 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 { // 创建一个List集合来保存转换视频文件为flv格式的命令 //获取无音视频路径 String noneSoundVideo = ""; String hasSoundVideo = ""; Process process = null;//------------------ ProcessBuilder builder = new ProcessBuilder();//------------------ InputStream isErr = null;//------------------ InputStream is = null;//------------------ OutputStream os = null; ThreadUtil stdoutUtil = null; ThreadUtil erroroutUtil = null; boolean mark = true; if (codcFilePath.indexOf("/") != -1) { noneSoundVideo = codcFilePath.substring(0, codcFilePath.indexOf("videos")+6) + "/" + "nonesound"+"/" + cid + ".mp4"; hasSoundVideo = codcFilePath.substring(0, codcFilePath.indexOf("videos")+6) + "/"+ "hassound"+"/" + cid + ".mp4"; } System.out.println("--"+noneSoundVideo); //判断无音视频是否存在,不存在则将有音视频转为无音视频。 try { if (!"".equals(noneSoundVideo) && !"".equals(hasSoundVideo) && !fileExist(noneSoundVideo) && fileExist(hasSoundVideo)) { List<String> commend = new ArrayList<String>(); commend.add(ffmpegPath); commend.add("-i"); commend.add(hasSoundVideo); commend.add("-an"); commend.add("-sameq"); commend.add("-y"); commend.add(noneSoundVideo); builder.command(commend);//------------------ builder.redirectErrorStream(true);//------------------ process = builder.start();//------------------ isErr = process.getErrorStream(); is = process.getInputStream(); stdoutUtil = new ThreadUtil(is); erroroutUtil = new ThreadUtil(isErr); //启动线程读取缓冲区数据 stdoutUtil.start(); erroroutUtil.start(); process.waitFor();//------------------ os = process.getOutputStream(); os.flush(); if (os!=null) { os.close(); } //cu.executeCommand(commend); } if (fileExist(ffmpegPath) && fileExist(upFilePath)) { //如果不是mp3文件,将其转为mp3文件 /*boolean flag = false; if (upFilePath.indexOf(".pcm") != -1) { flag = true; } String mp3 = upFilePath.replace(".pcm", ".mp3"); if (flag) { List<String> convert = new ArrayList<String>(); convert.add(ffmpegPath); // 添加转换工具路径 convert.add("-acodec"); convert.add("pcm_s16le"); convert.add("-ar"); convert.add("8000"); convert.add("-ac"); convert.add("2"); convert.add("-f"); convert.add("alaw"); convert.add("-i");// 添加参数"-i",该参数指定要转换的文件 convert.add(upFilePath); convert.add("-acodec"); convert.add("libmp3lame"); convert.add("-ac"); convert.add("2"); convert.add("-ab"); convert.add("128k"); convert.add(mp3); builder.command(convert);//------------------ builder.redirectErrorStream(true);//------------------ process = builder.start();//------------------ isErr = process.getErrorStream(); is = process.getInputStream(); stdoutUtil = new ThreadUtil(is); erroroutUtil = new ThreadUtil(isErr); //启动线程读取缓冲区数据 stdoutUtil.start(); erroroutUtil.start(); process.waitFor();//------------------ os = process.getOutputStream(); os.flush(); if (os!=null) { os.close(); } } convert.add(mp3); // 添加要转换格式的视频文件的路径 convert.add("-qscale"); //指定转换的质量 convert.add("6"); convert.add("-ab"); //设置音频码率 convert.add("64"); convert.add("-ac"); //设置声道数 convert.add("2"); convert.add("-ar"); //设置声音的采样频率 convert.add("22050"); convert.add("-r"); //设置帧频 convert.add("24"); convert.add("-y"); // 添加参数"-y",该参数指定将覆盖已存在的文件 convert.add(codcFilePath); */ // 创建一个List集合来保存从视频中截取图片的命令 List<String> cutpic = new ArrayList<String>(); cutpic.add(ffmpegPath); cutpic.add("-i"); cutpic.add(noneSoundVideo); cutpic.add("-i"); //cutpic.add(mp3); cutpic.add(upFilePath); cutpic.add("-ab"); cutpic.add("192"); cutpic.add("-acodec"); cutpic.add("aac"); cutpic.add("-ac"); cutpic.add("2"); cutpic.add("-ar"); cutpic.add("44100"); cutpic.add("-qscale"); cutpic.add("4"); cutpic.add("-r"); cutpic.add("29.97"); cutpic.add("-s"); cutpic.add("800x480"); cutpic.add("-y"); cutpic.add("-vcodec"); cutpic.add("libx264"); cutpic.add(codcFilePath); builder.command(cutpic);//------------------ builder.redirectErrorStream(true);//------------------ process = builder.start();//------------------ isErr = process.getErrorStream(); is = process.getInputStream(); stdoutUtil = new ThreadUtil(is); erroroutUtil = new ThreadUtil(isErr); //启动线程读取缓冲区数据 stdoutUtil.start(); erroroutUtil.start(); process.waitFor();//------------------ //process.destroy();//------------------ os = process.getOutputStream(); os.flush(); // 如果此属性为 true,则任何由通过此对象的 start() 方法启动的后续子进程生成的错误输出都将与标准输出合并, //因此两者均可使用 Process.getInputStream() 方法读取。这使得关联错误消息和相应的输出变得更容易 } } catch (Exception e) { mark = false; System.out.println(e); e.printStackTrace(); } finally { try{ /*if (isErr != null) {------------------ isErr.close();------------------ } if (is != null) {------------------ is.close(); }------------------*/ if (os != null) {//------------------ os.close();//------------------ } } catch (Exception ee) { mark = false; //ee.printStackTrace(); } } return mark; } private boolean checkfile(String path) { File file = new File(path); if (!file.isFile()) { return false; } return true; } private boolean fileExist(String path) { File file = new File(path); if (file.exists() && file.isFile()){ return true; } return false; } @Override public boolean saveMedia(Media media) throws Exception { // TODO Auto-generated method stub return false; } @Override public int getAllMediaCount() throws Exception { // TODO Auto-generated method stub return 0; } @Override public List<Media> queryALlMedia(int firstResult, int maxResult) throws Exception { // TODO Auto-generated method stub return null; } @Override public Media queryMediaById(int id) throws Exception { // TODO Auto-generated method stub return null; } } class ThreadUtil implements Runnable { // 设置读取的字符编码 private String character = "GB2312"; private InputStream inputStream; public ThreadUtil(InputStream inputStream) { this.inputStream = inputStream; } public void start() { Thread thread = new Thread(this); thread.setDaemon(true);//将其设置为守护线程 thread.start(); } public void run() { BufferedReader br = null; try { br = new BufferedReader(new InputStreamReader(inputStream, character)); String line = null; while ((line = br.readLine()) != null) { if (line != null) { //list.add(line); System.out.println(line); } } } catch (IOException e) { e.printStackTrace(); } finally { try { //释放资源 if (inputStream != null) { inputStream.close(); } if (br != null) { br.close(); } } catch (IOException e) { e.printStackTrace(); } } } } |
补充代码(在项目中因为语音识别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"); |