在python中使用ffmpeg获取视频持续时间

在python中使用ffmpeg获取视频持续时间,python,video,ffmpeg,Python,Video,Ffmpeg,我已经在我的电脑上使用pip ffprobe命令安装了ffprobe,并从安装了ffmpeg 但是,我仍然无法运行列出的代码 我尝试使用以下代码失败 SyntaxError: Non-ASCII character '\xe2' in file GetVideoDurations.py on line 12, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details 有人知道怎么了吗?我没有正确

我已经在我的电脑上使用pip ffprobe命令安装了ffprobe,并从安装了ffmpeg

但是,我仍然无法运行列出的代码

我尝试使用以下代码失败

SyntaxError: Non-ASCII character '\xe2' in file GetVideoDurations.py
on line 12, but no encoding declared; see
http://python.org/dev/peps/pep-0263/ for details
有人知道怎么了吗?我没有正确引用目录吗?我是否需要确保
.py
和视频文件位于特定位置

导入子流程
def getLength(文件名):
结果=subprocess.Popen([“ffprobe”,“filename”],
stdout=subprocess.PIPE,stderr=subprocess.stdout)
返回[x代表result.stdout.readlines()中的x,如果x中的“Duration”]
fileToWorkWith=‪'C:\Users\PC\Desktop\Video.mkv'
getLength(fileToWorkWith)
如果问题有些基本,我会道歉。我所需要的是能够迭代一组视频文件,并获得它们的开始时间和结束时间


谢谢大家!

无需遍历
FFprobe
的输出。存在仅返回输入文件持续时间的:

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

我认为查马斯的第二个评论回答了这个问题:你的剧本中有一个奇怪的角色,要么是因为你用了“而不是a”,要么是因为你有一个带有非英语口音的单词,比如这样的

作为一句话,对于您正在做的事情,您也可以尝试像您一样解析ffmpeg输出(但也许将来我会使用Chamath的ffprobe方法,它看起来更干净):


我们还可以使用ffmpeg获取任何视频或音频文件的持续时间

要安装ffmpeg,请遵循以下步骤

导入子流程
进口稀土
process=subprocess.Popen(['ffmpeg','-i',视频文件的路径],stdout=subprocess.PIPE,stderr=subprocess.stdout)
stdout,stderr=process.communicate()
matches=re.search(r“Duration:\s{1}(?P\d+?):(?P\d+?):(?P\d+\。\d+?),,”,stdout,re.DOTALL)。groupdict()
打印(匹配['hours'])
打印(匹配['minutes'])
打印(匹配['seconds'])
Python代码

<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>

cmnd=['/root/bin/ffmpeg','-i',视频路径]
process=subprocess.Popen(cmnd,stdout=subprocess.PIPE,stderr=subprocess.stdout)
stdout,stderr=process.communicate()
#这与regex匹配,以H:M:S格式获取时间
matches=re.search(r“Duration:\s{1}(?P\d+?):(?P\d+?):(?P\d+\。\d+?),,”,stdout,re.DOTALL)。groupdict()
t_hour=匹配项['hours']
t_min=匹配项['minutes']
t_sec=匹配['seconds']
小时秒=整数(小时)*3600
t_min_sec=int(t_min)*60
t_s_sec=int(四舍五入(浮动(t_sec)))
总秒=小时秒+分钟秒+秒秒
#此匹配1用于获取视频的帧速率
matches1=重新搜索(r'(\d+)fps',stdout)
frame_rate=matches1.group(0)//这将提供20fps
frame_rate=matches1.group(1)//它将给出20
我建议使用FFprobe(FFmpeg附带)

查马斯给出的答案非常接近,但最终对我来说失败了

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)
请注意,我使用的是Python3.5和3.6,这对我来说很有用

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)
如果要将此函数放入类中并在Django(1.8-1.11)中使用,只需更改一行并将此函数放入类中,如下所示:

def get_duration(file):
致:


注意:使用相对路径在本地对我有效,但生产服务器需要绝对路径。您可以使用
os.path.abspath(os.path.dirname(文件))
获取视频或音频文件的路径

您是否尝试添加编码?正如查马斯所说,这种错误是典型的。 将utf-8编码添加到脚本头:

#!/usr/bin/env python
# -*- coding: utf-8 -*- 
基于@llogan指南,使用
ffprobe
更新了解决方案,并指出:
由于
stderr
输出导致的易碎解决方案:
ffmpeg
stderr
输出不用于机器解析和 它被认为是易碎的

我从以下文档()和


实际上,sed是不必要的:
ffmpeg-i file.mp4 2>&1 | grep-o-p“(?我喜欢用ffmpeg构建一个共享库,并用python加载它。
C++代码:

#ifdef_uuwin32__
#定义库类declspec(dllexport)
#否则
#定义LIB_类
#恩迪夫
外部“C”{
#定义\uu STDC\u常量\u宏
#包括“libavformat/avformat.h”
}
外部“C”库类int64\t getDur(const char*url){
AVFormatContext*pFormatContext=avformat_alloc_context();
if(avformat\u open\u输入(&pFormatContext,url,NULL,NULL)){
avformat_free_上下文(pFormatContext);
返回-1;
}
int64\u t t=pFormatContext->duration;
avformat_close_输入(&P格式上下文);
avformat_free_上下文(pFormatContext);
返回t;
}
然后使用gcc编译它并获得一个共享库。
Python代码:

从ctypes导入*
lib=CDLL('/the/path/to/your/library')
getDur=lib.getDur
getDur.restype=c_longlong
duration=getDur('文件的路径/URL')

它在我的python程序中运行良好。

解析来自
ffmpeg
的输出是脆弱的,不适合脚本使用。请改用
ffprobe
,如中所示。解析来自
ffmpeg
的输出是脆弱的,不适合脚本使用。请改用
ffprobe
,如中所示。您可能应该这样做添加一个解释,说明这对刚接触ffmpeg/ffprobe和Python的人有什么作用。@JavierC.H.不要使用字符串格式来生成bash命令。如果用户提供
input\u video
,您就让他们从Python代码中随意运行bash命令。是否可以将其作为HH:MM:SS格式输出放入
ffmpeg-i file.mkv2>&1|grep-o-P“(?对于持续时间为
N/a
的任何人,可能需要重新打包文件以向其添加标题。不建议查看
shell=True
grep
如果单独使用ffprobe是不必要的。例如ee和。此外,ffmpeg的stderr输出不用于机器解析,并且被认为是脆弱的。这就是为什么FFT探针用于@llogan:Than
def get_duration(file):
def get_duration(self, file):
#!/usr/bin/env python
# -*- coding: utf-8 -*- 
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()
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()