V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
tinypig
V2EX  ›  Python

如何高效的遍历一个海量视频的文件夹获取所有视频 Metadata?

  •  
  •   tinypig · 2016-12-18 03:17:19 +08:00 · 3692 次点击
    这是一个创建于 2901 天前的主题,其中的信息可能已经有所发展或是发生改变。

    需要统计服务器上的视频信息,写了个脚本,使用 MediaInfo 获取视频信息,但是因为文件数量比较多,便利效率比较低(单进程每秒 1.5 个文件),后来使用了 Multiprocessing 多进程,可以达到效率是高了,但是一个小时也才能获取到 1.5 万左右的文件信息。

    求问,有什么比较好的方法可以较高提高效率么?

    注:视频文件在文件服务器上,千兆网络挂载过来,使用了 Multiprocessing 后,遍历时速度带宽大约到了 800~900M,主要代码如下:

    pool_size = multiprocessing.cpu_count() * 2 - 4
    with multiprocessing.Pool(pool_size) as Pool:
        walk = os.walk(path)
        fn_gen = itertools.chain.from_iterable((os.path.join(root, file) for file in files) for root, dirs, files in walk)
        Pool.map(video_handler, fn_gen)
    
    10 条回复    2016-12-19 10:03:53 +08:00
    mrytsr
        1
    mrytsr  
       2016-12-18 09:12:22 +08:00 via Android
    ffprobe
    Septembers
        2
    Septembers  
       2016-12-18 10:44:59 +08:00   ❤️ 2
    用 pymediainfo 然后在本地执行
    (只是获取 mediainfo 并不需要完整读取文件
    (但是你通过网络挂载的话可能不支持 seek 导致需要读取完整文件
    (这或许是主要导致慢的原因
    264768502
        3
    264768502  
       2016-12-18 12:09:15 +08:00 via Android   ❤️ 1
    这个 io 是瓶颈,试试多线程的线程池(可以试试开到 10 以上)+pymediainfo(mediainfo 的源代码里有 python 的用例)
    网络挂载是 smb/nfs/webdav/ftp?
    tinypig
        4
    tinypig  
    OP
       2016-12-18 12:57:49 +08:00
    @Septembers
    @264768502
    用的是 pymediainfo ,通过 cifs 挂载的。
    cpu 每个核的负载都是在 30~50%这样
    264768502
        5
    264768502  
       2016-12-18 16:23:01 +08:00 via Android   ❤️ 1
    如果有机会的话可以换个协议么,比如 nfs

    说 cpu 负载是说本地还是服务器的呢
    cifs/smb 也有可能是服务器单核性能的瓶颈

    另外最好是用协程的 pool,会比线程进程池更高效.(除非视频处理跟复杂,那样的话还是用进程池)
    tinypig
        6
    tinypig  
    OP
       2016-12-18 16:33:50 +08:00
    @264768502
    CPU 负载是说本地负载。
    我昨天试过用 Gevent.Pool ,效率不高,跟单进程的差不多,也有可能是我用的方式不对,我只是把上面 Multiprocessing 的 pool 换成了 gevent 的 pool 。
    Septembers
        7
    Septembers  
       2016-12-18 18:04:17 +08:00 via iPad
    @tinypig 建议放置在 远程执行
    goodniuniu
        8
    goodniuniu  
       2016-12-18 18:23:29 +08:00 via iPhone
    明天回去试试代码,感觉瓶颈在网络上
    SlipStupig
        9
    SlipStupig  
       2016-12-19 02:41:10 +08:00   ❤️ 1
    这种东西本身就是需要一个高 IO 的问题,有条件换成 HDFS (能配 ssd 就更好了) MapReduce 会快很多,不可能换的话,几个方面考虑:
    1.使用 pypy
    2.不要把文件下回来然后处理,最好能在远程处理完
    3.视频读取媒体信息不需要完整读取的,所以直接解析文件头部就可以得到了,如果不想自己写解析函数,如果读取大文件的时候可以用 mmap 去读取而不是直接 fopen
    4.用 gevent ,记得先得使用 monkey patch 否则无效
    tinypig
        10
    tinypig  
    OP
       2016-12-19 10:03:53 +08:00
    @SlipStupig
    1. 使用扫描脚本是写在 Django admin 的 commands 里,方便操作数据库 :)所以之前没考虑用 pypy
    2. 这个业务只是一个外部统计使用的,所以没有办法部署到相应的文件服务器上,只能通过网络挂载。
    3. 我现在使用的获取媒体信息的库是 MediaInfo (对应的 pymediainfo ),看介绍他应该就是只下载一部分内容即可的,稍后我测试一下看看。
    4. 这一点好像我忽略了,只是替换了它的 Pool ,稍后我尝试一下。

    感谢。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3327 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 00:17 · PVG 08:17 · LAX 16:17 · JFK 19:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.