Java videos are uniformly converted to mp4 format and uploaded asynchronously through multiple threads

Background: I encountered a project where I uploaded video files in any format and needed to convert them all into mp4 format. The specific details are 1. The video displayed on the front end cannot be loaded from the beginning. It needs to fast forward to where and which node to start loading like a certain news, so as to achieve non-stuck playback. 2. The background obtains data information such as duration and size, four pictures. Video screenshot cover, choose one as the cover.

Go directly to the code: get the duration of the video, take screenshots, and convert the video

import com.alibaba.fastjson.JSONObject;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ConvertVideo {
    private static String mplayerPath; //= "C:/watermark/mencoder.exe";

    private static String ffmpegPath; //= "C:/watermark/ffmpeg-4.3.1-2021-01-01-essentials_build/bin/ffmpeg.exe";

    private static String filepath; //= "D:/minio/data/";

    public static void setMplayerPath(String mplayerPath) {
        ConvertVideo.mplayerPath = mplayerPath;
    }

    public static void setFfmpegPath(String ffmpegPath) {
        ConvertVideo.ffmpegPath = ffmpegPath;
    }

    public static void setFilepath(String filepath) {
        ConvertVideo.filepath = filepath;
    }

    /**
     * 视频格式转换入口
     *
     * @param inputPath  源文件 路径
     * @param outputPath 目标文件 路径
     * @param outputPath1 中间文件地址 路径
     * @return
     */
    public synchronized static boolean process(String inputPath, String outputPath ,String outputPath1) {
        int type = checkContentType(inputPath);
        boolean status = false;
        Long old = System.currentTimeMillis();
        System.out.println("old--------" + old);
        if (type == 0) {
            System.out.println("直接转成MP4格式");
            status = processMP4(inputPath, outputPath);// 直接转成flv格式
        } else if (type == 1) {
            String avifilepath = processAVI(inputPath, outputPath1);
            System.out.println(avifilepath);
            if (avifilepath == null){
                return false;// 没有得到avi格式
            }
            status = processMP4(avifilepath, outputPath);// 将avi转成flv格式
        }
        Long yong = System.currentTimeMillis();
        System.out.println("消耗时间----------" + (yong-old));
        return status;
    }

    /**
     * 判断文件类型.执行不同的转换流程
     *
     * @param inputPath 源文件路径
     * @return
     */
    private static int checkContentType(String inputPath) {
        String type = inputPath.substring(inputPath.lastIndexOf(".") + 1, inputPath.length())
                .toLowerCase();
        // ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等)
        if (type.equals("avi")) {
            return 0;
        } else if (type.equals("mpg")) {
            return 0;
        } else if (type.equals("wmv")) {
            return 0;
        } else if (type.equals("3gp")) {
            return 0;
        } else if (type.equals("mov")) {
            return 0;
        } else if (type.equals("mp4")) {
            return 0;
        } else if (type.equals("asf")) {
            return 0;
        } else if (type.equals("asx")) {
            return 0;
        } else if (type.equals("flv")) {
            return 0;
        }
        // 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等),
        // 可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.
        else if (type.equals("wmv9")) {
            return 1;
        } else if (type.equals("rm")) {
            return 1;
        } else if (type.equals("rmvb")) {
            return 1;
        }else if (type.equals("dat")) {
            return 1;
        }
        return 9;
    }

    /**
     * 判断源文件是否存在
     *
     * @param path 文件路径
     * @return
     */
    private static boolean checkfile(String path) {
        File file = new File(path);
        if (!file.isFile()) {
            return false;
        }
        return true;
    }

    // 对ffmpeg无法解析的文件格式(wmv9,rm,rmvb等), 可以先用别的工具(mencoder)转换为avi(ffmpeg能解析的)格式.
    private static String processAVI(String inputPath, String outputPath1) {
        List<String> commend = new ArrayList<>();
        commend.add(mplayerPath);
        //commend.add("C:/watermark/mencoder.exe");
        commend.add(inputPath);
        commend.add("-oac");
        commend.add("mp3lame");
        commend.add("-lameopts");
        commend.add("preset=64");
        commend.add("-ovc");
        commend.add("xvid");
        commend.add("-xvidencopts");
        commend.add("bitrate=600");
        commend.add("-of");
        commend.add("avi");
        commend.add("-o");
        commend.add(outputPath1);
        try {
            ProcessBuilder builder = new ProcessBuilder();
            Process process = builder.command(commend).redirectErrorStream(true).start();
            new PrintStream(process.getInputStream()).start();
            new PrintStream(process.getErrorStream()).start();
            process.waitFor();
            process.destroy();
            return outputPath1;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    // ffmpeg能解析的格式:(asx,asf,mpg,wmv,3gp,mp4,mov,avi,flv等) 转换为MP4
    private static boolean processMP4(String inputPath, String outputPath) {

        if (!checkfile(inputPath)) {
            System.out.println(inputPath + " is not file");
            return false;
        }

        List<String> command = new ArrayList<>();
        command.add(ffmpegPath);
        //command.add("C:/watermark/ffmpeg-4.3.1-2021-01-01-essentials_build/bin/ffmpeg.exe");
        command.add("-i");
        command.add(inputPath);
        command.add("-c:v");
        command.add("libx264");
        command.add("-mbd");
        command.add("0");
        command.add("-c:a");
        command.add("aac");
        command.add("-strict");
        command.add("-2");
        command.add("-pix_fmt");
        command.add("yuv420p");
        command.add("-movflags");
        command.add("faststart");
        command.add(outputPath);
        try {
            Process videoProcess = new ProcessBuilder(command).redirectErrorStream(true).start();

            new PrintStream(videoProcess.getErrorStream()).start();

            new PrintStream(videoProcess.getInputStream()).start();

            videoProcess.waitFor();
            videoProcess.destroy();
            System.out.println(outputPath);
            return true;
        } catch (Exception e) {

            return false;
        }
    }
    
    //map4截取图片
    public synchronized static boolean processImg(String veido_path, String image_path,String minao) {
        File file = new File(veido_path);
        if (!file.exists()) {
          System.err.println("路径[" + veido_path + "]对应的视频文件不存在!");
          return false;
        }
        List<String> commands = new ArrayList<String>();
        commands.add(ffmpegPath);
        commands.add("-i");
        commands.add(veido_path);
        commands.add("-y");
        commands.add("-f");
        commands.add("image2");
        commands.add("-ss");
        System.out.println(String.valueOf(minao));
        commands.add(minao);// 这个参数是设置截取视频多少秒时的画面
        // commands.add("-t");
        // commands.add("0.001");
        commands.add("-s");
        commands.add("700x700");//尺寸
        /*commands.add(veido_path.substring(0, veido_path.lastIndexOf("."))
            .replaceFirst("vedio", "file") + ".jpg");*/
        commands.add(image_path);
        try {
          ProcessBuilder builder = new ProcessBuilder();
          builder.command(commands);
          builder.start();
          System.out.println("截取成功");
          return true;
        } catch (Exception e) {
          e.printStackTrace();
          return false;
        }
      }
    
    
    
    public static JSONObject readVideoTimeFromCommand(String filePath){
        JSONObject jsonObject = new JSONObject();
        ProcessBuilder builder = new ProcessBuilder();
        List<String> commands = new ArrayList<>();
        commands.add(ffmpegPath);
        commands.add("-i");
        commands.add(filePath);
        builder.command(commands);
        builder.redirectErrorStream(true);
        Process p = null;
        try {
            p = builder.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 获取执行输出信息
        BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8));
        StringBuilder outInfo = new StringBuilder();
        String line = "";
        while (true) {
            try {
                if (!((line = br.readLine()) != null)) {
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            outInfo.append(line);
        }
        try {
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 通过正则获取时长信息
        String regexDuration = "Duration: (.*?), start: (.*?), bitrate: (\\d*) kb\\/s";
        Pattern pattern = Pattern.compile(regexDuration);
        Matcher matcher = pattern.matcher(outInfo.toString());
        if (matcher.find()) {
            return getTime(matcher.group(1));
        }
        return jsonObject;
    }

    /**
     * 获取时间毫秒
     * @param time 格式:"00:00:10.68"
     * @return
     */
    private static JSONObject getTime(String time) {
        JSONObject jsonObject = new JSONObject();
    	System.out.println(time);
        int index = time.lastIndexOf(".");
        String distpath = time.substring(0, index);
        jsonObject.put("time",distpath);
        int min = 0;
        String[] strs = time.split(":");
        String ZERO="0";
        if (strs[0].compareTo(ZERO) > 0) {
            // 秒
            min += Long.parseLong(strs[0]) * 60 * 60 * 1000;
        }
        if (strs[1].compareTo(ZERO) > 0) {
            min += Long.parseLong(strs[1]) * 60 * 1000;
        }
        if (strs[2].compareTo(ZERO) > 0) {
            min += Math.round(Double.parseDouble(strs[2]) * 1000);
        }
        System.out.println(min);
        jsonObject.put("min",min);
        return jsonObject;
    }

}

/**
 * 资源释放流.避免内存溢出导致进程阻塞
 */
class PrintStream extends Thread {

    java.io.InputStream __is = null;

    public PrintStream(java.io.InputStream is) {
        __is = is;
    }

    @Override
    public void run() {
        try {
            while (this != null) {
                int _ch = __is.read();
                if (_ch != -1){
                    System.out.print((char) _ch);
                }else{
                    break;
                }
            }
            __is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static String secondsToTime(int seconds){
        int h=seconds/3600;			//小时
        int m=(seconds%3600)/60;		//分钟
        int s=(seconds%3600)%60;		//秒
        String hh = "";
        String mm = "";
        String ss = "";
        if(h>0){
            if(h<9){
                hh = "0"+h;
            }else{
                hh = ""+h;
            }
            if(m<9){
                mm = "0"+m;
            }else{
                mm = ""+m;
            }
            if(s<9){
                ss = "0"+s;
            }else{
                ss = ""+s;
            }
            return hh+":"+mm+":"+ss;
        }
        if(m>0){
            if(m<9){
                mm = "0"+m;
            }else{
                mm = ""+m;
            }
            if(s<9){
                ss = "0"+s;
            }else{
                ss = ""+s;
            }
            return "00:"+mm+":"+ss;
        }
        if(s<9){
            ss = "0"+s;
        }else{
            ss = ""+s;
        }
        return "00:00:"+ss;
    }


    public static void main(String[] args) {
        //获取时长和大小
        ConvertVideo.readVideoTimeFromCommand("文件路径");
        //截图  最后一个参数需要是 00:00:00格式的  截图最好截图前10秒的图,要不然截图会不成功
       // ConvertVideo.processImg("源文件", "图片存放位置" + ".jpg", secondsToTime("视频文件大小"));//截图
       //视频转换
       // ConvertVideo.process("源文件路径", "转成的mp4文件路径", "中间avi临时文件路径");
    }


}

Note: Two files are required

Link: https://pan.baidu.com/s/1qZb7CqcUxTZDe-nYwsnWsQ 
Extraction code: abcd

Link: https://pan.baidu.com/s/1oPzD1ZNCgF3HCKfi8aTEzg 
Extraction code: abcd

Note that whether this kind of conversion is to obtain the duration, screenshot or video conversion, if it is executed by multiple threads, one thread will complete the execution of the other thread before it will be executed. It is equivalent to multi-threading being useless, but the conversion is too time-consuming, so getting the duration I found other ways to take screenshots

Above code:

import org.apache.commons.io.FileUtils;
import org.springframework.web.multipart.MultipartFile;
import ws.schild.jave.MultimediaObject;
import ws.schild.jave.info.MultimediaInfo;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.TimeZone;

public class VideoUtil {

    /**
     * 上传视频,获取视频时长,返回毫秒
     * @param multipartFile
     * @return
     */
    public static long getDurationBackMillis(MultipartFile multipartFile){
        if(multipartFile != null){
            try{
                // 根据上传的文件名字,构建初始化的文件对象(临时文件),这个文件是空的
                File file = new File(multipartFile.getOriginalFilename());
                // 通过工具类,将文件拷贝到空的文件对象中
                FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), file);

                // 将普通文件对象转换为媒体对象
                MultimediaObject multimediaObject = new MultimediaObject(file);
                // 获取媒体对象的信息对象
                MultimediaInfo info = multimediaObject.getInfo();
                // 从媒体信息对象中获取媒体的时长,单位是:ms
                long duration = info.getDuration();
                // 删除临时文件
                file.delete();

                return duration;
            } catch(Exception e){
                return 0L;
            }
        }
        return 0L;
    }

    /**
     * 上传视频,获取视频时长,返回时分秒字符串
     * @param multipartFile
     * @return
     */
    public static String getDurationBackString(MultipartFile multipartFile){
        // 获取视频时长,返回毫秒
        long duration = getDurationBackMillis(multipartFile);
        // 毫秒转时分秒的转换
        // 日期格式化对象,给时分秒格式
        SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
        // 这里很重要,如果不设置时区的话,输出结果就会是几点钟,而不是毫秒值对应的时分秒数量了。
        formatter.setTimeZone(TimeZone.getTimeZone("GMT+00:00"));
        // 毫秒转化为字符串
        return formatter.format(duration);
    }
}

import org.bytedeco.javacpp.opencv_core;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;

public class DealVideo {

    /*默认图片格式 jpg*/
    public static String DEFAULT_IMG_FORMAT = "jpg";

    /**
     * 获取指定视频的帧并保存为图片JPG格式至指定文件
     *
     * @param videoFile  源视频文件路径
     * @param targetFile 截取帧的图片存放路径
     * @param frameNum   截取第几帧
     * @throws Exception
     */
    public static void fetchFrameToFile(String videoFile, String targetFile, int frameNum) {
        //校验输入和输出
        checkInAnOut(videoFile, targetFile);
        try {
            File frameFile = new File(targetFile);
            FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoFile);
            ff.start();
            int length = ff.getLengthInFrames();
            /*第几帧判断设置*/
            if (frameNum < 0) {
                frameNum = 0;
            }
            if (frameNum > length) {
                frameNum = length - 5;
            }
            //指定第几帧
            ff.setFrameNumber(frameNum);
            int i = 0;
            Frame f = null;
            while (i < length) {
                // 过滤前5帧,避免出现全黑的图片,依自己情况而定
                f = ff.grabFrame();
                if ((i >= 5) && (f.image != null)) {
                    break;
                }
                i++;
            }
            opencv_core.IplImage img = f.image;
            int width = img.width();
            int height = img.height();
            BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
            bi.getGraphics().drawImage(f.image.getBufferedImage().getScaledInstance(width, height, Image.SCALE_SMOOTH),
                    0, 0, null);
            ff.flush();
            ff.stop();
            ImageIO.write(bi, DEFAULT_IMG_FORMAT, frameFile);
        } catch (Exception e) {
            //throw new RuntimeException("转换视频图片异常");
            e.printStackTrace();
        }

    }

    /**
     * 获取指定视频的帧并保存为图片自定义类型至指定文件
     *
     * @param videoFile  源视频文件路径
     * @param targetFile 截取帧的图片存放文件路径
     * @param outImgFormat 输出图片格式
     * @param frameNum   截取第几帧
     * @throws Exception
     */
/*    public static void fetchFrameToFile(String videoFile, String targetFile, String outImgFormat, int frameNum) throws FrameGrabber.Exception, IOException {
        //校验输入和输出
        checkInAnOut(videoFile, targetFile);
        try {
            File frameFile = new File(targetFile);
            FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoFile);
            ff.start();
            int length = ff.getLengthInFrames();
            *//*第几帧判断设置*//*
            if (frameNum < 0) {
                frameNum = 0;
            }
            if (frameNum > length) {
                frameNum = length - 5;
            }
            //指定第几帧
            ff.setFrameNumber(frameNum);
            int i = 0;
            Frame f = null;
            while (i < length) {
                // 过滤前5帧,避免出现全黑的图片,依自己情况而定
                f = ff.grabFrame();
                if ((i >= 5) && (f.image != null)) {
                    break;
                }
                i++;
            }
            opencv_core.IplImage img = f.image;
            int width = img.width();
            int height = img.height();
            BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
            bi.getGraphics().drawImage(f.image.getBufferedImage().getScaledInstance(width, height, Image.SCALE_SMOOTH),
                    0, 0, null);
            ff.flush();
            ff.stop();
            // ImageUtils2 工具类旋转图片
            BufferedImage ret = ImageUtils2.rotateClockwise0(bi);
            ImageIO.write(ret, outImgFormat, frameFile);
        } catch (Exception e) {
            throw new RuntimeException("转换视频图片异常");
        }
    }*/

    /**
     * 获取指定视频的帧图片,并转换为base64字符串
     *
     * @param videoFile 源视频文件路径
     * @param frameNum  截取第几帧
     * @throws Exception
     */
    public static String fetchFrameToBase64(String videoFile, int frameNum) throws FrameGrabber.Exception, IOException {
        //校验输入
        checkVideoFile(videoFile);
        try (ByteArrayOutputStream output = new ByteArrayOutputStream();) {
            FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoFile);
            ff.start();
            int length = ff.getLengthInFrames();
            /*第几帧判断设置*/
            if (frameNum < 0) {
                frameNum = 0;
            }
            if (frameNum > length) {
                frameNum = length - 5;
            }
            //指定第几帧
            ff.setFrameNumber(frameNum);
            int i = 0;
            Frame f = null;
            while (i < length) {
                // 过滤前5帧,避免出现全黑的图片,依自己情况而定
                f = ff.grabFrame();
                if ((i >= 5) && (f.image != null)) {
                    break;
                }
                i++;
            }
            opencv_core.IplImage img = f.image;
            int width = img.width();
            int height = img.height();
            BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
            bi.getGraphics().drawImage(f.image.getBufferedImage().getScaledInstance(width, height, Image.SCALE_SMOOTH),
                    0, 0, null);
            ImageIO.write(bi, DEFAULT_IMG_FORMAT, output);
            // 这里需要获取图片的base64数据串,所以将图片写到流里面
            ff.flush();
            ff.stop();
            return new BASE64Encoder().encode(output.toByteArray());
        } catch (Exception e) {
            throw new RuntimeException("转换视频图片异常");
        }
    }


    /**
     * 校验输入输出
     *
     * @param videoFile
     * @param targetFile
     */
    public static void checkInAnOut(String videoFile, String targetFile) {
        checkVideoFile(videoFile);
        checkTargetFileDir(targetFile);
    }

    /**
     * 验证文件目录是否存在,不存在就创建
     *
     * @param targetFile 文件路径
     * @return
     */
    public static void checkTargetFileDir(String targetFile) {
        String dirPath = targetFile.substring(0, targetFile.lastIndexOf(File.separator) + 1);
        File dir = new File(dirPath);
        if (!dir.exists()) {
            dir.mkdirs();
        }
    }

    /**
     * 检验文件是否存在
     *
     * @param videoFile
     */
    public static void checkVideoFile(String videoFile) {
        File file = new File(videoFile);
        if (!file.exists()) {
            throw new RuntimeException("文件不存在");
        }
    }

}

The approximate code of the code demo I uploaded

//先上传源文件到系统
savePath = CommonUtils.upload(file, bizPath, uploadType,sy);
//获取源文件的时长和大小以及截图
 //时长
 String durationBackString = VideoUtil.getDurationBackString(file);
//大小
 long durationBackMillis = VideoUtil.getDurationBackMillis(file);
//截图
 DealVideo.fetchFrameToFile(inputPath,distpath + newnames + ".jpg",i1);

//异步转换
 task.task1(inputPath, outputPath, outputPath1, uuid);



Asynchronous thread pool

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

@Configuration
@EnableAsync
public class ThreadPoolConfig {

    /**
     * 每秒需要多少个线程处理?
     * tasks/(1/taskcost)
     */
    private int corePoolSize = 3;

    /**
     * 线程池维护线程的最大数量
     * (max(tasks)- queueCapacity)/(1/taskcost)
     */
    private int maxPoolSize = 100;

    /**
     * 缓存队列
     * (coreSizePool/taskcost)*responsetime
     */
    private int queueCapacity = 10;

    /**
     * 允许的空闲时间
     * 默认为60
     */
    private int keepAlive = 100;

    @Bean
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置核心线程数
        executor.setCorePoolSize(corePoolSize);
        // 设置最大线程数
        executor.setMaxPoolSize(maxPoolSize);
        // 设置队列容量
        executor.setQueueCapacity(queueCapacity);
        // 设置允许的空闲时间(秒)
        //executor.setKeepAliveSeconds(keepAlive);
        // 设置默认线程名称
        executor.setThreadNamePrefix("thread-");
        // 设置拒绝策略rejection-policy:当pool已经达到max size的时候,如何处理新任务
        // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        return executor;
    }
}

Add asynchronous to startup class

 Asynchronous task code

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.util.ConvertVideo;
import org.jeecg.common.util.FileUrlUtil;
import org.jeecg.common.util.MinioUtil;
import org.jeecg.modules.business.num.entity.YwVisit;
import org.jeecg.modules.business.num.service.IYwVisitService;
import org.jeecg.modules.business.video.entity.YwVideo;
import org.jeecg.modules.business.video.service.IYwVideoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
import org.springframework.util.concurrent.ListenableFuture;

import java.util.Random;

@Component
@Slf4j
public class MyTask {

    @Autowired
    private IYwVideoService videoService;

    @Autowired
    private IYwVisitService ywVisitService;

    @Async("taskExecutor")
    public synchronized void task1(String inputPath,String outputPath,String outputPath1,String uuid) throws Exception {
        System.out.println("正在执行线程" + Thread.currentThread().getName() + " 执行异步任务一"+uuid);
        boolean process = ConvertVideo.process(inputPath, outputPath, outputPath1);
        System.out.println("转换完成");
        YwVideo video = videoService.getOne(new QueryWrapper<YwVideo>()
                .eq("uuid", uuid)
        );
        if(null!=video){
            if(!process){
                video.setFlag("2");
                //根据uuid 更新状态
                //throw new Exception("转换错误");
            }else{
                video.setFlag("1");
            }
            //根据uuid更新状态
            videoService.updateById(video);
        }else{
            YwVisit visit = new YwVisit();
            visit.setUuid(uuid);
            ywVisitService.save(visit);
        }
        FileUrlUtil.removeObject(inputPath,"minio");
        FileUrlUtil.removeObject(outputPath1,"minio");
    }


    @Async("taskExecutor")
    public synchronized void test(int num) throws Exception {
        System.out.println("正在执行线程" + Thread.currentThread().getName() + " 执行异步任务"+num);
    }


}

Guess you like

Origin blog.csdn.net/weixin_41018853/article/details/128081894