美文网首页
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