基于moviepy库利用图片制作简易视频

  • 改进了程序,增加了多线程运行,大幅提高速度


  1. 利用一个图片库,每次从中抽取一定数量的图片,裁剪成同一尺寸后,利用moviepy这个库的ImageSequenceClip批量生成简易视频,可加入音频。
  2. 每次运行程序都会将用于储存的文件夹刷新清空
  3. 加入了背景音乐,还有水印图片的镶嵌,因为利用moviepy的直接图片嵌入失败,也没有找到合适的解决方案,所以利用PIL先将图片拼接到每张图片上,在用moviepy合成视频,最后加上背景音乐。
  4. 更新!增加了多线程机制,提高生成速度
import moviepy.editor
from PIL import Image,ImageFile  
import os.path  , random, shutil
import glob  
from pydub import AudioSegment

ImageFile.LOAD_TRUNCATED_IMAGES = True
fileDir = "图库"    #源图片文件夹路径
cut_Dir = "image"    #移动到新的文件夹路径\裁剪图片源
tarDir =cut_Dir+"/"
ima_url = "image/images"      #用于存放裁剪后的图片
v_url = "vedio"       #视频存放的文件夹
vedio_url = v_url+"/new"    #最后为视频保存的文件名
logo_url = "logo/二维码图.png"    #二维码的位置
music_url = "music"       #音乐所处文件夹
#主要参数设置
photo_num = 25    #一个视频使用多少图片
vedio_num = 1    #制作视频的数量

# 加水印/二维码
# logo = Image.open(logo_url)

#从图片库中提取图片
def moveFile(fileDir):
    pathDir = os.listdir(fileDir)    #取图片的原始路径
    # filenumber=len(pathDir)
    # rate=0.026    #自定义抽取图片的比例,比方说100张抽10张,那就是0.1
    picknumber=int(photo_num) #按照rate比例从文件夹中取一定数量图片
    sample = random.sample(pathDir, picknumber)  #随机选取picknumber数量的样本图片
    # print (sample)
    Dir = fileDir + '/'
        
    for name in sample:
        # print(name)
        fileDir = Dir + name
        # print(fileDir)
        shutil.copy(fileDir, tarDir+name)
        # print(tarDir+name)
    # print(tarDir+"logo.jpg",logo)
    shutil.copy(logo_url,tarDir+"logo.jpg")
    return

def musicFile(fileDir):
    pathDir = os.listdir(fileDir)    #取音乐的原始路径
    sample = random.sample(pathDir, 1) 
    print(fileDir+'/'+sample[0])
    return fileDir+'/'+sample[0]

#把文件钟图片的分辨率进行修改
def convertjpg(jpgfile,outdir,width=1280,height=720):     
    img=Image.open(jpgfile) 
    img=img.convert('RGB') 
    try:  
        new_img=img.resize((width,height),Image.BILINEAR)
        # 加水印图片
        # new_img.paste(logo)     
        new_img.save(os.path.join(outdir,os.path.basename(jpgfile)))  
    except Exception as e: 
        print(e)  

#刷新保存视频的文件夹,避免文件存在无法写入
try:
    os.mkdir("vedio")
except:
    shutil.rmtree("vedio")
    os.mkdir("vedio")


for i in range(vedio_num):    #视频制作数量
    #图片文件夹的刷新
    try:
        os.mkdir(tarDir)      #尝试创建,若存在则失败
    except:
        # print("文件夹已存在")
        shutil.rmtree(tarDir)      #删除已有文件夹,重新创建
        os.mkdir(tarDir)
        os.mkdir(ima_url)        #创建多级文件
    
    #图片的挑选
    moveFile(fileDir)
    #图片裁剪
    rurl = cut_Dir +r"/*.jpg"
    for jpgfile in glob.glob(rurl):  #裁剪图片
        convertjpg(jpgfile,ima_url)  #图片写入的地址
    #生成视频
    try:
        image_clip = ImageSequenceClip(ima_url, fps=0.5)    #生成视频
    except:
        print("图片有错误,放弃制作")
        continue
    #写入视频
    vurl = vedio_url+"%d" %(i)
    vurl = vurl+".mp4"
    # print(vurl) 

    audio_background = AudioFileClip(musicFile(music_url))
    
    image_clip = image_clip.set_audio(audio_background)    #加入音乐

    image_clip.write_videofile(vurl)     #将视频写入本地

改进了程序,增加了多线程运行,大幅提高速度

from moviepy.editor import *
import moviepy.editor
from PIL import Image,ImageFile  
import os.path  , random, shutil
import glob  
from pydub import AudioSegment
import time
from multiprocessing.pool import ThreadPool
import psutil

ImageFile.LOAD_TRUNCATED_IMAGES = True
fileDir = "图库"    #源图片文件夹路径
cut_Dir = "image"    #移动到新的文件夹路径\裁剪图片源
tarDir =cut_Dir+"/"
ima_url = "image/images"      #用于存放裁剪后的图片
v_url = "vedio"       #视频存放的文件夹
vedio_url = v_url+"/new"    #最后为视频保存的文件名
logo_url = "logo/二维码图.png"    #二维码的位置
music_url = "music"       #音乐所处文件夹
#主要参数设置
photo_num = 25    #一个视频使用多少图片
vedio_num = 10    #制作视频的数量

# 加水印/二维码
# logo = Image.open(logo_url)

#从图片库中提取图片
def moveFile(fileDir,writeDir):
    pathDir = os.listdir(fileDir)    #取图片的原始路径
    # filenumber=len(pathDir)
    # rate=0.026    #自定义抽取图片的比例,比方说100张抽10张,那就是0.1
    picknumber=int(photo_num) #按照rate比例从文件夹中取一定数量图片
    sample = random.sample(pathDir, picknumber)  #随机选取picknumber数量的样本图片
    # print (sample)
    Dir = fileDir + '/'
        
    for name in sample:
        # print(name)
        fileDir = Dir + name
        # print(fileDir)
        shutil.copy(fileDir, writeDir+name)
        # print(tarDir+name)
    # print(tarDir+"logo.jpg",logo)
    shutil.copy(logo_url,writeDir+"logo.jpg")
    return

def musicFile(fileDir):
    pathDir = os.listdir(fileDir)    #取音乐的原始路径
    sample = random.sample(pathDir, 1) 
    print(fileDir+'/'+sample[0])
    return fileDir+'/'+sample[0]

#把文件钟图片的分辨率进行修改
def convertjpg(jpgfile,outdir,width=1280,height=720):     
    img=Image.open(jpgfile) 
    img=img.convert('RGB') 
    try:  
        new_img=img.resize((width,height),Image.BILINEAR)
        # 加水印图片
        # new_img.paste(logo)     
        new_img.save(os.path.join(outdir,os.path.basename(jpgfile)))  
    except Exception as e: 
        print(e)  



def make(num):
    tarDir = cut_Dir+str(num)+"/"
    ima_url = tarDir+"images"
    try:
        os.mkdir(tarDir)      #尝试创建,若存在则失败
        os.mkdir(ima_url)        #创建多级文件
    except:
        # print("文件夹已存在")
        shutil.rmtree(tarDir)      #删除已有文件夹,重新创建
        os.mkdir(tarDir)
        os.mkdir(ima_url)        #创建多级文件
        
    #图片的挑选
    moveFile(fileDir,tarDir)
    #图片裁剪
    rurl = cut_Dir +"/*.jpg"
    for jpgfile in glob.glob(rurl):  #裁剪图片
        convertjpg(jpgfile,ima_url)  #图片写入的地址
    #生成视频

    image_clip = ImageSequenceClip(ima_url, fps=0.5)    #生成视频

    #写入视频
    vurl = vedio_url+"%d" %(num)
    vurl = vurl+".mp4"
    # print(vurl) 

    audio_background = AudioFileClip(musicFile(music_url))
        
    image_clip = image_clip.set_audio(audio_background)    #加入音乐

    image_clip.write_videofile(vurl)     #将视频写入本地
    shutil.rmtree(tarDir)       #删除前面用于缓存图片的文件夹

def main():
    starttime =time.time()
    #刷新保存视频的文件夹,避免文件存在无法写入
    try:
        os.mkdir("vedio")
    except:
        shutil.rmtree("vedio")
        os.mkdir("vedio")
    pool = ThreadPool(psutil.cpu_count())    #根据cpu线程数建立线程池
    returnValues = pool.map(make, range(vedio_num))

        
    endtime=time.time()
    print(endtime-starttime)

main()