moviepy 简介
MoviePy是一个用于视频修改的Python模块,它可被用于一些根本操作(如剪切、拼接、刺进标题)、视频合成(即非线性修改)、视频处理和创立高档特效。它可对大多数常见视频格式进行读写(来源于官方文档)【底层是使用 ffmpeg
进行操作视频和音频,使用ImageMagick
进行操作图片】
由此可知,咱们能够通过一些图片,视频等资料,能够自动化的批量生成一大批无脑视频
脚本传送门
目录结构
将案牍转成语音
将准备好的脚本文件写入 content.txt
中,将脚本转成音频
文字转语音有现成的大量方案,本文使用Google的gtts
进行将文字转语音,先将脚本文件中按照标点符号离隔进行转成每一个语音,然后使用 ffmpeg
将语速调快至本来的1.2倍(本来转出来的太慢了),并核算每一句话的播映时长,用来均匀核算每一张图片应该播映多少秒,文件名包括每一句话的案牍【用来做字幕,播映时长】
一件件令人惊叹的作品在他的手中诞生_duration_5.000000.mp3
代码所示
def text_to_voice():
try:
shutil.rmtree('./tts')
os.mkdir('./tts')
except:
pass
voice = []
content = open('content.txt').read()
contents = re.split(r'[。!??,,]', content)
for content in contents:
content = content.strip()
if not len(content):
continue
filename = './tts/%s.mp3' % content
# 转语音
g_tts = gTTS(content, lang='zh-CN')
g_tts.save(filename)
# 调整语速 为 1.2 倍速
sound = AudioSegment.from_mp3(filename)
duration = int(sound.duration_seconds)
update_speed_filename = './tts/%s_duration_%f.mp3' % (content, math.ceil(duration * 0.85))
cmd = "ffmpeg -y -i %s -filter_complex \"atempo=tempo=%s\" %s" % (filename, '1.2', update_speed_filename)
res = subprocess.call(cmd, shell=True)
if res == 0:
os.remove(filename)
voice.append(update_speed_filename)
print(update_speed_filename)
return voice
获取一切图片
def get_all_files(path):
files = []
for root, dirs, filenames in os.walk(path):
for filename in filenames:
files.append(os.path.join(root, filename))
return files
将图片格式化为固定大小
def resize_images(image_path):
# 打开图片
image = Image.open(image_path)
width = 1400 # 固定宽度
height = 787 # 固定高度
# 核算缩放份额
original_width, original_height = image.size
scale = min(width / original_width, height / original_height)
# 核算缩放后的大小
new_width = int(original_width * scale)
new_height = int(original_height * scale)
# 缩放图片
image = image.resize((new_width, new_height))
# 创立新的画布
canvas = Image.new('RGB', (width, height), (0, 0, 0))
# 核算居中方位
x = (width - new_width) // 2
y = (height - new_height) // 2
# 将缩放后的图片粘贴到画布上
canvas.paste(image, (x, y))
# 保存图片
canvas.save(image_path)
将图片转成视频,并加上背景音乐,解说和字幕
def handle_movie(voice = []):
# 核算一切语音的长度,得出需要视频的长度
duration_clips, text_clips = [], []
for item in voice:
filename = str(item.split('/')[-1])
tmp = filename.split('_')
text_clips.append(tmp[0])
duration_clips.append(float(tmp[-1].replace('.mp3', '')))
duration = sum(duration_clips)
# 背景音乐
bg_music = AudioFileClip("./bgm/1.MP3").set_duration(duration).volumex(0.3)
# 解说 + 字幕
voice_clips, txt_clips = [], []
for idx, item in enumerate(text_clips):
start = sum(duration_clips[:idx])
end = start + duration_clips[idx]
voice_clips.append(
AudioFileClip(voice[idx]).set_start(start).volumex(0.8))
txt_clip = TextClip(text_clips[idx], fontsize=10, color='black', font='兰亭黑-中黑')
txt_clip = txt_clip.set_pos('bottom').set_duration(duration_clips[idx]).crossfadein(1).crossfadeout(1)
txt_clip = txt_clip.set_start(start).set_end(end)
txt_clips.append(txt_clip)
picture_path = './pictures'
# 定义每张图片的编排,并增加淡入淡出作用
images = get_all_files(picture_path)
# 将图片格式化
for image in images:
# 将图片变成 16:9 高度787.5 ,宽度1400
resize_images(image)
image_num = len(images)
image_duration = duration / image_num
image_clips = []
# 镜头焦点作用
def resize_func(t):
return 1 + 0.005 * t
# screensize = (640, 360)
for image_path in get_all_files('./pictures'):
image_clip = ImageClip(image_path).set_duration(image_duration).resize(resize_func).set_position(('center', 'center')).set_fps(25)
image_clip = image_clip.crossfadein(1).crossfadeout(1)
image_clips.append(image_clip)
# 将一切图片编排合并为一个编排
image_clip = concatenate_videoclips(image_clips)
# 将图画、字幕和音频编排合并为一个编排,并增加淡入淡出作用
video_clip = CompositeVideoClip([image_clip] + txt_clips)
audio_clip = CompositeAudioClip([bg_music] + voice_clips)
video_clip = video_clip.set_audio(audio_clip)
video_clip = video_clip.crossfadein(1).crossfadeout(1)
# 导出视频编排
video_clip.write_videofile("video.mp4", fps=24)
遇到的坑
- 背景音乐时长要大于视频时长,否则会报错(能够优化处理,使用
ffmpeg
进行将背景音乐循环) - 设置的时分字体要电脑有的字体,否则或许中文或许无法打印
结语
详细代码已上传github传送门,具体目录结构和代码运行看readm.md
有问题或改善的能够联系 1105504520@qq.com