派生自 projectDept/qhighschool

EricsHu
2022-12-05 068fc7f2e81178e55fa191a13709af64b1a163f6
src/main/java/com/qxueyou/scc/teach/live/utils/FfmpegMediaHelper.java
@@ -16,44 +16,44 @@
import com.qxueyou.scc.teach.live.utils.FfmpegVideoInfo;
/**
 * 视频转码类
 * 视频转码类
 * @author cyq
 *
 */
public class FfmpegMediaHelper {
   /**
    * 实例化log
    * 实例化log
    */
   private static final Logger log = LogManager.getLogger(FfmpegMediaHelper.class);
   /**
    * 高清码率
    * 高清码率
    */
   private static int bitRateHd = 800 * 1024;
   /**
    * 标清码率
    * 标清码率
    */
   private static int bitRateSd = 400 * 1024;
   /**
    * 低清码率
    * 低清码率
    */
   private static int bitRateLd = 200 * 1024;
   /**
    * 转mp4的固定命令
    * 转mp4的固定命令
    */
   private static List<String> commandMp4 = new ArrayList<String>(10);
   /**
    * 转m3u8的固定命令
    * 转m3u8的固定命令
    */
   private static String commandM3u8;
   /**
    * 是否为视频
    * 是否为视频
    */
   private static Boolean videoFlag = false;
   /**
    * תmp4
    * 转mp4
    * @param fileVO
    * @param videoInfo
    * @return
@@ -63,12 +63,12 @@
         return false;
      }
      try {
         System.out.println("FfmpegMediaHelper--转码mp4中...");
         System.out.println("FfmpegMediaHelper--转码mp4中...");
         commandMp4.clear();
         commandMp4.add("ffmpeg");
         commandMp4.add("-i");
         commandMp4.add(fileVO.getInputPath());
         commandMp4.add("-ab");      // 设置音频码率
         commandMp4.add("-ab");      // 设置音频码率
         commandMp4.add("128*1024");
         commandMp4.add("-r");
         commandMp4.add("23");
@@ -83,16 +83,16 @@
         } else {
            convertMp4Ld(fileVO, videoInfo);
         }
         System.out.println("FfmpegMediaHelper--转码mp4完成...");
         System.out.println("FfmpegMediaHelper--转码mp4完成...");
         return true;
      } catch (Exception e) {
         System.out.println("FfmpegMediaHelper--转码mp4异常...");
         log.error("转码mp4异常:" + e.getMessage());
         System.out.println("FfmpegMediaHelper--转码mp4异常...");
         log.error("转码mp4异常:" + e.getMessage());
         throw e;
      }
   }
   /**
    * תm3u8
    * 转m3u8
    * @param fileVO
    * @param videoInfo
    * @return
@@ -102,7 +102,7 @@
         return false;
      }
      try {
         System.out.println("FfmpegMediaHelper--转码m3h8中...");
         System.out.println("FfmpegMediaHelper--转码m3h8中...");
         commandM3u8 = "ffmpeg -i " + fileVO.getInputPath() + " -strict -2 -c:v libx264 -c:a aac -f hls -hls_time 10 -hls_list_size 0";
   
         if (videoInfo.getVideoHeight() >= 1000) {
@@ -115,41 +115,41 @@
         } else {
            convertM3u8Ld(fileVO, videoInfo);
         }
         System.out.println("FfmpegMediaHelper--转码m3u8完成...");
         System.out.println("FfmpegMediaHelper--转码m3u8完成...");
         return true;
      } catch (Exception e) {
         System.out.println("FfmpegMediaHelper--转码m3u8异常...");
         log.error("转码m3u8异常:" + e.getMessage());
         System.out.println("FfmpegMediaHelper--转码m3u8异常...");
         log.error("转码m3u8异常:" + e.getMessage());
         throw e;
      }
   }
   
   /**
    * 转高清mp4
    * 转高清mp4
    */
   private static void convertMp4Hd(FfmpegFileVO fileVO, FfmpegVideoInfo videoInfo) throws Exception {
      try {
         String resolution = (int) (1080 * videoInfo.getAspectRatio() / 2) * 2 + "*1080"; // 宽高必须是偶数
         String resolution = (int) (1080 * videoInfo.getAspectRatio() / 2) * 2 + "*1080"; // 宽高必须是偶数
         List<String> command = new ArrayList<String>(commandMp4);
         if (videoInfo.getVideoBitRate() == null || videoInfo.getVideoBitRate() > bitRateHd) {
            command.add("-vb"); // 视频码率
            command.add("-vb"); // 视频码率
            command.add(String.valueOf(bitRateHd));
         }
         command.add("-s"); // 尺寸(分辨率)
         command.add("-s"); // 尺寸(分辨率)
         command.add(resolution);
         command.add(fileVO.getOutputPath() + videoInfo.getUuid() + "mp4-hd.mp4");
         convertMp4(command);
         videoInfo.setMp4HdUrl(fileVO.getOutputPath() + videoInfo.getUuid() + "mp4-hd.mp4");   // 转码成功,将路径设置到videoInfo中
         videoInfo.setMp4HdUrl(fileVO.getOutputPath() + videoInfo.getUuid() + "mp4-hd.mp4");   // 转码成功,将路径设置到videoInfo中
      } catch (Exception e) {
         throw e;
      }
   }
   /**
    * 转高清m3u8
    * 转高清m3u8
    */
   private static void convertM3u8Hd(FfmpegFileVO fileVO, FfmpegVideoInfo videoInfo) throws Exception {
      try {
         String resolution = (int) (1080 * videoInfo.getAspectRatio() / 2) * 2 + "*1080"; // 宽高必须是偶数
         String resolution = (int) (1080 * videoInfo.getAspectRatio() / 2) * 2 + "*1080"; // 宽高必须是偶数
         
         StringBuffer commandBuffer = new StringBuffer(commandM3u8);
         if (videoInfo.getVideoBitRate() == null || videoInfo.getVideoBitRate() > bitRateHd) {
@@ -166,7 +166,7 @@
   }
   
   /**
    * 转标清mp4
    * 转标清mp4
    */
   private static void convertMp4Sd(FfmpegFileVO fileVO, FfmpegVideoInfo videoInfo) throws Exception {
      try {
@@ -186,7 +186,7 @@
      }
   }
   /**
    * 转标清m3u8
    * 转标清m3u8
    */
   private static void convertM3u8Sd(FfmpegFileVO fileVO, FfmpegVideoInfo videoInfo) throws Exception {
      try {
@@ -205,7 +205,7 @@
   }
   /**
    * 转低清mp4
    * 转低清mp4
    */
   private static void convertMp4Ld(FfmpegFileVO fileVO, FfmpegVideoInfo videoInfo) throws Exception {
      try   {
@@ -225,7 +225,7 @@
      }
   }
   /**
    * 转低清m3u8
    * 转低清m3u8
    */
   private static void convertM3u8Ld(FfmpegFileVO fileVO, FfmpegVideoInfo videoInfo) throws Exception {
      try {
@@ -244,7 +244,7 @@
   }
   /**
    * 获取媒体信息
    * 获取媒体信息
    * 
    * @param fileVO
    * @param videoInfo
@@ -254,19 +254,19 @@
      if (!checkfile(fileVO.getInputPath())) {
         return false;
      }
      BufferedReader buf = null; // 保存ffmpeg的输出结果流
      BufferedReader buf = null; // 保存ffmpeg的输出结果流
      String currLine = null;
      String line = null;
      try {
         log.debug("获取媒体信息...");
         log.debug("获取媒体信息...");
         List<String> command = new ArrayList<String>();
         // ffprobe 命令获取媒体信息
         // ffprobe 命令获取媒体信息
         command.add("ffprobe");
         command.add("-print_format");
         // json格式输出
         // json格式输出
         command.add("json");
         command.add("-show_streams");
@@ -279,11 +279,11 @@
         buf = new BufferedReader(new InputStreamReader(p.getInputStream()));
         while ((currLine = buf.readLine()) != null) {
            // 处理多余字符
            // 处理多余字符
            line = currLine.trim().replaceAll("\"", "").replaceAll(",", "").replace(" ", "");
            handleLine(line, videoInfo);
            // 获取文件时长(flv需要这么取)
            // 获取文件时长(flv需要这么取)
              if(currLine.trim().startsWith("Duration:") && currLine.contains(",") ){
                 String strFirst = currLine.trim().split(",")[0].substring(9).trim().substring(0,8);
                 String[] arrTime = strFirst.split(":");
@@ -293,18 +293,18 @@
                    Integer iSecond = Integer.parseInt(arrTime[2]);
                    
                    videoInfo.setPlayTime(iHour * 60 * 60 + iMinute * 60 + iSecond);
                    log.debug("视频时长:" + videoInfo.getPlayTime());
                    log.debug("视频时长:" + videoInfo.getPlayTime());
                 }
              }
         }
         p.waitFor();// 这里线程阻塞,将等待外部转换进程运行成功运行结束后,才往下执行
         p.waitFor();// 这里线程阻塞,将等待外部转换进程运行成功运行结束后,才往下执行
         log.debug("获取媒体信息完成");
         log.debug("获取媒体信息完成");
         return true;
      } catch (Exception e) {
         log.debug("获取媒体信息异常:" + e.getMessage());
         log.debug("获取媒体信息异常:" + e.getMessage());
         throw e;
      }
   }
@@ -312,55 +312,55 @@
      if (line.contains(":")) {
         String[] arr = line.split(":");
         if (null != arr && arr.length == 2) {
            // 1. 如果是标志位
            // 1. 如果是标志位
            if ("codec_type".equals(arr[0].trim())) {
               // 视频
               // 视频
               if ("video".equals(arr[1].trim())) {
                  videoFlag = true;
               }
               // 音频
               // 音频
               if ("audio".equals(arr[1].trim())) {
                  videoFlag = false;
               }
            }
            // 视频宽度
            // 视频宽度
            if (videoFlag && "width".equals(arr[0])) {
               videoInfo.setVideoWidth(Integer.valueOf(arr[1]));
               if (videoInfo.getVideoHeight() != null) {
                  videoInfo.setAspectRatio((float) (videoInfo.getVideoWidth().floatValue() / videoInfo.getVideoHeight().floatValue()));
                  log.debug("计算宽高比:" + videoInfo.getVideoWidth() + "/" + videoInfo.getVideoHeight() + ":" + videoInfo.getAspectRatio());
                  log.debug("计算宽高比:" + videoInfo.getVideoWidth() + "/" + videoInfo.getVideoHeight() + ":" + videoInfo.getAspectRatio());
               }
            }
            // 视频高度
            // 视频高度
            if (videoFlag && "height".equals(arr[0])) {
               videoInfo.setVideoHeight(Integer.valueOf(arr[1]));
               if (videoInfo.getVideoWidth() != null) {
                  videoInfo.setAspectRatio((float) (videoInfo.getVideoWidth().floatValue() / videoInfo.getVideoHeight().floatValue()));
                  log.debug("计算宽高比:" + videoInfo.getVideoWidth() + "/" + videoInfo.getVideoHeight() + ":" + videoInfo.getAspectRatio());
                  log.debug("计算宽高比:" + videoInfo.getVideoWidth() + "/" + videoInfo.getVideoHeight() + ":" + videoInfo.getAspectRatio());
               }
            }
            
            //获取视屏帧率表达式
            //获取视屏帧率表达式
            if (videoFlag && "avg_frame_rate".equals(arr[0])) {
               log.info("开始计算帧率,"+arr[1]);
               log.info("开始计算帧率,"+arr[1]);
               if(StringUtils.isNotEmpty(arr[1])){
                  String [] strFrameArr = arr[1].split("/");
                  if(strFrameArr!=null && strFrameArr.length==2 && Double.valueOf(strFrameArr[1].trim())>0){
                     int frameRate = (int) Math.ceil((Double.valueOf(strFrameArr[0].trim())/Double.valueOf(strFrameArr[1].trim())));
                     videoInfo.setFrameRate(frameRate);   
                     videoInfo.setFrameRateExp(arr[1]);
                     log.info("计算帧率:frameRate="+frameRate+" frameRateExp="+arr[1]);
                     log.info("计算帧率:frameRate="+frameRate+" frameRateExp="+arr[1]);
                  }
               }
            }
            
            
            // 视频码率
            // 视频码率
            if (videoFlag && "bit_rate".equals(arr[0])) {
               videoInfo.setVideoBitRate(Integer.valueOf(arr[1]));
               log.debug("视频码率:" + videoInfo.getVideoBitRate());
               log.debug("视频码率:" + videoInfo.getVideoBitRate());
            }
            // 文件时长
            // 文件时长
            if (videoFlag && "duration".equals(arr[0])) {
               if (arr[1].contains(".")) {
                  //videoInfo.setPlayTime(Integer.valueOf(arr[1].indexOf('.')));
@@ -368,7 +368,7 @@
               } else {
                  videoInfo.setPlayTime(Integer.valueOf(arr[1]));
               }
               log.debug("视频时长:" + videoInfo.getPlayTime());
               log.debug("视频时长:" + videoInfo.getPlayTime());
            }
         }
      }
@@ -376,7 +376,7 @@
   /**
    * 截图
    * 截图
    * 
    * @param fileVO
    * @param outputPath
@@ -388,37 +388,37 @@
      }
      try {
         log.debug("FfmpegMediaHelper--视频截屏...");
         log.debug("FfmpegMediaHelper--视频截屏...");
         String comm = "ffmpeg -ss 00:00:01 -i " + fileVO.getInputPath() + " -t 0.1 -f mjpeg -y " + fileVO.getOutputPath() + "snapshot.jpg";
   
         Process videoProcess = Runtime.getRuntime().exec(comm);
         new PrintStreamThread(videoProcess.getErrorStream()).start();
   
         videoProcess.waitFor();
         log.debug("FfmpegMediaHelper--视频截屏完成");
         log.debug("FfmpegMediaHelper--视频截屏完成");
         return true;
      } catch (Exception e) {
         log.error("视频截屏异常" + e.getMessage());
         log.error("视频截屏异常" + e.getMessage());
         throw e;
      }
   }
   
   /**
    * 根据帧率截屏
    * @param fileVO 待截图视频文件信息
    * @param imgPrefixName 截取图片名称的前缀信息
    * @param framePerSecond 每秒图片帧数
    * @param width  截取图片宽度(ps:单位像素点)
    * @param height 截取图片高度(ps:单位像素点)
    * @return 是否截取成功
    * 根据帧率截屏
    * @param fileVO 待截图视频文件信息
    * @param imgPrefixName 截取图片名称的前缀信息
    * @param framePerSecond 每秒图片帧数
    * @param width  截取图片宽度(ps:单位像素点)
    * @param height 截取图片高度(ps:单位像素点)
    * @return 是否截取成功
    * @throws Exception
    */
   
   /**
    * 
    * @param fileVO  文件信息
    * @param imgPrefixName  截取图片的前缀信息
    * @param framePerSecond  每秒多少帧
    * @param fileVO  文件信息
    * @param imgPrefixName  截取图片的前缀信息
    * @param framePerSecond  每秒多少帧
    * @return
    * @throws Exception
    */
@@ -438,13 +438,13 @@
//         ffmpeg  -ss 00:00:00.000  -i D:/usr/qxueyou/huifang/test.mp4 -f image2 -vf fps=fps=1/5 D:/usr/qxueyou/huifang/pic/new_%d.jpg
         
         String comm = "ffmpeg -ss 00:00:00.000 -i " + fileVO.getInputPath() + " -f image2 -s " + width + "*" + height + " -vf fps=fps=1/"+ framePerSecond +" "+ fileVO.getOutputPath()+"/" + imgPrefixName + "%d.jpg";
         log.info("screenShot命令, "+ comm);
         log.info("screenShot命令, "+ comm);
         process = Runtime.getRuntime().exec(comm);
         new PrintStreamThread(process.getErrorStream()).start();
         process.waitFor();
         return true;
      } catch (Exception e) {
         log.error("视频截屏异常" + e.getMessage());
         log.error("视频截屏异常" + e.getMessage());
         throw e;
      }finally {
         closeProcess(process);
@@ -461,13 +461,13 @@
      Process process = null;
      try {
         String comm = "ffmpeg -ss "+ statTime + " -t " + duration + " -i "+ fileVO.getInputPath() + " -y -vcodec copy -acodec copy " + fileVO.getOutputPath();
         log.info("dividVideo命令, "+ comm);
         log.info("dividVideo命令, "+ comm);
         process = Runtime.getRuntime().exec(comm);
         new PrintStreamThread(process.getErrorStream()).start();
         process.waitFor();
         return true;
      } catch (Exception e) {
         log.error("切割视频失败" + e.getMessage());
         log.error("切割视频失败" + e.getMessage());
         throw e;
      }finally {
         closeProcess(process);
@@ -477,7 +477,7 @@
   
   
   /**
    * 合并视频
    * 合并视频
    * 
    * @param fileVO
    * @return
@@ -489,7 +489,7 @@
      }
      
      String comm = "ffmpeg -f concat -safe 0 -i " + fileVO.getInputPath() + " -c copy " + fileVO.getOutputPath();
      log.info("mergeVideo命令, "+ comm);
      log.info("mergeVideo命令, "+ comm);
      
      Process videoProcess = Runtime.getRuntime().exec(comm);
      new PrintStreamThread(videoProcess.getErrorStream()).start();
@@ -501,7 +501,7 @@
   
   
   /**
    * 合并视频
    * 合并视频
    * 
    * @param fileVO
    * @return
@@ -544,7 +544,7 @@
   public static String converUploadVideoToLiveMp4(FfmpegFileVO fileVO,FfmpegVideoInfo videoInfo) throws Exception{
      String outputPath = null;
      try {
//         log.info("FfmpegMediaHelper.TransferUploadVideoToWyMp4,直播上传...");
//         log.info("FfmpegMediaHelper.TransferUploadVideoToWyMp4,直播上传...");
         List<String> command = new ArrayList<String>();
         String name = UUIDUtils.generateUUID().replace("-", "");
         outputPath = fileVO.getOutputPath() +name + ".mp4";
@@ -567,7 +567,7 @@
    }
   
   /**
    * mp4转ts文件
    * mp4转ts文件
    * ffmpeg -i 1.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts out1.ts
    * 
    * @param fileVO
@@ -578,7 +578,7 @@
      Process process= null;
      try {
         String comm = "ffmpeg -i " + fileVO.getInputPath() + " -c copy -bsf:v h264_mp4toannexb -y -f mpegts " + fileVO.getOutputPath();
         log.info("mp4toannexb命令, "+ comm);
         log.info("mp4toannexb命令, "+ comm);
         process = Runtime.getRuntime().exec(comm);
         new PrintStreamThread(process.getErrorStream()).start();
         process.waitFor();
@@ -605,13 +605,13 @@
            process.destroy();
         }
      } catch (IOException e) {
         log.error("关闭process失败。。", e);
         log.error("关闭process失败。。", e);
      }
   }
   
   /**
    * 关闭进程
    * 关闭进程
    * 
    * @param process
    * @return
@@ -625,7 +625,7 @@
    } 
   /**
    * 解析成MP4格式
    * 解析成MP4格式
    * 
    * @param oldfilepath
    * @return
@@ -653,7 +653,7 @@
   }
   /**
    * 解析m3u8格式
    * 解析m3u8格式
    * 
    * @param oldfilepath
    * @return
@@ -684,7 +684,7 @@
   }
   
   /**
     * 检查转码输入文件是否存在
     * 检查转码输入文件是否存在
     * @param path
     * @return
     */
@@ -694,18 +694,18 @@
    }
}
/**
 * 打印线程
 * 打印线程
 * @author cyq
 *
 */
class PrintStreamThread extends Thread {
   /**
    * 输入流
    * 输入流
    */
   java.io.InputStream __is;
   /**
    * 构造方法
    * 构造方法
    * @param is
    */
   public PrintStreamThread(java.io.InputStream is) {
@@ -713,7 +713,7 @@
   }
   /**
    * 线程执行方法
    * 线程执行方法
    */
   public void run() {
      try {