销售小姐姐找我问我们的视频时长一共有多少,看着目录里面密密麻麻的视频,这要是手动统计,绝对会让我蛋疼得很。
好在查了一下,ffmpeg有一个python的apiwrapper。
在这里 https://github.com/kkroening/ffmpeg-python
使用比较简单,没啥好说的,我们这里用的是这个api
ffmpeg.probe(file)
他会返回一个dict,所有视频的信息都会包含在这个dict里面,当然也包含视频时长的信息。
需要注意这个api里面返回的视频时长信息都是字符串,需要给他做一下转换,参考下面的代码处理。
知道了这些,我们就可以来写一个简单的统计当前目录视频时长的脚本了。
我们课程要求必须是mp4格式的,所以就省了很多麻烦,只关注mp4文件就好了。
单线程版本
import os
import ffmpeg
t = 0
for r,ds,fs in os.walk('.'):
for f in fs:
if f.endswith('mp4'):
file=os.path.join(r,f)
t=t+ float(ffmpeg.probe(file)['format']['duration'])
print(t/60/60)
可是单线程版本好慢啊,半天才会返回结果,考虑到这个api是调用ffmpeg的命令行的,所以肯定能够并行化。
来祭出multiprocessing这个半死不拉活的大杀器。
没办法,python的多线程是残废的,正经应该用多进程,不过这里是调用另外一个程序,所以多线程也可以用。
多线程版本
import os
import numpy as np
import ffmpeg
from multiprocessing.dummy import Pool as ThreadPool
path = '.'
files = []
for r,ds,fs in os.walk(path):
for f in fs:
if f.lower().endswith('mp4'):
file=os.path.join(r,f)
files.append(file)
p = ThreadPool()
ret = p.map(lambda file: float(ffmpeg.probe(file)['format']['duration']), files)
p.close()
p.join()
print(np.sum(ret)/60/60)
里面那个dummy表示我们使用的是multioricessing的多线程版本而不是多进程版本,如果要使用多进程版本,去掉这个dummy就行。
不过使用多进程的话,要小心这里用的是lambda,他不能很好的配合多进程,老老实实写个函数比较好。
再来一个分目录多线程版本,可以看到每个目录下面的情况
import os
import numpy as np
import ffmpeg
from multiprocessing.dummy import Pool as ThreadPool
path = '.'
def count_duration(path):
files = []
for r, ds, fs in os.walk(path):
for f in fs:
if f.lower().endswith('mp4'):
file = os.path.join(r, f)
files.append(file)
p = ThreadPool()
ret = p.map(lambda file: float(
ffmpeg.probe(file)['format']['duration']), files)
p.close()
p.join()
return(np.sum(ret) / 60 / 60)
dirs = [os.path.join(path, d) for d in os.listdir(path)]
for d in dirs:
if os.path.isdir(d):
t = count_duration(d)
print(f'[{d}] \t=>\t [{t}]'.format(d, t))
这里用到了fstring,很方便。