美文网首页
python爬虫脚本下载视频,同时借助FFmpeg合并视频

python爬虫脚本下载视频,同时借助FFmpeg合并视频

作者: JXP大鹏 | 来源:发表于2018-09-08 22:36 被阅读0次

    requests是简洁的Python http库, 相较Python标准库urllib, requests更加人性化。
    用requests下载视频或大文件时,默认是把请求到的相应数据完整下载到内存中。这样假如下载一个2G的视频,肯定会非常吃内存,也可能在下载过程中中断而前功尽弃。

    可以使用requests流式请求来下载, 在requests加入 stream=Ture参数来开启流式请求,之后就可以一点点下载到磁盘上。

    import requests
    r = requests.get(file_url, stream=True)
    

    之后就可以使用response的iter_content数据来分块下载视频,并且还支持断点续传

    with open('a.mp4', 'wb') as f:
        for data in r.iter_content(chunk_size=1024):
            f.write(data)
    

    但有些网站的视频是分段的, 要合并视频这就要使用FFmpeg了, FFmpeg支持Windows, Linux和Mac三大平台,在终端或者命令行中操作。
    之后我会写一篇FFmpeg的安装方法
    快速合并视频的方法

    ffmpeg -y -f concat -safe 0 -i list.txt -c copy out.mp4
    

    其中list.txt是待合并视频文件的列表,结构如下

    file 'video1.mp4'
    file 'video2.mp4'
    

    在python内可以简单的用os模块的system方法调用终端命令,不过可以用更好的subprocess模块, subprocess提供了多个方法, 在Python3.5后提供了run, 不过python2还没有可以使用call或check_call。

    多视频合并也会产生很多中间文件,这些文件的清除也是一件很麻烦的事情,因此可以使用python的临时文件模块 tempfile ,tempfile模块提供了一个NamedTemporaryFile方法 可以创建一个临时文件,默认路径在/tmp下,关闭后自动删除。

    最后你肯定不希望在下载第二个视频时把第一个视频覆盖掉,那么在视频下载前可以切换到一个指定目录中保存文件,下载完成后在切换回来,直接写在函数里显然不太好看,可以把切换目录的工作写在装饰器内。

    #coding=utf-8
    import os
    import requests
    import subprocess
    from tempfile import NamedTemporaryFile
    
    def switch_dir(fun):
        def wapper(*args, **kwargs):
            old_path = os.getcwd()
            path = kwargs.get('path') or '/tmp'
            os.chdir(path)
            try:
                return fun(*args, **kwargs)
            except:
                raise e
            finally:
                os.chdir(old_path)
        return wapper
    
    @switch_dir
    def down_video(urls, output='out.mp4', chuck_size=1024, *args, **kwargs):
        #urls: 待下载的视频url列表 list, 应至少包含一个url
        #可选参数
        #ouptut 最终保存的视频文件名
        #chuck_size 下载视频分块大小   
        #return: 视频文件名   
    
        if len(urls) == 1:
            r = requests.get(url, stream=True)
            with open(ouptut, 'wb') as f:
                for data in r.iter_content(chuck_size=chuck_size):
                    f.write(data)
            return ouptut
    
        video_list = NamedTemporaryFile(dir='.') # 创建一个临时文件记录分段视频的文件名, dir指定在当前工作目录创建
        file_list = [] # 创建一个临时列表 保存视频文件对象
        for url in urls:
            video_file = NamedTemporaryFile(dir='.', suffix='.mp4') # suffix指定文件后缀 
            r = requests.get(url, stream=True)
            for data in r.iter_content(chunk_size=chuck_size):
                video_file.write(data)
                video_file.file.flush() # 记得写入磁盘
            video_list.write("file '{}'\n".format(video_file.name)) # video_file.name 获取视频文件的名字
            video_list.file.flush()
            file_list.append(video_file) # 临时文件对象存如列表方便合并完成后关闭
        # 合并视频 check_call方法会暂时阻塞主进程直到合并完成
        sub = subprocess.check_call(
            ['ffmpeg', '-y', '-f', 'concat', '-safe', '0', '-i', video_list.name, '-c', 'copy', output],
            stdout=-1, 
            stderr=-1)
        (i.close() for i in video_list)
        video_list.close()
        return output
    

    这样就算完成了
    调用使用

    urls = [
      "http://..."
    ]
    path = '/home/myvideo'
    down_video(urls, path=path)

    相关文章

      网友评论

          本文标题:python爬虫脚本下载视频,同时借助FFmpeg合并视频

          本文链接:https://www.haomeiwen.com/subject/enolgftx.html