zhaowenyu
2026-03-02 473b5351fbbfd4e5fa4b0f87356253776bfa6da6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package com.ard.sample.utils;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
/**
 * 视频时长解析工具类(FFmpeg 命令行版)
 * 无需下载文件,直接解析远程 HTTPS 地址的 MP4 视频时长
 */
@Component
public class VideoDurationUtilFFmpeg {
 
    private static final Pattern DURATION_PATTERN = Pattern.compile("Duration: (\\d{2}):(\\d{2}):(\\d{2}\\.\\d{2})");
 
    /**
     * 获取远程 HTTPS 地址的 MP4 视频时长
     * @param videoHttpsUrl 视频 HTTPS 地址
     * @return 视频时长(秒,保留2位小数),解析失败返回 null
     */
    public double getRemoteMp4Duration(String videoHttpsUrl) {
        // 入参校验
        if (videoHttpsUrl == null || !videoHttpsUrl.trim().toLowerCase().startsWith("https")
                || !videoHttpsUrl.trim().toLowerCase().endsWith(".mp4")) {
            throw new IllegalArgumentException("无效的MP4视频HTTPS地址:" + videoHttpsUrl);
        }
 
        try {
            // 构建 FFmpeg 命令,直接解析远程 URL
            String[] command = {
                    "ffmpeg",
                    "-i", videoHttpsUrl,
                    "-hide_banner"
            };
 
            Process process = new ProcessBuilder(command)
                    .redirectErrorStream(true)
                    .start();
 
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(process.getInputStream())
            );
 
            String line;
            while ((line = reader.readLine()) != null) {
                Matcher matcher = DURATION_PATTERN.matcher(line);
                if (matcher.find()) {
                    int hours = Integer.parseInt(matcher.group(1));
                    int minutes = Integer.parseInt(matcher.group(2));
                    double seconds = Double.parseDouble(matcher.group(3));
 
                    double totalSeconds = hours * 3600 + minutes * 60 + seconds;
 
                    return totalSeconds;
//                    return new BigDecimal(totalSeconds)
//                            .setScale(2, RoundingMode.HALF_UP);
                }
            }
 
            // 等待进程结束
            process.waitFor();
            if (process.exitValue() != 0) {
                throw new RuntimeException("FFmpeg 执行失败,退出码:" + process.exitValue());
            }
 
        } catch (Exception e) {
            System.err.println("解析视频时长失败,URL:" + videoHttpsUrl + ",异常:" + e.getMessage());
        }
        return -1;
    }
 
//    // 测试方法(可删除)
//    public static void main(String[] args) {
//        VideoDurationUtilFFmpeg util = new VideoDurationUtilFFmpeg();
//
//        TimestampUtils _timestampUtils = new TimestampUtils();
//        // 替换为你的测试视频 URL
//        double duration = util.getRemoteMp4Duration("https://192.168.1.3:9001/dockfile/wayline/d16eb96c-a0cc-458f-852c-09dddd59827f/DJI_202602121540_002_d16eb96c-a0cc-458f-852c-09dddd59827f/DJI_20260212154239_0004_V.mp4");
//        long endTime=_timestampUtils.plusSecondsByMillis(System.currentTimeMillis(),duration);
//        if (duration != -1) {
//            System.out.println("视频时长:" + duration + " 秒");
//            System.out.println("视频结束时间:" + endTime);
//        } else {
//            System.out.println("解析失败");
//        }
//    }
}