Java环境:
 
注意:以下转码兼容所有Android,iOS.网络上找的关于ffmpeg转mp4,只能兼容部分Android,iOS根本播放不了。
 
我这里有三个ffmpeg.exe文件版本。网络找下下载对应版本,根据ffmpeg大小不同具有不同的功能。
第1个: ffmpeg.exe 有7.57M大小,在32位系统转mp4标准输出  代码如下(代码为一段一段的转,转完后,再去转其它的):不能合成amr的音视频。需要将amr转为mp3,再合成。
 

 

合成前先将amr 转mp3
  1. List<String> commend = new ArrayList<String>();
  2. commend.add("c:\\ffmpeg\\ffmpeg");
  3. commend.add("-i");
  4. commend.add("c:/ffmpeg/input/20160316133058.amr");
  5. commend.add("c:\\ffmpeg\\output\\Auuuu.mp3");

将wmv转成mp4

  1. List<String> commend = new ArrayList<String>();
  2. commend.add("c:\\ffmpeg\\ffmpeg");
  3. commend.add("-i");
  4. //commend.add("c:/ffmpeg/input/courseA.mp4");
  5. commend.add("c:/ffmpeg/input/A.wmv");
  6. commend.add("-ab");
  7. commend.add("192");
  8. commend.add("-acodec");
  9. //commend.add("aac");
  10. commend.add("libfaac");
  11. commend.add("-ac");
  12. commend.add("2");
  13. commend.add("-ar");
  14. commend.add("44100");
  15. commend.add("-qscale");
  16. commend.add("4");
  17. commend.add("-r");
  18. commend.add("29.97");
  19. commend.add("-s");
  20. commend.add("800x480");
  21. commend.add("-y");
  22. commend.add("c:\\ffmpeg\\output\\ACK.mp4");

将音频和视频合成mp4

  1. List<String> commend = new ArrayList<String>();
  2. commend.add("c:\\ffmpeg\\ffmpeg");
  3. commend.add("-i");
  4. commend.add("c:/ffmpeg/input/courseC.mp4");
  5. commend.add("-i");
  6. commend.add("c:/ffmpeg/output/Auuuu.mp3");
  7. commend.add("-ab");
  8. commend.add("192");
  9. commend.add("-acodec");
  10. //commend.add("aac"); 在32位系统下不能使用aac.在64位系统下才能使用aac
  11. commend.add("libfaac"); //32位系统下使用,64位不能用。
  12. commend.add("-ac");
  13. commend.add("2");
  14. commend.add("-ar");
  15. commend.add("44100");
  16. commend.add("-qscale");
  17. commend.add("4");
  18. commend.add("-r");
  19. commend.add("29.97");
  20. commend.add("-s");
  21. commend.add("800x480");
  22. commend.add("-y");
  23. commend.add("c:\\ffmpeg\\output\\ACKKPPPP.mp4");

 

第2个: ffmpeg.exe 有33.1M大小,在32位系统转mp4标准输出  代码同上:

  1. List<String> commend = new ArrayList<String>();
  2. //使用
  3. commend.add("c:\\ffmpeg\\ffmpeg");
  4. //commend.add("-i");
  5. //commend.add("c:/ffmpeg/input/courseA.mp4");
  6. //commend.add("c:/ffmpeg/output/Auuuu.mp4");
  7. commend.add("-i");
  8. commend.add("c:/ffmpeg/input/courseC.mp4");
  9. commend.add("-i");
  10. commend.add("c:/ffmpeg/input/20160316133058.amr"); //------如果想合成amr和mp4,需要把以下红色注释掉。否则只能将amr先转mp3,再来合成。(不需要注释下面红色部分。),
  11. commend.add("-ab");
  12. commend.add("192");
  13. //commend.add("-acodec");
  14. //commend.add("aac");
  15. //commend.add("libfaac");
  16. commend.add("-ac");
  17. commend.add("2");
  18. commend.add("-ar");
  19. commend.add("44100");
  20. commend.add("-qscale");
  21. commend.add("4");
  22. commend.add("-r");
  23. commend.add("29.97");
  24. commend.add("-s");
  25. commend.add("800x480");
  26. commend.add("-y");
  27. commend.add("-vcodec");
  28. commend.add("libx264");
  29. commend.add("c:\\ffmpeg\\output\\ACKKPPPP.mp4");
  1. List<String> commend = new ArrayList<String>();
  2. commend.add("c:\\ffmpeg\\ffmpeg");
  3. commend.add("-i");
  4. //commend.add("c:/ffmpeg/input/courseA.mp4");
  5. commend.add("c:/ffmpeg/input/C.wmv");
  6. commend.add("-ab");
  7. commend.add("192");
  8. commend.add("-acodec");
  9. commend.add("aac"); //--------wmv转mp4这里,必须使用这个。
  10. //commend.add("libfaac");
  11. commend.add("-ac");
  12. commend.add("2");
  13. commend.add("-ar");
  14. commend.add("44100");
  15. commend.add("-qscale");
  16. commend.add("4");
  17. commend.add("-r");
  18. commend.add("29.97");
  19. commend.add("-s");
  20. commend.add("800x480");
  21. commend.add("-y");
  22. commend.add("c:\\ffmpeg\\output\\courseC.mp4");

第3个:ffmpeg.exe 有37.3大小,是64位的,只能在64位系统上面运行。代码如下:

  1. List<String> commend = new ArrayList<String>();
  2. //commend.add("c:\\ffmpeg\\ffmpeg");
  3. /*commend.add("-i");
  4. //commend.add("c:/ffmpeg/input/courseA.mp4");
  5. commend.add("c:/ffmpeg/output/Auuuu.mp4");*/
  6. /* 目前项目中采用的一种方法 */
  7. List<String> commend = new ArrayList<String>();
  8. commend.add("c:\\ffmpeg\\ffmpeg");
  9. commend.add("-i");
  10. commend.add("c:/ffmpeg/input/courseC.mp4");
  11. commend.add("-i");
  12. commend.add("c:/ffmpeg/input/20160316133058.amr");
  13. commend.add("-ab");
  14. commend.add("192");
  15. commend.add("-acodec");
  16. commend.add("aac"); //--------64位ffmpeg时 请用这个格式转。
  17. //commend.add("libfaac"); --------32位ffmpeg时,请用这个格式转。
  18. commend.add("-ac");
  19. commend.add("2");
  20. commend.add("-ar");
  21. commend.add("44100");
  22. commend.add("-qscale");
  23. commend.add("4");
  24. commend.add("-r");
  25. commend.add("29.97");
  26. commend.add("-s");
  27. commend.add("800x480");
  28. commend.add("-y");
  29. commend.add("-vcodec");
  30. commend.add("libx264");
  31. commend.add("c:\\ffmpeg\\output\\ACKKLMOPLLL.mp4");
以下为完整的代码:
流程是:Servlet接收上传的amr文件。并将ffmpeg路径和音频路径,视频路径转到这个类下面执行。
 

 

————–Servlet —————-
  1. package com.victoria.controller;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.io.PrintWriter;
  5. import java.net.URLDecoder;
  6. import java.util.HashMap;
  7. import java.util.List;
  8. import java.util.Map;
  9. import javax.servlet.ServletContext;
  10. import javax.servlet.ServletException;
  11. import javax.servlet.http.HttpServlet;
  12. import javax.servlet.http.HttpServletRequest;
  13. import javax.servlet.http.HttpServletResponse;
  14. import net.sf.json.JSONArray;
  15. import net.sf.json.JSONObject;
  16. import org.apache.commons.fileupload.FileItem;
  17. import org.apache.commons.fileupload.disk.DiskFileItemFactory;
  18. import org.apache.commons.fileupload.servlet.ServletFileUpload;
  19. import com.victoria.dao.DaoFactory;
  20. import com.victoria.dao.MediaDao;
  21. import com.victoria.entity.Media;
  22. import com.victoria.manager.MediaManager;
  23. import com.victoria.utils.DateTimeUtil;
  24. /**
  25. *
  26. * MediaService.java
  27. *
  28. * @version : 1.1
  29. *
  30. * @author : 苏若年 <a href="mailto:DennisIT@163.com">发送邮件</a>
  31. *
  32. * @since : 1.0 创建时间: 2013-2-08 下午02:24:47
  33. *
  34. * TODO : class MediaService.java is used for ...
  35. *
  36. */
  37. public class MediaServlet extends HttpServlet {
  38. public void doGet(HttpServletRequest request, HttpServletResponse response)
  39. throws ServletException, IOException {
  40. doPost(request, response);
  41. }
  42. public void doPost(HttpServletRequest request, HttpServletResponse response)
  43. throws ServletException, IOException {
  44. PrintWriter out = response.getWriter();
  45. MediaDao mediaDao = DaoFactory.getMediaDao();
  46. ServletContext sctx = this.getServletContext();
  47. //获得保存文件的路径
  48. String audiosPath = sctx.getRealPath("audios");
  49. String videosPath = sctx.getRealPath("videos");
  50. String dataPath = DateTimeUtil.getYMDFormat();
  51. String savePath = ""; //mp4保存路径
  52. String fileName = ""; //上传的文件名
  53. audiosPath = audiosPath + File.separator + dataPath;
  54. Map<String, String> map = new HashMap<String, String>();
  55. //创建音频保存路径
  56. File audiosFile = new File(audiosPath);
  57. if (!audiosFile.exists()) {
  58. audiosFile.mkdir();
  59. }
  60. //创建视频保存路径
  61. videosPath = videosPath + File.separator + dataPath;
  62. File videosFile = new File(videosPath);
  63. if (!videosFile.exists()) {
  64. videosFile.mkdir();
  65. }
  66. String uri = request.getRequestURI();
  67. String path = uri.substring(uri.lastIndexOf("/"));
  68. if (uri.indexOf(".") != -1) {
  69. path = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
  70. }
  71. //System.out.println("path: "+ System.getProperties().getProperty("os.name"));
  72. if("/uploadFile".equals(path)){
  73. //提供解析时的一些缺省配置
  74. DiskFileItemFactory factory = new DiskFileItemFactory();
  75. //创建一个解析器,分析InputStream,该解析器会将分析的结果封装成一个FileItem对象的集合
  76. //一个FileItem对象对应一个表单域
  77. ServletFileUpload sfu = new ServletFileUpload(factory);
  78. try {
  79. Media media = new Media();
  80. List<FileItem> items = sfu.parseRequest(request);
  81. boolean flag = false; //转码成功与否的标记
  82. for(int i=0; i<items.size(); i++){
  83. FileItem item = items.get(i);
  84. //要区分是上传文件还是普通的表单域
  85. if(!item.isFormField()){//isFormField()为true,表示这不是文件上传表单域
  86. //上传文件
  87. //获得文件名
  88. fileName = item.getName();
  89. System.out.println("---------------上传文件名:"+fileName+"-----------------");
  90. long size = item.getSize();
  91. if((fileName == null || "".equals(fileName)) && size == 0){
  92. continue;
  93. }
  94. fileName = URLDecoder.decode(fileName, "UTF-8");
  95. //System.out.println("上传文件" + item.getName());
  96. //在某些操作系统上,item.getName()方法会返回文件的完整名称,即包括路径
  97. String mp3 = audiosPath + File.separator + DateTimeUtil.getYMDHMS();
  98. String fileType = "";
  99. if (fileName.indexOf(".")!=-1) {
  100. fileType = fileName.substring(fileName.lastIndexOf(".")); //截取文件格式
  101. mp3 += fileType;
  102. }
  103. //待转码的文件
  104. File uploadFile = new File(mp3);
  105. item.write(uploadFile);
  106. System.out.println("--------------mp3:"+mp3+"--------------");
  107. if(item.getSize()>500*1024*1024){
  108. map.put("state", "0");
  109. }
  110. //String mediaPicPath = basePath + "/images" +File.separator+ serialName + ".jpg"; //设置上传视频截图的保存路径
  111. // 获取配置的转换工具(ffmpeg.exe)的存放路径
  112. String ffmpegPath = getServletContext().getRealPath("/tools/ffmpeg.exe");
  113. System.out.println("--------------ffmpegPath:"+ffmpegPath+"--------------");
  114. String[] arr = null;
  115. if (fileName.indexOf(File.separator)!=-1) {
  116. //如果文件名带完整路径 包括 斜杠的。进行截取
  117. String wei = fileName.substring(fileName.lastIndexOf(File.separator)+1, fileName.lastIndexOf("."));
  118. arr = wei.split("-");
  119. media.setImei(wei.substring(0, wei.lastIndexOf("-")));
  120. media.setCid(arr[arr.length-1]);
  121. if ("course1".equals(arr[arr.length-1])){
  122. } else {
  123. }
  124. } else {
  125. //如果文件名是不带路径的
  126. String wei = fileName.substring(0, fileName.lastIndexOf("."));
  127. arr = wei.split("-");
  128. media.setImei(wei.substring(0, wei.lastIndexOf("-")));
  129. media.setCid(arr[arr.length-1]);
  130. System.out.println("imei:"+media.getImei()+"Cid:"+arr[arr.length-1]);
  131. if ("course1".equals(arr[1])){
  132. } else {
  133. }
  134. }
  135. String codcFilePath = videosPath +File.separator+ media.getCid() +"-" + DateTimeUtil.getYMDHMS() + ".mp4";//设置转换为flv格式后文件的保存路径
  136. //用于保存mp4最终路径
  137. savePath = "/videos/" + dataPath + "/" + media.getCid() +"-" +DateTimeUtil.getYMDHMS() + ".mp4";
  138. media.setSrc("/audios/" + dataPath + "/" + DateTimeUtil.getYMDHMS() + fileType);
  139. media.setDest(savePath);
  140. media.setUptime(DateTimeUtil.getYMDHMSFormat());
  141. //转码
  142. ffmpegPath = ffmpegPath.replaceAll("\\\\","/");
  143. codcFilePath = codcFilePath.replaceAll("\\\\","/");
  144. String uploadFilePath = uploadFile.getAbsolutePath().replaceAll("\\\\","/");
  145. flag = mediaDao.executeCodecs(ffmpegPath, uploadFilePath, codcFilePath, media.getCid());
  146. }
  147. }
  148. if(flag){
  149. //转码成功,向数据表中添加该视频信息
  150. //mediaDao.saveMedia(media);
  151. //MediaManager.getInstance().addMedia(media);
  152. map.put("state", "1");
  153. map.put(media.getCid(), savePath);
  154. } else {
  155. map.put("state", "0");
  156. }
  157. //request.setAttribute("message", message);
  158. //request.getRequestDispatcher("media_upload.jsp").forward(request,response);
  159. //response.sendRedirect(request.getContextPath()+ "/index.jsp?success=modify");
  160. } catch (Exception e) {
  161. e.printStackTrace();
  162. map.put("state", "0");
  163. throw new ServletException(e);
  164. } finally {
  165. //response.getOutputStream().write();
  166. response.setCharacterEncoding("UTF-8");
  167. response.getWriter().print(JSONObject.fromObject(map));
  168. }
  169. }
  170. if("/queryAll".equals(path)){
  171. List<Media> mediaList;
  172. try {
  173. mediaList = mediaDao.queryALlMedia(0,5);
  174. request.setAttribute("mediaList", mediaList);
  175. request.getRequestDispatcher("media_list.jsp").forward(request, response);
  176. } catch (Exception e) {
  177. e.printStackTrace();
  178. }
  179. }
  180. if("/play".equals(path)){
  181. String idstr = request.getParameter("id");
  182. int mediaId = -1;
  183. Media media = null;
  184. if(null!=idstr){
  185. mediaId = Integer.parseInt(idstr);
  186. }
  187. try {
  188. media = mediaDao.queryMediaById(mediaId);
  189. } catch (Exception e) {
  190. e.printStackTrace();
  191. }
  192. request.setAttribute("media", media);
  193. request.getRequestDispatcher("media_player.jsp").forward(request, response);
  194. }
  195. }
  196. }
补充代码(在项目中因为语音识别apk不能和系统自带的录音调用接口同时使用,导致 我只能用语音识别apk去生成pcm格式文件):

 

因为pcm格式不能和视频直接合成,需要先转换为amr音频文件或wav文件后,才能和视频合成。代码如下:
  1. //ffmpeg -f s16le -ar 8000 -ac 2 -i out.pcm -ar 44100 -ac 2 out.wav ---- 可用
  2. //ffmpeg -i file.wav -f s16le -acodec pcm_s16le file.pcm ----- 没测
  3. //ffmpeg -f s16le -ar 44.1k -ac 2 -i file.pcm file.wav ----- 没测
  4. // ffmpeg -y -ac 2 -ar 44100 -f s16le -i output.pcm -acodec libmp3lame -ab 128k a.mp3 ----- 不能用
  5. List<String> commend = new ArrayList<String>();
  6. /*commend.add("c:\\ffmpeg\\ffmpeg");
  7. commend.add("-f");
  8. commend.add("s16le");
  9. commend.add("-ar");
  10. commend.add("8000");
  11. commend.add("-ac");
  12. commend.add("2");
  13. commend.add("-i");
  14. commend.add("c:\\ffmpeg\\input\\863925029959719-courseA.pcm");
  15. commend.add("-ar");
  16. commend.add("44100");
  17. commend.add("-ac");
  18. commend.add("2");
  19. commend.add("c:\\ffmpeg\\output\\vvvvvvvvv.wav");*/
  20.  
  21. //ffmpeg -i testwav.wav -ar 8000 -ab 12.2k audio.amr -----不能用
  22. //ffmpeg -i test.wav -acodec libamr_nb -ab 12.2k -ar 8000 -ac 1 wav2amr.amr -----不能用
  23. //ffmpeg.exe -i PA003.wav -ar 8000 -ab 12.2k -ac 1 target.amr 此方法验证通过
  24. commend.add("c:\\ffmpeg\\ffmpeg");
  25. commend.add("-i");
  26. commend.add("c:\\ffmpeg\\output\\vvvvvvvvv.wav");
  27. //commend.add("-acodec");
  28. //commend.add("libamr_nb");
  29. commend.add("-ab");
  30. commend.add("12.2k");
  31. commend.add("-ar");
  32. commend.add("8000");
  33. commend.add("-ac");
  34. commend.add("1");
  35. 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(“800×480”);
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(“800×480”);
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(“800×480”);
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(“800×480”);
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(“800×480”);
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);
        }
    }
 
}
 
 
  1. package com.victoria.dao;
  2. import java.util.List;
  3. import com.victoria.entity.Media;
  4.  
  5. /**
  6. *
  7. * MediaDao.java
  8. *
  9. * @version : 1.1
  10. *
  11. * @author : 苏若年 <a href="mailto:DennisIT@163.com">发送邮件</a>
  12. *
  13. * @since : 1.0 创建时间: 2013-2-07 上午10:19:54
  14. *
  15. * TODO : interface MediaDao.java is used for ...
  16. *
  17. */
  18. public interface MediaDao {
  19. /**
  20. * 视频转码
  21. * @param ffmpegPath 转码工具的存放路径
  22. * @param upFilePath 用于指定要转换格式的文件,要截图的视频源文件
  23. * @param codcFilePath 格式转换后的的文件保存路径
  24. * @param mediaPicPath 截图保存路径
  25. * @return
  26. * @throws Exception
  27. */
  28. public boolean executeCodecs(String ffmpegPath,String upFilePath, String codcFilePath, String cid)throws Exception;
  29. /**
  30. * 保存文件
  31. * @param media
  32. * @return
  33. * @throws Exception
  34. */
  35. public boolean saveMedia(Media media) throws Exception;
  36.  
  37. /**
  38. * 查询本地库中所有记录的数目
  39. * @return
  40. * @throws Exception
  41. */
  42. public int getAllMediaCount()throws Exception;
  43. /**
  44. * 带分页的查询
  45. * @param firstResult
  46. * @param maxResult
  47. * @return
  48. */
  49. public List<Media> queryALlMedia(int firstResult, int maxResult)throws Exception;
  50. /**
  51. * 根据Id查询视频
  52. * @param id
  53. * @return
  54. * @throws Exception
  55. */
  56. public Media queryMediaById(int id)throws Exception;
  57. }

  

———-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(“800×480”);
                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”);
 
 
 
 

版权声明:本文为wangfx原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/wangfx/p/5649016.html