【Java】java使用ffmpeg實現視頻切割


轉自:https://blog.csdn.net/qq_34445142/article/details/106570745

ffmpeg命令官方文檔:http://ffmpeg.org/ffmpeg.html

需求:將已經錄制好的視頻,從固定時間開始截取,到固定時間結束.並且將視頻截取成相對平均的若干段視頻

1.首先需要安裝FFmpeg.

2.代碼

 //分割視頻的大小
    private long blockSize = 1 * 1024 * 1024;
    
    @Test
    public void Test1() throws Exception {
       List<String> lists = cutVideo("/Users/wangge/Desktop/erge.mp4");
        System.out.println(lists);
    }

視頻切割規則計算,切割命令組裝

/**
     * @param filePath 要處理的文件路徑
     * @return 分割后的文件路徑
     * @throws Exception 文件
     */
    List<String> cutVideo(String filePath) throws Exception {
        File file = new File(filePath);
        if (!file.exists()) {
            throw new FileNotFoundException(filePath + "文件不存在");
        }
        if (!filePath.endsWith(".mp4")) {
            throw new Exception("文件格式錯誤");
        }
        //從ffmpeg獲得的時間長度00:00:00格式
        String videoTimeString = getVideoTime(file);
        log.info("從ffmpeg獲得的時間長度00:00:00格式:{}",videoTimeString);
        //將時長轉換為秒數
        int videoSecond = parseTimeToSecond(videoTimeString);
        log.info("將時長轉換為秒數:{}",videoSecond);
        //視頻文件的大小
        long fileLength = getVideoFileLength(file);
        log.info("視頻文件的大小:{}",fileLength);
        List<String> cutedVideoPaths = new ArrayList<String>();
        if (fileLength <= blockSize) {
            log.info("如果視頻文件大小不大於預設值,則直接返回原視頻文件");
            cutedVideoPaths.add(filePath);
        } else {
            log.info("超過預設大小,需要切割");
            int partNum = (int) (fileLength / blockSize);
            log.info("文件大小除以分塊大小的商:{}",partNum);
            long remainSize = fileLength % blockSize;
            log.info("余數:{}",remainSize);
            int cutNum;
            if (remainSize > 0) {
                cutNum = partNum + 1;
            } else {
                cutNum = partNum;
            }
            log.info("cutNum:{}",cutNum);
            int eachPartTime = videoSecond / cutNum;
            log.info("eachPartTime:{}",eachPartTime);
            String fileFolder = file.getParentFile().getAbsolutePath();
            log.info("fileFolder:{}",fileFolder);
            String fileName[] = file.getName().split("\\.");
            log.info("fileName[]:{}",fileName);

            for (int i = 0; i < cutNum; i++) {
                List<String> commands = Lists.newArrayList();
                commands.add("ffmpeg");
                commands.add("-ss");
                commands.add(parseTimeToString(eachPartTime * i));
                if (i != cutNum - 1) {
                    commands.add("-t");
                    commands.add(parseTimeToString(eachPartTime));
                }
                commands.add("-i");
                commands.add(filePath);
                commands.add("-codec");
                commands.add("copy");
                commands.add(fileFolder + File.separator + fileName[0] + "_part" + i + "." + fileName[1]);
                cutedVideoPaths.add(fileFolder + File.separator + fileName[0] + "_part" + i + "." + fileName[1]);
                newRunCommand(commands);
            }
        }
        return cutedVideoPaths;
    }

開始逐條執行命令

private Result newRunCommand(List<String> command) {
        log.info("相關命令 command:{}",command);
        Result result = new Result(false, "");
        ProcessBuilder builder = new ProcessBuilder(command);
        builder.redirectErrorStream(true);
        try {
            Process process = builder.start();
            final StringBuilder stringBuilder = new StringBuilder();
            final InputStream inputStream = process.getInputStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                String line;
                 while ((line = reader.readLine()) != null) {
                    stringBuilder.append(line);
                }

            while ((line = reader.readLine()) != null){

            }
            if (reader != null) {
                reader.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
        } catch (Exception e) {
            throw new RuntimeException("ffmpeg執行異常" + e.getMessage());
        }
        return result;
    }

工具類相關:

/**
     * 獲取視頻文件時長
     *
     * @param file 文件
     * @return 時長 格式hh:MM:ss
     * @throws FileNotFoundException 視頻不存在拋出此異常
     */
    private String getVideoTime(File file) throws FileNotFoundException {
        if (!file.exists()) {
            throw new FileNotFoundException(file.getAbsolutePath() + "不存在");
        }
        List<String> commands = new ArrayList<String>();
        commands.add("ffmpeg");
        commands.add("-i");
        commands.add(file.getAbsolutePath());
        Result result = runCommand(commands);
        String msg = result.getMsg();
        if (result.isSuccess()) {
            Pattern pattern = Pattern.compile("\\d{2}:\\d{2}:\\d{2}");
            Matcher matcher = pattern.matcher(msg);
            String time = "";
            while (matcher.find()) {
                time = matcher.group();
            }
            return time;
        } else {
            return "";
        }
    }
 /**
     * 獲取文件大小
     *
     * @param file 去的文件長度,單位為字節b
     * @return 文件長度的字節數
     * @throws FileNotFoundException 文件未找到異常
     */
    private long getVideoFileLength(File file) throws FileNotFoundException {
        if (!file.exists()) {
            throw new FileNotFoundException(file.getAbsolutePath() + "不存在");
        }
        return file.length();
    }
/**
     * 將字符串時間格式轉換為整型,以秒為單位
     *
     * @param timeString 字符串時間時長
     * @return 時間所對應的秒數
     */
    private int parseTimeToSecond(String timeString) {
        Pattern pattern = Pattern.compile("\\d{2}:\\d{2}:\\d{2}");
        Matcher matcher = pattern.matcher(timeString);
        if (!matcher.matches()) {
            try {
                throw new Exception("時間格式不正確");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        String[] time = timeString.split(":");
        return Integer.parseInt(time[0]) * 3600 + Integer.parseInt(time[1]) * 60 + Integer.parseInt(time[2]);
    }

    /**
     * 將秒表示時長轉為00:00:00格式
     *
     * @param second 秒數時長
     * @return 字符串格式時長
     */
    private String parseTimeToString(int second) {
        int end = second % 60;
        int mid = second / 60;
        if (mid < 60) {
            return mid + ":" + end;
        } else if (mid == 60) {
            return "1:00:" + end;
        } else {
            int first = mid / 60;
            mid = mid % 60;
            return first + ":" + mid + ":" + end;
        }

    }
public class Result {
        private boolean success;
        private String msg;

        public Result(boolean success, String msg) {
            this.success = success;
            this.msg = msg;
        }

        public Result() {

        }

        public boolean isSuccess() {
            return success;
        }

        public void setSuccess(boolean success) {
            this.success = success;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }
    }

processBuiler教程:https://geek-docs.com/java/java-tutorial/processbuilder.html#ProcessBuilder-7


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM