MediaFilePreviewImpl.java 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. package cn.keking.service.impl;
  2. import cn.keking.config.ConfigConstants;
  3. import cn.keking.model.FileAttribute;
  4. import cn.keking.model.FileType;
  5. import cn.keking.model.ReturnResponse;
  6. import cn.keking.service.FileHandlerService;
  7. import cn.keking.service.FilePreview;
  8. import cn.keking.utils.DownloadUtils;
  9. import org.bytedeco.ffmpeg.global.avcodec;
  10. import org.bytedeco.javacv.FFmpegFrameGrabber;
  11. import org.bytedeco.javacv.FFmpegFrameRecorder;
  12. import org.bytedeco.javacv.Frame;
  13. import org.springframework.stereotype.Service;
  14. import org.springframework.ui.Model;
  15. import org.springframework.util.ObjectUtils;
  16. import java.io.File;
  17. /**
  18. * @author : kl
  19. * @authorboke : kailing.pub
  20. * @create : 2018-03-25 上午11:58
  21. * @description:
  22. **/
  23. @Service
  24. public class MediaFilePreviewImpl implements FilePreview {
  25. private final FileHandlerService fileHandlerService;
  26. private final OtherFilePreviewImpl otherFilePreview;
  27. private static final String mp4 = "mp4";
  28. public MediaFilePreviewImpl(FileHandlerService fileHandlerService, OtherFilePreviewImpl otherFilePreview) {
  29. this.fileHandlerService = fileHandlerService;
  30. this.otherFilePreview = otherFilePreview;
  31. }
  32. @Override
  33. public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
  34. String fileName = fileAttribute.getName();
  35. String suffix = fileAttribute.getSuffix();
  36. String cacheName = fileAttribute.getcacheName();
  37. String outFilePath = fileAttribute.getoutFilePath();
  38. boolean forceUpdatedCache=fileAttribute.forceUpdatedCache();
  39. String fileKey = fileAttribute.getFileKey();
  40. FileType type = fileAttribute.getType();
  41. String[] mediaTypesConvert = FileType.MEDIACONVERT_TYPES_CONVERT; //获取支持的转换格式
  42. boolean mediaTypes = false;
  43. for(String temp : mediaTypesConvert){
  44. if (suffix.equals(temp)) {
  45. mediaTypes = true;
  46. break;
  47. }
  48. }
  49. if(!url.toLowerCase().startsWith("http") || checkNeedConvert(mediaTypes)){ //不是http协议的 // 开启转换方式并是支持转换格式的
  50. if (forceUpdatedCache || !fileHandlerService.listConvertedFiles().containsKey(cacheName) || !ConfigConstants.isCacheEnabled()) { //查询是否开启缓存
  51. ReturnResponse<String> response = DownloadUtils.downLoad(fileAttribute, fileName);
  52. if (response.isFailure()) {
  53. return otherFilePreview.notSupportedFile(model, fileAttribute, response.getMsg());
  54. }
  55. String filePath = response.getContent();
  56. String convertedUrl = null;
  57. try {
  58. if(mediaTypes){
  59. convertedUrl=convertToMp4(filePath,outFilePath,fileKey);
  60. }else {
  61. convertedUrl =outFilePath; //其他协议的 不需要转换方式的文件 直接输出
  62. }
  63. } catch (Exception e) {
  64. e.printStackTrace();
  65. }
  66. if (convertedUrl == null ) {
  67. return otherFilePreview.notSupportedFile(model, fileAttribute, "视频转换异常,请联系管理员");
  68. }
  69. if (ConfigConstants.isCacheEnabled()) {
  70. // 加入缓存
  71. fileHandlerService.addConvertedFile(cacheName, fileHandlerService.getRelativePath(outFilePath));
  72. }
  73. model.addAttribute("mediaUrl", fileHandlerService.getRelativePath(outFilePath));
  74. }else{
  75. model.addAttribute("mediaUrl", fileHandlerService.listConvertedFiles().get(cacheName));
  76. }
  77. return MEDIA_FILE_PREVIEW_PAGE;
  78. }
  79. if(type.equals(FileType.MEDIA)){ // 支持输出 只限默认格式
  80. model.addAttribute("mediaUrl", url);
  81. return MEDIA_FILE_PREVIEW_PAGE;
  82. }
  83. return otherFilePreview.notSupportedFile(model, fileAttribute, "系统还不支持该格式文件的在线预览");
  84. }
  85. /**
  86. * 检查视频文件转换是否已开启,以及当前文件是否需要转换
  87. * @return
  88. */
  89. private boolean checkNeedConvert(boolean mediaTypes) {
  90. //1.检查开关是否开启
  91. if("true".equals(ConfigConstants.getMediaConvertDisable())){
  92. return mediaTypes;
  93. }
  94. return false;
  95. }
  96. private static String convertToMp4(String filePath,String outFilePath,String fileKey)throws Exception {
  97. FFmpegFrameGrabber frameGrabber = FFmpegFrameGrabber.createDefault(filePath);
  98. Frame captured_frame;
  99. FFmpegFrameRecorder recorder = null;
  100. try {
  101. File desFile=new File(outFilePath);
  102. //判断一下防止重复转换
  103. if(desFile.exists()){
  104. return outFilePath;
  105. }
  106. if (!ObjectUtils.isEmpty(fileKey)) { //判断 是压缩包的创建新的目录
  107. int index = outFilePath.lastIndexOf("/"); //截取最后一个斜杠的前面的内容
  108. String folder = outFilePath.substring(0, index);
  109. File path = new File(folder);
  110. //目录不存在 创建新的目录
  111. if (!path.exists()) {
  112. path.mkdirs();
  113. }
  114. }
  115. frameGrabber.start();
  116. recorder = new FFmpegFrameRecorder(outFilePath, frameGrabber.getImageWidth(), frameGrabber.getImageHeight(), frameGrabber.getAudioChannels());
  117. // recorder.setImageHeight(640);
  118. // recorder.setImageWidth(480);
  119. recorder.setFormat(mp4);
  120. recorder.setFrameRate(frameGrabber.getFrameRate());
  121. recorder.setSampleRate(frameGrabber.getSampleRate());
  122. //视频编码属性配置 H.264 H.265 MPEG
  123. recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
  124. //设置视频比特率,单位:b
  125. recorder.setVideoBitrate(frameGrabber.getVideoBitrate());
  126. recorder.setAspectRatio(frameGrabber.getAspectRatio());
  127. // 设置音频通用编码格式
  128. recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
  129. //设置音频比特率,单位:b (比特率越高,清晰度/音质越好,当然文件也就越大 128000 = 182kb)
  130. recorder.setAudioBitrate(frameGrabber.getAudioBitrate());
  131. recorder.setAudioOptions(frameGrabber.getAudioOptions());
  132. recorder.setAudioChannels(frameGrabber.getAudioChannels());
  133. recorder.start();
  134. while (true) {
  135. captured_frame = frameGrabber.grabFrame();
  136. if (captured_frame == null) {
  137. System.out.println("转码完成:"+filePath);
  138. break;
  139. }
  140. recorder.record(captured_frame);
  141. }
  142. } catch (Exception e) {
  143. e.printStackTrace();
  144. return null;
  145. }finally {
  146. if (recorder != null) { //关闭
  147. recorder.stop();
  148. recorder.close();
  149. }
  150. frameGrabber.stop();
  151. frameGrabber.close();
  152. }
  153. return outFilePath;
  154. }
  155. }