根据公司需要,最近需要制作大量的食谱和美食视频,代码如下:
from moviepy.editor import *
import pandas as pd
from TTS import TTS
import time,random,requests,os,re
#遍历文件夹,找出所有mp4,flv视频或者jpg,png图片或者acc,mp3音频文件
def func(filepath,form_lst,clip_path = []):
files = os.listdir(filepath)#查看当前目录中的文件
#print(files)
for file in files:#拿到每一个文件名
file_p = os.path.join(filepath,file)#形成文件的地址
# print(file_p)
file_name = file_p.split('.')
if os.path.isdir(file_p):#如果文件是文件夹
clip_path = func(file_p,form_lst,clip_path = clip_path)
elif file_name[-1] in form_lst:
file_p = os.path.normpath(file_p)
clip_path.append(file_p)
# print(clip_path)
else:
continue
return clip_path
def get_img(url,f_path, count = 0, max_count = 3):
ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36'
headers = {'User-Agent':f'{ua}'}
try:
time.sleep(random.random() * 3)
r = requests.get(url=url, headers=headers, timeout=30)
# r.raise_for_status()
# r.encoding = 'utf-8'
# print(r.text)
with open(f_path, 'wb') as f:
f.write(r.content)
return f_path
except:
count += 1
print(f'第{count}次爬取{url}失败')
time.sleep(30)
if count < max_count:
return get_img(url=url, count=count)
def add_logo(clip):
#给视频加水印
logo = (TextClip("制作:轩轩和格格",font='SIMYOU.TTF',fontsize=30,color='white',bg_color='white',stroke_color='pink',stroke_width=2,method='label')
.set_duration(clip.duration) # 水印持续时间
.resize(height=50) # 水印的高度,会等比缩放
.margin(left=40, bottom=40, opacity=0) # 水印边距和透明度
.set_pos(("right", "bottom"))) # 水印的位置
clip_add_logo = CompositeVideoClip([clip, logo])
return clip_add_logo
def make_mp4(caipu_title_img,caipu_name,caipu_material,caipu_step_img,caipu_step_txt):
# 定义画面尺寸和帧率
h, w ,fps= 720, 1280,30
#语音带#读不了报错,需要先去掉
caipu_material = re.sub('[#]','',caipu_material)
caipu_step_txt = re.sub('[#]','',caipu_step_txt)
# windows路径名不能含有特殊字符,因此我们在菜谱名字里面去掉,方便后面使用作为保存文件名
caipu_name = re.sub('[#\/:*?"<>|]', '', caipu_name)
if len(caipu_name) > 12:
caipu_name0 = caipu_name[:12]
else:
caipu_name0 = caipu_name
# print(caipu_name0)
f_path = os.path.normpath(f'./babyfood/{caipu_name}')
if not os.path.exists(f_path):
os.makedirs(f_path)
# 1镜头:片头.封面背景
#片头语音
voice_begin = random.choice(func(filepath='./片头', form_lst=['mp3']))
voice_begin = AudioFileClip(voice_begin)
#食谱名字语音
TTS(caipu_name, f_path + '\\name.mp3')
voice_name = AudioFileClip(f_path + '\\name.mp3')
#组合成开场语音
voice0 = concatenate_audioclips([voice_begin,voice_name])
#语音时长决定视频时长
t0 = voice0.duration
#片头背景图
bg_img = random.choice(func(filepath='./封面', form_lst=['png', 'jpg', 'jpeg']))
# 片头背景图实例化
bg_img_cover = ImageClip(bg_img, duration=t0).resize(width=w)
# 片头主图
# 保存链接上的标题图到本地电脑,获取本地地址
title_img = get_img(url=caipu_title_img, f_path=f_path + '\\title_img.jpg')
print(title_img)
#片头主图实例化
Img_cover = ImageClip(title_img, duration=t0)
# 片头标题
text_cover = TextClip(caipu_name0, font='titlehupo.TTF', fontsize=100, color='white').set_position(
'center').set_duration(t0)
# 片头视频片段,无声音
clip0 = CompositeVideoClip([bg_img_cover, Img_cover, text_cover]).set_audio(voice0).resize(width=w, height=h)
# 给片头片段加logo
clip0 = add_logo(clip=clip0)
# 所有镜头都保存到列表里,方便后面连接起来组合最终视频
clip_steps = [clip0]
# 2镜头:第一段主体视频:菜谱名称,沿用封面的参数或者用主题参数,方便后续调整单独列出.
# # 第1个主镜头的语音:名称
# TTS(caipu_name, f_path + '\\name.mp3')
# voice1 = AudioFileClip(f_path + '\\name.mp3')
# t1 = voice1.duration
# # 镜头由背景图\主图\字幕三个图层构成,视频时长都根据语音时长来定
# bg_img1 = ImageClip(bg_img, duration=t1).resize(width=w)
# Img1 = ImageClip(title_img, duration=t1)
# Img1 = add_logo(Img1).set_position("center").resize(width=w)
# text1 = TextClip(caipu_name0, font='titlehupo.TTF', fontsize=100, color='white').set_position(
# 'center').set_duration(t1)
#
# clip1 = CompositeVideoClip([bg_img1, Img1, text1]).set_audio(voice1).resize(width=w, height=h)
# clip_steps.append(clip1)
# # 第2个主镜头的语音:所需食材(所需食材最好再分解成小片段)
# n = 0
# for caipu_mt in caipu_material.split(';'):
# if caipu_mt == None:
# continue
# n += 1
# TTS(caipu_mt, f_path + f'\\material{n}.mp3')
# voice2 = AudioFileClip(f_path + f'\\material{n}.mp3')
# # 语音时长决定视频时长
# t2 = voice2.duration
# # 镜头由背景图\主图\字幕三个图层构成,视频时长都根据语音时长来定
# bg_img2 = ImageClip(bg_img, duration=t2).resize(width=w)
# Img2 = ImageClip(title_img, duration=t2)
# Img2 = add_logo(Img2).set_position('center').resize(width=w * 0.6)
# text2 = TextClip(caipu_mt, font='SIMYOU.TTF', fontsize=20, color='white').margin(bottom=50,
# opacity=0).set_position(
# 'bottom').set_duration(t2)
# clip2 = CompositeVideoClip([bg_img2, Img2, text2]).set_audio(voice2).resize(width=w, height=h)
# clip_steps.append(clip2)
i = 0
# 每一个操作步骤做成一个片段
for step_img_url, step_txts in zip(caipu_step_img.split(';'), caipu_step_txt.split(';')):
# 如果末尾是符号,分割出来的就会是None,需要过掉
if step_img_url == '' or step_txts == '':
continue
print(step_img_url)
step_img = get_img(url=step_img_url, f_path=f_path + f'\\step{i}.jpg')
#把所需食材加到第一个步骤里面
if i == 0:
step_txts = step_txts.split(',') + ['食材清单:'] + caipu_material.split(';')
else:
step_txts = step_txts.split(',')
for step_txt in step_txts:
# 如果末尾是符号,分割出来的就会是None,需要过掉
if step_txt == '':
continue
i += 1
# 步骤语音
TTS(step_txt, f_path + f'\\step{i}.mp3')
voice3 = AudioFileClip(f_path + f'\\step{i}.mp3')
# 背景图
bg_img3 = ImageClip(bg_img, duration=voice3.duration).resize(width=w)
# 步骤图从网络连接保存到本地,获取本地地址
# 步骤主图
img3 = ImageClip(step_img, duration=voice3.duration)
img3 = add_logo(img3).set_position('center').resize(width=w * 0.6)
# 步骤文字
text3 = TextClip(step_txt, font='SIMYOU.TTF', fontsize=20, color='white').margin(bottom=50,
opacity=0).set_position(
'bottom').set_duration(voice3.duration)
# 步骤视频片段
clip_step = CompositeVideoClip([bg_img3, img3, text3]).set_audio(voice3).resize(width=w, height=h)
# 步骤的片段都加到列表里面去
clip_steps.append(clip_step)
# 形成主体视频
main_clip = concatenate_videoclips(clip_steps, method='compose').resize(width=w, height=h)
# 获取视频的配音
main_audio = main_clip.audio
# 添加背景音乐和片尾
bg_music = random.choice(func(filepath='背景音乐', form_lst=['mp3'], clip_path=[]))
print(bg_music)
background_music = AudioFileClip(bg_music)
# 设置背景音乐循环,时间与视频时间一致
bg_audio = afx.audio_loop(background_music, duration=main_clip.duration)
# 视频声音和背景音乐,音频叠加
audio_clip_add = CompositeAudioClip([main_audio.volumex(1.5), bg_audio.volumex(0.3)]).set_duration(
main_clip.duration)
# 视频写入背景音
main_video = main_clip.set_audio(audio_clip_add)
clip_tail = VideoFileClip(random.choice(func(filepath='./片尾', form_lst=['mp4'], clip_path=[]))).resize(width=w,
height=h)
final_clip = concatenate_videoclips([main_video, clip_tail], method='compose').resize(width=w, height=h)
date = time.strftime('%Y%m%d', time.localtime())
out_put_path = f'./out_put'
if not os.path.exists(out_put_path):
os.mkdir(out_put_path)
final_clip.write_videofile(f'{out_put_path}/{date}{count}{caipu_name}.mp4', bitrate='1800k', fps=fps)
def main(count):
#对原素材进行处理一下问题
# caipu = pd.read_excel('caipu20221205.xlsx')
#
# caipu_names = caipu['宝宝辅食菜谱名称']
# caipu_materials = caipu['所需食材']
# caipu_step_txts = caipu['制作步骤文字说明']
# caipu_step_imgs = caipu['制作步骤配图']
# caipu_title_imgs = caipu['菜谱主图']
# for i in range(101):
# caipu['菜谱主图'][i] = str(caipu_step_imgs[i]).split(';')[-1]
#
# for i in range(len(caipu_names)):
# caipu['制作步骤文字说明'][i] = str(caipu['制作步骤文字说明'][i]).replace(' ','').replace('\t','')
# caipu['所需食材'][i] = str(caipu['所需食材'][i]).replace(' ','')
#
# caipu.to_excel('baby_caipu.xlsx', sheet_name="baby_caipu", index=False)
#处理字幕和图片
caipu = pd.read_excel('baby_caipu.xlsx')
caipu_title_imgs = caipu['菜谱主图']
caipu_names = caipu['宝宝辅食菜谱名称']
caipu_materials = caipu['所需食材']
caipu_step_imgs = caipu['制作步骤配图']
caipu_step_txts = caipu['制作步骤文字说明']
for caipu_title_img,caipu_name,caipu_material,caipu_step_img,caipu_step_txt in list(zip(caipu_title_imgs,caipu_names,caipu_materials,caipu_step_imgs,caipu_step_txts))[::-1][count:]:
time.sleep(random.random() * 2)
if all([caipu_title_img, caipu_name, caipu_material, caipu_step_img, caipu_step_txt]) == False:
continue
try:
make_mp4(caipu_title_img=caipu_title_img,caipu_name=caipu_name,caipu_material=caipu_material,caipu_step_img=caipu_step_img,caipu_step_txt=caipu_step_txt)
except:
print(f'第{count}个视频出错,重新执行')
main(count=count)
print(f'今日已完成第{count}个视频')
count += 1
if __name__ =='__main__':
count = 26
main(count=count)