调整代码

This commit is contained in:
wanggeng888 2021-06-10 18:16:59 +08:00
parent 0a05388483
commit 65c596c808
6 changed files with 229 additions and 18 deletions

View File

@ -4,6 +4,7 @@ import ink.wgink.module.file.media.manager.domain.ImageMetaInfo;
import ink.wgink.module.file.media.manager.domain.MusicMetaInfo;
import ink.wgink.module.file.media.manager.domain.VideoMetaInfo;
import ink.wgink.module.file.media.manager.domain.gif.AnimatedGifEncoder;
import ink.wgink.module.file.media.manager.process.IMediaStream;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
@ -98,7 +99,8 @@ public class MediaManager {
musicStreamPattern = Pattern.compile(musicStreamRegex);
}
private MediaManager() {}
private MediaManager() {
}
public static MediaManager getInstance() {
return MEDIA_MANAGER;
@ -156,7 +158,6 @@ public class MediaManager {
return true;
}
/**
* 执行FFmpeg命令
*
@ -212,21 +213,69 @@ public class MediaManager {
}
}
/**
* 执行命令
*
* @param commonds
* @param mediaStream
* @return
*/
public void executeCommand(List<String> commonds, IMediaStream mediaStream) {
if (CollectionUtils.isEmpty(commonds)) {
LOG.error("--- 指令执行失败因为要执行的FFmpeg指令为空 ---");
return;
}
LinkedList<String> ffmpegCmds = new LinkedList<>(commonds);
ffmpegCmds.addFirst(FFMPEG_PATH);
LOG.info("--- 待执行的FFmpeg指令为---" + ffmpegCmds);
Runtime runtime = Runtime.getRuntime();
Process ffmpeg = null;
try {
// 执行ffmpeg指令
ProcessBuilder builder = new ProcessBuilder();
builder.command(ffmpegCmds);
ffmpeg = builder.start();
LOG.info("--- 开始执行FFmpeg指令--- 执行线程名:" + builder.toString());
// 取出输出流和错误流的信息
// 注意必须要取出ffmpeg在执行命令过程中产生的输出信息如果不取的话当输出流信息填满jvm存储输出留信息的缓冲区时线程就回阻塞住
mediaStream.error(ffmpeg.getErrorStream());
mediaStream.input(ffmpeg.getInputStream());
} catch (Exception e) {
LOG.error("--- FFmpeg命令执行出错 --- 出错信息: " + e.getMessage());
} finally {
if (null != ffmpeg) {
ProcessKiller ffmpegKiller = new ProcessKiller(ffmpeg);
// JVM退出时先通过钩子关闭FFmepg进程
runtime.addShutdownHook(ffmpegKiller);
}
}
}
/**
* 视频转换
* <p>
* 注意指定视频分辨率时宽度和高度必须同时有值
*
* @param fileInput 源视频路径
* @param fileOutPut 转换后的视频输出路径
* @param withAudio 是否保留音频true-保留false-不保留
* @param crf 指定视频的质量系数值越小视频质量越高体积越大该系数取值为0-51直接影响视频码率大小,取值参考CrfValueEnum.code
* @param preset 指定视频的编码速率速率越快压缩率越低取值参考PresetVauleEnum.presetValue
* @param width 视频宽度为空则保持源视频宽度
* @param height 视频高度为空则保持源视频高度
* @param fileInput 源视频路径
* @param fileOutPut 转换后的视频输出路径
* @param withAudio 是否保留音频true-保留false-不保留
* @param crf 指定视频的质量系数值越小视频质量越高体积越大该系数取值为0-51直接影响视频码率大小,取值参考CrfValueEnum.code
* @param preset 指定视频的编码速率速率越快压缩率越低取值参考PresetVauleEnum.presetValue
* @param width 视频宽度为空则保持源视频宽度
* @param height 视频高度为空则保持源视频高度
* @param mediaStream 媒体流处理转码的过程中产生的流信息
* @return 转换结果
*/
public void convertVideo(File fileInput, File fileOutPut, boolean withAudio, Integer crf, String preset, Integer width, Integer height) {
public void convertVideo(File fileInput,
File fileOutPut,
boolean withAudio,
Integer crf,
String preset,
Integer width,
Integer height,
IMediaStream mediaStream) {
if (null == fileInput || !fileInput.exists()) {
throw new RuntimeException("源视频文件不存在,请检查源视频路径");
}
@ -268,10 +317,13 @@ public class MediaManager {
commond.add("-y"); // 当已存在输出文件时不提示是否覆盖
commond.add(fileOutPut.getAbsolutePath());
executeCommand(commond);
if (mediaStream == null) {
executeCommand(commond);
return;
}
executeCommand(commond, mediaStream);
}
/**
* 视频帧抽取
* 默认抽取第10秒的帧画面
@ -932,7 +984,7 @@ public class MediaManager {
}
}
public static class MediaManagerBuilder {
private static class MediaManagerBuilder {
static MediaManager mediaManager = new MediaManager();
}

View File

@ -0,0 +1,24 @@
package ink.wgink.module.file.media.manager.process;
import ink.wgink.module.file.media.manager.MediaManager;
import java.io.InputStream;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: MediaProcess
* @Description: 媒体流
* @Author: wanggeng
* @Date: 2021/6/10 10:52 上午
* @Version: 1.0
*/
public interface IMediaStream {
void input(InputStream inputStream) throws Exception;
void error(InputStream errorStream) throws Exception;
}

View File

@ -58,17 +58,17 @@ public class VideoServiceImpl extends DefaultBaseService implements IVideoServic
long fileSize = video.getSize();
String fileType = mediaService.getFileType(fileName);
String fileMd5 = mediaService.upload(video, filePath, fileName);
String fileFullPath = filePath + File.separator + fileName;
String fileFullPath = filePath;
// 构建视频内容
VideoVO videoVO = new VideoVO();
videoVO.setFileName(fileName);
videoVO.setFileFullPath(fileFullPath);
videoVO.setFilePath(VIDEO_PATH + File.separator + fileName);
videoVO.setFilePath(VIDEO_PATH);
videoVO.setFileSize(fileSize);
videoVO.setFileType(fileType);
videoVO.setFileMd5(fileMd5);
File uploadFile = new File(fileFullPath);
File uploadFile = new File(fileFullPath + File.separator + fileName);
VideoMetaInfo videoMetaInfo = MediaManager.getInstance().getVideoMetaInfo(uploadFile);
if (videoMetaInfo == null) {
throw new FileException("上传失败");
@ -86,8 +86,9 @@ public class VideoServiceImpl extends DefaultBaseService implements IVideoServic
videoVO.setAudioBitRate(musicMetaInfo.getBitRate());
videoVO.setAudioSampleRate(musicMetaInfo.getSampleRate());
}
return save(token, videoVO);
String fileId = save(token, videoVO);
// 转码
return fileId;
}
}

View File

@ -0,0 +1,31 @@
package ink.wgink.module.file.media.task.transcoding;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: VideoTransCodingManager
* @Description: 视频转码
* @Author: wanggeng
* @Date: 2021/6/10 9:46 上午
* @Version: 1.0
*/
public class VideoTransCodingManager {
private static VideoTransCodingManager VIDEO_TRANS_CODING_MANAGER = VideoTransCodingManagerBuilder.videoTransCodingManager;
private ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 10, 30L, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
private VideoTransCodingManager() {}
private static class VideoTransCodingManagerBuilder {
public static VideoTransCodingManager videoTransCodingManager = new VideoTransCodingManager();
}
}

View File

@ -0,0 +1,53 @@
package ink.wgink.module.file.media.task.transcoding.runnable;
import ink.wgink.module.file.media.manager.MediaManager;
import ink.wgink.module.file.media.manager.domain.enums.CrfValueEnum;
import ink.wgink.module.file.media.manager.domain.enums.PresetVauleEnum;
import ink.wgink.module.file.media.manager.process.IMediaStream;
import ink.wgink.module.file.media.service.video.IVideoService;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* When you feel like quitting. Think about why you started
* 当你想要放弃的时候想想当初你为何开始
*
* @ClassName: VideoTransCodingRunnable
* @Description: 视频转码
* @Author: wanggeng
* @Date: 2021/6/10 10:04 上午
* @Version: 1.0
*/
public class VideoTransCodingRunnable implements Runnable {
private String sourcePath;
private String sourceName;
private IVideoService videoService;
@Override
public void run() {
File sourceFile = new File(sourcePath + File.separator + sourceName);
File outFile = new File(sourcePath + File.separator + sourceName + ".mp4");
MediaManager.getInstance().convertVideo(sourceFile, outFile, true, CrfValueEnum.HIGH_QUALITY.getCode(), PresetVauleEnum.MAX_FAST_ZIP_SPEED.getPresetValue(), null, null, new IMediaStream() {
@Override
public void input(InputStream inputStream) throws Exception {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
for (String line; (line = bufferedReader.readLine()) != null; ) {
System.out.println("input-" + line);
}
}
@Override
public void error(InputStream errorStream) throws Exception {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(errorStream));
for (String line; (line = bufferedReader.readLine()) != null; ) {
System.out.println("error-" + line);
}
}
});
}
}

View File

@ -1,10 +1,16 @@
import ink.wgink.module.file.media.manager.MediaManager;
import ink.wgink.module.file.media.manager.domain.VideoMetaInfo;
import ink.wgink.module.file.media.manager.domain.enums.CrfValueEnum;
import ink.wgink.module.file.media.manager.domain.enums.PresetVauleEnum;
import ink.wgink.module.file.media.manager.process.IMediaStream;
import org.junit.Test;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* When you feel like quitting. Think about why you started
@ -44,5 +50,49 @@ public class MediaTest {
process.destroy();
}
@Test
public void t3() {
MediaManager.getInstance().setFFmpegPath("/Users/wanggeng/ffmpeg/ffmpeg");
String sourcePath = "/Users/wanggeng/Desktop/UploadFiles/videos/20210119";
String sourceName = "85355a761e3442cda765c3bc6f5bd526.mp4";
File sourceFile = new File(sourcePath + File.separator + sourceName);
File outFile = new File(sourcePath + File.separator + sourceName + ".mp4");
MediaManager.getInstance().convertVideo(sourceFile, outFile, true, CrfValueEnum.LOW_QUALITY.getCode(), PresetVauleEnum.MAX_FAST_ZIP_SPEED.getPresetValue(), null, null, new IMediaStream() {
@Override
public void input(InputStream inputStream) throws Exception {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
for (String line; (line = bufferedReader.readLine()) != null; ) {
System.out.println(line);
}
}
@Override
public void error(InputStream errorStream) throws Exception {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(errorStream));
for (String line; (line = bufferedReader.readLine()) != null; ) {
System.out.println(line);
}
}
});
}
@Test
public void t4() {
String line = " Duration: 00:14:05.11, start: 0.000000, bitrate: 1022 kb/s";
String line2 = "frame= 1 fps=0.0 q=0.0 size= 0kB time=00:00:00.13 bitrate= 2.8kbits/s speed=3.58x ";
Pattern durationPattern = Pattern.compile("Duration: \\d{2}:\\d{2}:\\d{2}\\.\\d{2}");
Pattern timePattern = Pattern.compile("time=\\d{2}:\\d{2}:\\d{2}\\.\\d{2}");
Matcher durationMatcher = durationPattern.matcher(line);
Matcher timeMatcher = timePattern.matcher(line2);
while(durationMatcher.find()) {
String count = durationMatcher.group();
System.out.println(count);
}
while (timeMatcher.find()) {
String count = timeMatcher.group();
System.out.println(count);
}
}
}