如何在Python中获取视频的持续时间?

eos*_*s87 28 python video

我需要在Python中获取视频持续时间.我需要获得的视频格式是MP4,Flash视频,AVI和MOV ......我有一个共享托管解决方案,所以我没有FFmpeg支持.

Sin*_*ion 42

您可能需要调用外部程序.ffprobe可以为您提供这些信息:

import subprocess

def getLength(filename):
  result = subprocess.Popen(["ffprobe", filename],
    stdout = subprocess.PIPE, stderr = subprocess.STDOUT)
  return [x for x in result.stdout.readlines() if "Duration" in x]
Run Code Online (Sandbox Code Playgroud)

  • 你也可以使用`-print_format json`和`-show_streams`然后json.loads得到一个包含所有ffprobe信息的好词典.这还需要解析ffprobe打印出的额外信息(还没有找到隐藏的选项) (7认同)
  • Python包装[ffprobe(https://pypi.python.org/pypi/ffprobe/0.5)可能是太方便,`INT(浮动(FFProbe(文件名).视频[0] .duration)*1000)`让你毫秒 (5认同)
  • 使用`ffprobe` Python 模块,它的`from ffprobe import FFProbe; FFProbe('path/to/file').streams[0].duration` (3认同)
  • @dennmat:`-loglevel`不是`-log_level`(至少用ffprobe 2.3.3) (2认同)
  • 当我运行此代码时,出现错误“找不到文件”。尽管文件存在。 (2认同)

小智 26

2020年答案

解决方案:

  1. opencv 0.0065 秒?
  2. ffprobe 0.0998 秒
  3. moviepy 2.8239 秒

? OpenCV方法:

def with_opencv(filename):
    import cv2
    video = cv2.VideoCapture(filename)

    duration = video.get(cv2.CAP_PROP_POS_MSEC)
    frame_count = video.get(cv2.CAP_PROP_FRAME_COUNT)

    return duration, frame_count
Run Code Online (Sandbox Code Playgroud)

用法: print(with_opencv('my_video.webm'))


其他:

ffprobe 方法:

def with_ffprobe(filename):
    import subprocess, json

    result = subprocess.check_output(
            f'ffprobe -v quiet -show_streams -select_streams v:0 -of json "{filename}"',
            shell=True).decode()
    fields = json.loads(result)['streams'][0]

    duration = fields['tags']['DURATION']
    fps      = eval(fields['r_frame_rate'])
    return duration, fps
Run Code Online (Sandbox Code Playgroud)

moviepy 方法:

def with_moviepy(filename):
    from moviepy.editor import VideoFileClip
    clip = VideoFileClip(filename)
    duration       = clip.duration
    fps            = clip.fps
    width, height  = clip.size
    return duration, fps, (width, height)
Run Code Online (Sandbox Code Playgroud)

  • 似乎可以通过读取 fps 来修复: fps = video.get(cv2.CAP_PROP_FPS) 持续时间 = frame_count / fps (7认同)
  • 对于我的视频,OpenCV 代码返回 0 持续时间。但帧计数值很好,因此可以调用“fps = video.get(cv2.CAP_PROP_FPS)”并通过“frame_count/fps”获取持续时间。OpenCV 方法比使用 ffmpeg 的子进程更快,但是您必须在系统中安装很多东西才能使其正常工作。对我来说“pymediainfo”似乎几乎是两倍快 (5认同)
  • 你的 OpenCV 方法确实很有趣。然而,它似乎很容易出错,经常返回 0 值,这显然是由于编解码器的原因。我无法正确计算单个文件。如果您对此添加几句话,我很乐意投票=) (3认同)
  • opencv不可靠,请参见官方github问题https://github.com/opencv/opencv/issues/15749#issuecomment-796512723 (2认同)

mob*_*cdi 18

正如此处报道的那样https://www.reddit.com/r/moviepy/comments/2bsnrq/is_it_possible_to_get_the_length_of_a_video/

你可以使用moviepy模块

from moviepy.editor import VideoFileClip
clip = VideoFileClip("my_video.mp4")
print( clip.duration )
Run Code Online (Sandbox Code Playgroud)

  • ffpobe 比moviepy 快10 倍。 (5认同)
  • 这对我来说足够快而且简单。谢谢。请注意,此代码的输出单位为秒。 (2认同)

And*_*510 16

为了使事情更容易,以下代码将输出放到JSON.

您可以使用它来使用它probe(filename),或通过使用获得持续时间duration(filename):

json_info     = probe(filename)
secondes_dot_ = duration(filename) # float number of seconds
Run Code Online (Sandbox Code Playgroud)

它适用于Ubuntu 14.04当然ffprobe安装的地方.代码没有针对速度或美观目的进行优化,但它适用于我的机器,希望它有所帮助.

#
# Command line use of 'ffprobe':
#
# ffprobe -loglevel quiet -print_format json \
#         -show_format    -show_streams \
#         video-file-name.mp4
#
# man ffprobe # for more information about ffprobe
#

import subprocess32 as sp
import json


def probe(vid_file_path):
    ''' Give a json from ffprobe command line

    @vid_file_path : The absolute (full) path of the video file, string.
    '''
    if type(vid_file_path) != str:
        raise Exception('Gvie ffprobe a full file path of the video')
        return

    command = ["ffprobe",
            "-loglevel",  "quiet",
            "-print_format", "json",
             "-show_format",
             "-show_streams",
             vid_file_path
             ]

    pipe = sp.Popen(command, stdout=sp.PIPE, stderr=sp.STDOUT)
    out, err = pipe.communicate()
    return json.loads(out)


def duration(vid_file_path):
    ''' Video's duration in seconds, return a float number
    '''
    _json = probe(vid_file_path)

    if 'format' in _json:
        if 'duration' in _json['format']:
            return float(_json['format']['duration'])

    if 'streams' in _json:
        # commonly stream 0 is the video
        for s in _json['streams']:
            if 'duration' in s:
                return float(s['duration'])

    # if everything didn't happen,
    # we got here because no single 'return' in the above happen.
    raise Exception('I found no duration')
    #return None


if __name__ == "__main__":
    video_file_path = "/tmp/tt1.mp4"
    duration(video_file_path) # 10.008
Run Code Online (Sandbox Code Playgroud)

  • 在返回jason.loads(out)之前,out应该被解码为str.`out = out.decode('utf-8')` (2认同)

avi*_*zil 13

使用现代方法https://github.com/kkroening/ffmpeg-python ( pip install ffmpeg-python --user)。不要忘记ffmpeg也安装。

获取视频信息:

import ffmpeg

info=ffmpeg.probe(filename)

print(f"duration={info['format']['duration']}")
print(f"framerate={info['streams'][0]['avg_frame_rate']}")
Run Code Online (Sandbox Code Playgroud)

使用ffmpeg-python包还可以轻松创建、编辑滤镜并将其应用于视频。


che*_*976 5

找到这个新的python库:https://github.com/sbraz/pymediainfo

要获得持续时间:

from pymediainfo import MediaInfo
media_info = MediaInfo.parse('my_video_file.mov')
#duration in milliseconds
duration_in_ms = media_info.tracks[0].duration
Run Code Online (Sandbox Code Playgroud)

上面的代码是针对有效的mp4文件进行测试的,但是你应该做更多的检查,因为它严重依赖于MediaInfo的输出.


DeW*_*Wil 5

from subprocess import check_output

file_name = "movie.mp4"

#For Windows
a = str(check_output('ffprobe -i  "'+file_name+'" 2>&1 |findstr "Duration"',shell=True)) 

#For Linux
#a = str(check_output('ffprobe -i  "'+file_name+'" 2>&1 |grep "Duration"',shell=True)) 

a = a.split(",")[0].split("Duration:")[1].strip()

h, m, s = a.split(':')
duration = int(h) * 3600 + int(m) * 60 + float(s)

print(duration)
Run Code Online (Sandbox Code Playgroud)


sr9*_*yar 5

我想出的一个功能。这基本上只使用ffprobe参数

from subprocess import  check_output, CalledProcessError, STDOUT 


def getDuration(filename):

    command = [
        'ffprobe', 
        '-v', 
        'error', 
        '-show_entries', 
        'format=duration', 
        '-of', 
        'default=noprint_wrappers=1:nokey=1', 
        filename
      ]

    try:
        output = check_output( command, stderr=STDOUT ).decode()
    except CalledProcessError as e:
        output = e.output.decode()

    return output


fn = '/app/648c89e8-d31f-4164-a1af-034g0191348b.mp4'
print( getDuration(  fn ) )
Run Code Online (Sandbox Code Playgroud)

输出持续时间如下:

7.338000
Run Code Online (Sandbox Code Playgroud)


Min*_*sih 5

据报道 https://www.reddit.com/r/moviepy/comments/2bsnrq/is_it_possible_to_get_the_length_of_a_video/

你可以使用 moviepy 模块

from moviepy.editor import VideoFileClip 
clip = VideoFileClip("my_video.mp4") 
print( clip.duration )
Run Code Online (Sandbox Code Playgroud)

如果您尝试获取文件夹中许多视频的持续时间,则会崩溃并给出错误:AttributeError:“AudioFileClip”对象没有属性“reader”

因此,为了避免这种情况,您需要添加

clip.close()
Run Code Online (Sandbox Code Playgroud)

基于此: https ://zulko.github.io/moviepy/_modules/moviepy/video/io/VideoFileClip.html

所以代码看起来像这样:

from moviepy.editor import VideoFileClip
clip = VideoFileClip("my_video.mp4")
print( clip.duration )
clip.close()
Run Code Online (Sandbox Code Playgroud)

干杯! :)