|
| 1 | +import re |
| 2 | +from shutil import which |
| 3 | +from subprocess import Popen, PIPE |
| 4 | + |
| 5 | +from typing import Optional |
| 6 | + |
| 7 | +# Module to determine the length of video. |
| 8 | +# The length is found by the FFmpeg, the output of video_duration is in seconds. |
| 9 | + |
| 10 | + |
| 11 | +def video_duration(video_path: str, ffmpeg_path: Optional[str] = None) -> float: |
| 12 | + """ |
| 13 | + Retrieve the exact video duration as echoed by the FFmpeg and return |
| 14 | + the duration in seconds. Maximum duration supported is 999 hours, above |
| 15 | + which the regex is doomed to fail(no match). |
| 16 | +
|
| 17 | + :param video_path: Absolute path of the video file. |
| 18 | +
|
| 19 | + :param ffmpeg_path: Path of the FFmpeg software if not in path. |
| 20 | +
|
| 21 | + :return: Video length(duration) in seconds. |
| 22 | +
|
| 23 | + :rtype: float |
| 24 | + """ |
| 25 | + |
| 26 | + if not ffmpeg_path: |
| 27 | + ffmpeg_path = str(which("ffmpeg")) |
| 28 | + |
| 29 | + command = f'"{ffmpeg_path}" -i "{video_path}"' |
| 30 | + process = Popen(command, shell=True, stdout=PIPE, stderr=PIPE) |
| 31 | + output, error = process.communicate() |
| 32 | + |
| 33 | + match = re.search( |
| 34 | + r"Duration\:(\s\d?\d\d\:\d\d\:\d\d\.\d\d)\,", |
| 35 | + (output.decode() + error.decode()), |
| 36 | + ) |
| 37 | + |
| 38 | + if match: |
| 39 | + duration_string = match.group(1) |
| 40 | + |
| 41 | + hours, minutes, seconds = duration_string.strip().split(":") |
| 42 | + |
| 43 | + return float(hours) * 60.00 * 60.00 + float(minutes) * 60.00 + float(seconds) |
0 commit comments