Using ffmpeg to obtain video durations in python

后端 未结 7 1093
故里飘歌
故里飘歌 2020-12-10 06:46

I\'ve installed ffprobe using the pip ffprobe command on my PC, and installed ffmpeg from here.

However, I\'m still having trouble running the code listed here.

相关标签:
7条回答
  • 2020-12-10 06:59

    Updated solution using ffprobe based on @llogan guidance with the pointed link:

    import subprocess
    
    def get_duration(input_video):
        cmd = ["ffprobe", "-i", input_video, "-show_entries", "format=duration",
               "-v", "quiet", "-sexagesimal", "-of", "csv=p=0"]
        return subprocess.check_output(cmd).decode("utf-8").strip()
    

    Fragile Solution due to stderr output:

    the stderr output from ffmpeg is not intended for machine parsing and is considered fragile.

    I get help from the following documentation (https://codingwithcody.com/2014/05/14/get-video-duration-with-ffmpeg-and-python/) and https://stackoverflow.com/a/6239379/2402577

    Actually, sed is unnecessary: ffmpeg -i file.mp4 2>&1 | grep -o -P "(?<=Duration: ).*?(?=,)"


    You can use the following method to get the duration in HH:MM:SS format:

    import subprocess
    
    def get_duration(input_video):
        # cmd: ffmpeg -i file.mkv 2>&1 | grep -o -P "(?<=Duration: ).*?(?=,)"
        p1 = subprocess.Popen(['ffmpeg',  '-i', input_video], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        p2 = subprocess.Popen(["grep",  "-o", "-P", "(?<=Duration: ).*?(?=,)"], stdin=p1.stdout, stdout=subprocess.PIPE)
        p1.stdout.close()
        return p2.communicate()[0].decode("utf-8").strip()
    

    Example output for both: 01:37:11.83

    0 讨论(0)
  • 2020-12-10 07:00

    There is no need to iterate though the output of FFprobe. There is one simple command which returns only the duration of the input file:

    ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 <input_video>
    

    You can use the following method instead to get the duration:

    def get_length(input_video):
        result = subprocess.run(['ffprobe', '-v', 'error', '-show_entries', 'format=duration', '-of', 'default=noprint_wrappers=1:nokey=1', input_video], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        return float(result.stdout)
    
    0 讨论(0)
  • 2020-12-10 07:01

    Have you tried adding the encoding? That error is typical of that, as Chamath said. Add the utf-8 encoding to your script header:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*- 
    
    0 讨论(0)
  • 2020-12-10 07:05

    Python Code

    <code>
    cmnd = ['/root/bin/ffmpeg',  '-i', videopath]
    process = subprocess.Popen(cmnd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    stdout, stderr = process.communicate()
    
    #This matches regex to get the time in H:M:S format
    matches = re.search(r"Duration:\s{1}(?P<hours>\d+?):(?P<minutes>\d+?):(?P<seconds>\d+\.\d+?),", stdout, re.DOTALL).groupdict()
    t_hour = matches['hours']
    t_min  = matches['minutes']
    t_sec  = matches['seconds']
    
    t_hour_sec = int(t_hour) * 3600
    t_min_sec = int(t_min) * 60
    t_s_sec   = int(round(float(t_sec)))
    
    total_sec = t_hour_sec + t_min_sec + t_s_sec
    
    #This matches1 is to get the frame rate of a video
    matches1 = re.search(r'(\d+) fps', stdout)
    frame_rate = matches1.group(0) // This will give 20fps
    frame_rate = matches1.group(1) //It will give 20
    
    </code>
    
    0 讨论(0)
  • 2020-12-10 07:11

    we can also use ffmpeg to get the duration of any video or audio files.

    To install ffmpeg follow this link

    import subprocess
    import re
    
    process = subprocess.Popen(['ffmpeg',  '-i', path_of_video_file], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    stdout, stderr = process.communicate()
    matches = re.search(r"Duration:\s{1}(?P<hours>\d+?):(?P<minutes>\d+?):(?P<seconds>\d+\.\d+?),", stdout, re.DOTALL).groupdict()
    
    print (matches['hours'])
    print (matches['minutes'])
    print (matches['seconds'])
    
    0 讨论(0)
  • 2020-12-10 07:13

    I'd suggest using FFprobe (comes with FFmpeg).

    The answer Chamath gave was pretty close, but ultimately failed for me.

    Just as a note, I'm using Python 3.5 and 3.6 and this is what worked for me.

    import subprocess 
    
    def get_duration(file):
        """Get the duration of a video using ffprobe."""
        cmd = 'ffprobe -i {} -show_entries format=duration -v quiet -of csv="p=0"'.format(file)
        output = subprocess.check_output(
            cmd,
            shell=True, # Let this run in the shell
            stderr=subprocess.STDOUT
        )
        # return round(float(output))  # ugly, but rounds your seconds up or down
        return float(output)
    

    If you want to throw this function into a class and use it in Django (1.8 - 1.11), just change one line and put this function into your class, like so:

    def get_duration(file):
    

    to:

    def get_duration(self, file):
    

    Note: Using a relative path worked for me locally, but the production server required an absolute path. You can use os.path.abspath(os.path.dirname(file)) to get the path to your video or audio file.

    0 讨论(0)
提交回复
热议问题