正则表达式无法直接读取音视频文件时长,只能从工具(如ffprobe、mediainfo)输出的文本中匹配时间格式;需先调用外部工具获取元数据,再用多模式正则提取并转换为秒数。

正则表达式本身不能直接读取音频或视频文件的时长,它只能从已有的文本中匹配时间格式(如01:23:45.678、124m 32s、PT2H3M45S等)。要提取真实媒体文件的时长,必须先通过外部工具(如 ffprobe、mediainfo 或 Python 的 moviepy/mutagen)获取元数据文本,再用正则从中抽取结构化的时间字段。
明确时长信息的常见文本来源
原始媒体文件不含可读文本,需借助命令行工具生成描述性输出:
-
ffprobe(推荐):FFmpeg 自带,轻量、准确、跨平台。执行
ffprobe -v quiet -show_entries format=duration -of default=nw=1 input.mp4可输出类似duration=147.82的纯数字(单位:秒);加-show_entries stream=duration或用-sexagesimal可得时分秒格式。 -
mediainfo:输出更易读,例如
Duration : 2 h 27 min或Duration : 2h 27mn 18s 456ms,适合用正则做柔性匹配。 -
Python 脚本调用:用
subprocess.run执行上述命令,捕获 stdout 字符串,再用re.search()提取。
针对不同格式设计高容错正则模式
避免写死单一格式,应覆盖常见变体。以下为实用正则示例(Python 语法),含注释说明关键点:
-
匹配 HH:MM:SS(.mmm) 格式(如
02:03:04.567):r'(\d{1,2}):(\d{2}):(\d{2})(?:\.(\d{1,3}))?'
捕获组分别对应时、分、秒、毫秒(毫秒为非必需)。 -
匹配 Xh Xm Xs 带空格/符号的自由格式(如
2h 27mn 18s或124 m 32 s):r'(?i)(\d+)\s*(?:h|hr|hour|hours)?\s*(?:(\d+)\s*(?:m|mn|min|minute|minutes)?)?\s*(?:(\d+)\s*(?:s|sec|second|seconds)?)?'
使用(?i)忽略大小写,各时间单位均为可选,空格灵活处理。 -
匹配 ISO 8601 持续时间(如
PT2H3M45S):r'PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?'
注意P和T固定前缀,H/M/S 各段独立可选。
提取后统一转换为标准秒数(便于计算与存储)
仅匹配不等于解析。拿到各组数字后,需按权重换算:
- 若匹配到
HH:MM:SS.mmm:秒数 =int(HH)*3600 + int(MM)*60 + int(SS) + float("0."+mmm.ljust(3,"0")) - 若匹配到
Xh Ym Zs:秒数 =int(X or 0)*3600 + int(Y or 0)*60 + int(Z or 0) - 若只有总秒数字符串(如
"duration=147.82"):直接用float(re.search(r'duration[=:]\s*(\d+\.?\d*)', text).group(1))
建议封装一个函数,输入原始文本,返回浮点型总秒数,内部自动尝试多种正则并取首个成功结果。
注意事项与避坑提醒
正则不是万能解,实际使用中需注意:
- ffprobe 的
-sexagesimal输出是00:02:03.456000,但默认-of default是小数秒——优先用后者,更精确且无需正则。 - 不要用正则解析二进制文件或未经解码的媒体流,会失败或误匹配。
- 某些工具(如旧版 mediainfo)可能省略前导零或合并单位(如
"2h3m"),正则中要用\s*和可选分组应对。 - 中文环境输出可能含“时”“分”“秒”,需在正则中加入 Unicode 字符支持,如
r'(\d+)\s*[时h]\s*(\d+)\s*[分m]\s*(\d+)\s*[秒s]'。

















