moviepy是一个用于视频编辑的Python库,可以处理视频和音频文件。其常见用途:
-
视频剪辑和合并:剪辑/将多个视频文件合并成一个视频。
-
视频转换:将视频转换为不同的格式,比如将MP4文件转换为GIF。
-
文字和图形叠加:提供了添加文字、图形和动画效果到视频中的功能。
-
视频剪裁和调整大小:裁剪视频的特定部分或调整视频的大小。
-
视频特效:提供了一些内置的特效功能,比如模糊、颜色调整等。
-
视频和音频剪辑:提取视频的音频,或者将音频添加到视频中。
官方文档提供了详细的 API 参考和示例: https://zulko.github.io/moviepy/ ↩
𝟶. 安装 moviepy
首先,确保已安装 moviepy:
pip install moviepy
𝟷. 基本语法
-
导入库
from moviepy.editor import *
-
加载视频
video = VideoFileClip("input_video.mp4")
-
视频截取
subclip = video.subclip(10, 20) # 从10秒到20秒
-
改变分辨率
resized = video.resize(height=360) # 按高度调整
-
音量调节
video = video.volumex(0.5) # 音量降为原来的一半
-
视频旋转
rotated_clip = clip.rotate(180) # 视频旋转 180°
-
添加文本
txt_clip = TextClip("Hello World", fontsize=70, color='white') txt_clip = txt_clip.set_position('center').set_duration(10)
-
颜色剪辑
color_clip = ColorClip(size =(460, 380), color =[100, 255, 100])
-
合成视频
final = CompositeVideoClip([video, txt_clip])
-
添加音乐
audio_background = AudioFileClip("audio.mp3") final = final.set_audio(audio_background)
-
导出视频
final.write_videofile("output_video.mp4", fps=24)
𝟸. 高级用法
-
动态图像
image_clip = ImageClip("image.jpg").set_duration(2)
-
图像拼接
clips = [ImageClip(f"image{i}.jpg").set_duration(1) for i in range(1, 5)] video_with_images = concatenate_videoclips(clips)
-
加特效
from moviepy import vfx video_with_effect = video.fx(vfx.fadein, 2).fx(vfx.fadeout, 2)
-
创建 GIF
video.subclip(0, 5).write_gif("output.gif")
𝟹. 常用效果
-
淡入和淡出:
final = final.fx(vfx.fadein, 2).fx(vfx.fadeout, 2)
-
变速:
sped_up = video.fx(vfx.speedx, 2) # 加速2倍
-
镜头剪接:
video = video.fx(vfx.scroll, 50, 0) # 水平滚动
𝟺. 排雷避坑
💥ImageMagick is not installed
OSError: MoviePy Error: creation of None failed because of the following error:
[WinError 2] 系统找不到指定的文件。.
.This error can be due to the fact that ImageMagick is not installed on your computer, or (for Windows users) that you didn’t specify the path to the ImageMagick binary in file conf.py, or that the path you specified is incorrect
原因分析:
在使用 TextClip 前,必须安装独立的 ImageMagick 应用
解决方法:
- 下载并安装 ImageMagick ↩
- 在代码中添加
from moviepy.config import change_settings
change_settings({"IMAGEMAGICK_BINARY": r"C:\Program Files\ImageMagick-7.1.1-Q16\magick.exe"})
Python中的字符串前面加上r表示使用原始字符串,可以防止字符串中的转义字符被处理。
💥无法显示中文
moviepy TextClip无法显示中文:
已将中文字体文件拷贝到代码所在目录font子文件夹中,将TextClip的参数font设置为字体文件名。但是中文字符不显示,英文正常显示,字体没有变为自定义字体。
txt_clip = TextClip(
"title标题",
font='./font/简体.ttf', # font='font/A73.ttf'
)
原因分析:
这是因为字体文件名为中文名导致的,字体文件名称不能用中文, 会报错:
OSError: magick.exe: unable to read font `./font/简体.ttf (invalid stream operation)' @ error/annotate.c/RenderFreetype/1654.
解决办法:
改字体文件名即可。
txt_clip = TextClip(
"title标题",
font='./font/A73.ttf', # font='font/A73.ttf'
)
💥MoviePy couldn’t find the codec
from moviepy.editor import *
video = VideoFileClip("video.mp4")
video.write_videofile("output.avi")
转换格式时报错:
ValueError: MoviePy couldn't find the codec associated with the filename. Provide the 'codec' parameter in write_videofile.
原因分析:
文件扩展名和编码器不匹配,给定的输出文件格式与默认编码器不匹配,不同的格式需要不同的编码器进行处理。若文件扩展名为“.mp4”、“.ogv”、“.webm”,则会自动设置相应编解码器,也可以指定其他编解码器。使用 codec='libx264'
指定 MP4 的编码格式,确保视频能够被广泛支持。
解决方法:
最简单的解决方法是手动指定适当的编码器。例如,使用 libx264 作为 MP4 的编码器,使用 libxvid
作为 AVI 的编码器。
from moviepy.editor import VideoFileClip
video = VideoFileClip("video.mp4")
# 写出 AVI 格式,指定 codec
video.write_videofile("output_video.avi", codec='libxvid')
在使用 moviepy
导出不同输出文件格式时,需要注意每种格式对应的常用编解码器(codec)。以下是一些常见的输出文件格式及其推荐的 codec:
格式 | codec |
---|---|
.mp4 | libx264 (视频编解码器), aac (音频编解码器) |
.avi | libxvid (视频编解码器), mp3 (音频编解码器) |
.mkv | libx264 (视频编解码器), aac 或 mp3 (音频编解码器) |
.wmv | wmv2 或 wmv1 (视频编解码器), wma2 (音频编解码器) |
.mxf | mpeg2video 或 libx264 (根据需求调整),无特定规定的音频编解码器,通常可用 aac 或 pcm_s16le 。 |
.gif | 不需要指定 codec,因为GIF是一种图像格式,相当于直接从帧生成 GIF。 |
.dpg | libx264 是最常用的,有时可用 mpeg1video |
.mtv | mpeg1video (在某些情况下)或 libxvid |
.amv | libxvid (与 AVI 类似,但特定于 AMV 格式) |
.swf | SWF文件通常以 Flash 形式存储,不直接支持通过 moviepy 导出,但可以选择使用 libx264 。 |
每种格式和编解码器都有其特点,确保根据项目需求选择合适的格式及 codec,以保证输出质量和兼容性。
在处理大文件时,参数设置可以显著影响性能,注意设置合适的fps
(帧率,每秒编码的帧数)、codec
(编解码器,可以是ffmpeg支持的任何编解码器)等参数。
𝟻. 使用实例 · 转换
保存格式
write_videofile
方法保存视频write_audiofile
方法保存音频write_gif
方法保存 gif 图像
示例 ➊ :mp4转mp3
—— 【从视频提取音频】
from moviepy.editor import *
video = VideoFileClip("video.mp4")
audio = video.audio
audio.write_audiofile(r"video.mp3")
批量:
批量将MP4文件转换为MP3文件:
# pip install moviepy
from moviepy.editor import *
# 定义输入文件夹和输出文件夹
# input_folder = 'input_folder_path'
# output_folder = 'output_folder_path'
# input_folder = 'D:/Users/11111/Desktop/test'
input_folder = 'D:/test'
output_folder = 'D:/test'
# 循环处理每个MP4文件
for file_name in os.listdir(input_folder):
if file_name.endswith(".mp4"):
video = VideoFileClip(os.path.join(input_folder, file_name))
# 从文件名中获取输出文件名
output_file_name = file_name.replace(".mp4", ".mp3")
# 转换为MP3并保存
video.audio.write_audiofile(os.path.join(output_folder, output_file_name))
video.close()
示例 ➋ :mp4转gif
from moviepy.editor import *
video = VideoFileClip("video.mp4") # 读取mp4
video.write_gif(r"video.gif")
示例 ➌ :常见的 write_videofile 例子
—— 各种视频格式的相互转换
💥MoviePy couldn’t find the codec
# 导出为 MP4
video.write_videofile("output_video.mp4", codec='libx264', audio_codec='aac')
# 导出为 AVI
video.write_videofile("output_video.avi", codec='libxvid', audio_codec='mp3')
# 导出为 MKV
video.write_videofile("output_video.mkv", codec='libx264', audio_codec='aac')
# 导出为 WMV
video.write_videofile("output_video.wmv", codec='wmv2', audio_codec='wma2')
# 导出为 GIF
video.write_gif("output_video.gif")
# 导出为 DPG
video.write_videofile("output_video.dpg", codec='libx264')
# 导出为 AMV
video.write_videofile("output_video.amv", codec='libxvid')
𝟼. 使用实例 · 剪辑
示例 ➍ :文本剪辑
⚠ 在使用 TextClip 前,必须安装独立的 ImageMagick ↩ 应用。
💥ImageMagick is not installed
💥无法显示中文
from moviepy.editor import *
from moviepy.config import change_settings
change_settings({"IMAGEMAGICK_BINARY": r"C:\Program Files\ImageMagick-7.1.1-Q16\magick.exe"})
video = VideoFileClip("video.mp4") # 读取视频文件
video = video.volumex(0.5) # Reduce the audio volume, 音量降为原来的一半
clip = video.subclip(30, 45) # 截取第 30 秒至第 45 秒的部分
print(clip.size) # 获取视频分辨率 (720, 1076)
print(clip.w, clip.h) # 获取视频分辨率 720 1076
# ⚠ 在使用 TextClip 前,必须安装独立的 ImageMagick 应用
# http://www.imagemagick.org/script/download.php#windows
# 创建文本剪辑对象
txt_clip = TextClip(
"title标题",
font='./font/A73.ttf', # 字体, 字体文件名称不能用中文, 会报错:OSError: magick.exe: unable to read font `./font/简体.ttf (invalid stream operation)' @ error/annotate.c/RenderFreetype/1654.
fontsize=48,
color='white', # 颜色
# bg_color='transparent', # 透明背景
bg_color='black', # 黑背景
align='center', # 对齐
# size=(800, 200), # 分辨率, 宽高
size=(clip.w, clip.h // 4), # 高为视频分辨率的四分之一
)
# 创建一个5秒长的文字剪辑,与原视频开始时间对齐
text_clip = txt_clip.set_duration(5)
# 将文字剪辑和视频剪辑合成
clip_result = CompositeVideoClip([clip, text_clip])
# 导出结果视频
clip_result.write_videofile("output_video.mp4") # 保存修改后的视频
from moviepy.editor import *
from moviepy.config import change_settings
change_settings({"IMAGEMAGICK_BINARY": r"C:\Program Files\ImageMagick-7.1.1-Q16\magick.exe"})
video_clip = VideoFileClip("video.mp4").subclip(0, 10)
video_clip = video_clip.set_opacity(0.8)
text = TextClip("dynamic 拼接效果", font='./font/A73.ttf', fontsize=24, color='white', bg_color='black', size=(video_clip.w, 50))
text = text.set_position(('center', 'top')).set_duration(10).set_opacity(0.6)
final_video = CompositeVideoClip([video_clip, text]).set_duration(10)
final_video.write_videofile("combined_video.mp4", fps=24)
示例 ➎ :颜色剪辑
渐变色
from moviepy.editor import *
import numpy as np
def create_gradient(width, height, color1, color2):
"""
创建一个渐变色图像
:param width: 图片宽度
:param height: 图片高度
:param color1: 开始颜色 (R, G, B)
:param color2: 结束颜色 (R, G, B)
:return: 生成的渐变色图像
"""
# 创建一个空的图像
gradient = np.zeros((height, width, 3), dtype=np.uint8)
# 生成渐变
for x in range(width):
weight = x / (width - 1) # 计算渐变权重
gradient[:, x, 0] = int(color1[0] * (1 - weight) + color2[0] * weight) # R
gradient[:, x, 1] = int(color1[1] * (1 - weight) + color2[1] * weight) # G
gradient[:, x, 2] = int(color1[2] * (1 - weight) + color2[2] * weight) # B
return gradient
# 设置参数
width, height = 640, 480
color1 = (255, 0, 0) # 红色
color2 = (0, 0, 255) # 蓝色
# 创建渐变图像
gradient_image = create_gradient(width, height, color1, color2)
# 将 NumPy 数组转换为 ImageClip
gradient_clip = ImageClip(gradient_image).set_duration(5) # 设置时长为5秒
# 导出视频
gradient_clip.write_videofile("gradient_video.mp4", fps=24)
颜色闪烁闪烁
用了 concatenate_videoclips
# 颜色闪烁
# color不能直接用hex code或者color name,而只能用RGB CODE
from moviepy.editor import *
clips = [ColorClip(size=(640, 480), color=(255, 160, 122), duration=0.5),
ColorClip(size=(640, 480), color=(255, 255, 224), duration=0.5),
ColorClip(size=(640, 480), color=(255, 192, 203), duration=0.5)]
flash_clip = concatenate_videoclips(clips)
flash_clip.write_videofile("flashing_colors.mp4", fps=24)
示例 ➏ :遮罩剪辑
mask 掩膜,遮盖,遮罩,蒙版
from moviepy.editor import *
mask_clip = ImageClip("image.jpg", ismask=True, duration=5)
mask_clip.write_videofile("masked_video.mp4", fps=24)
示例 ➐ :视频混剪 - 连接
# 连接:在单个长剪辑中一个接一个地播放它们
from moviepy.editor import *
# from moviepy.editor import VideoFileClip, concatenate_videoclips
clip1 = VideoFileClip("video.mp4") # 12s
clip2 = VideoFileClip("rotated_video.mp4").subclip(5,10) # 5s
clip3 = VideoFileClip("video.mp4") # 12s
final_clip = concatenate_videoclips([clip1,clip2,clip3])
final_clip.write_videofile("concatenation.mp4") # 29s
示例 ➑:视频混剪 - 堆叠
# 堆叠:在单个较大的剪辑中并排放置
from moviepy.editor import *
# from moviepy.editor import VideoFileClip, clips_array, vfx
clip1 = VideoFileClip("video.mp4").margin(10) # add 10px contour
#print(clip1.size) # (340, 260)
clip2 = clip1.fx( vfx.mirror_x)
clip3 = clip1.fx( vfx.mirror_y)
clip4 = clip1.resize(0.60) # downsize 60%
final_clip = clips_array([[clip1, clip2],
[clip3, clip4]])
#final_clip.resize(width=340,height=260).write_videofile("stack.mp4")
final_clip.resize(clip1.size).write_videofile("stack.mp4")
示例 ➒ :视频混剪 - 合成
将多个视频片段与音频结合,创建一个简单的音乐视频效果。
from moviepy.editor import VideoFileClip, concatenate_videoclips, AudioFileClip
# 加载多个视频片段
clips = [
VideoFileClip("clip1.mp4").subclip(0, 5),
VideoFileClip("clip2.mp4").subclip(0, 5),
VideoFileClip("clip3.mp4").subclip(0, 5)
]
# 将视频片段合并成一个
final_clip = concatenate_videoclips(clips)
# 加入音频
audio_clip = AudioFileClip("song.mp3").set_duration(final_clip.duration)
final_video = final_clip.set_audio(audio_clip)
# 导出最终视频
final_video.write_videofile("music_video.mp4", fps=24)
简单的视频剪辑与合成
这个示例将多个视频片段合并成一个,并添加简单的文字。
from moviepy.editor import VideoFileClip, TextClip, CompositeVideoClip
# 加载视频片段
clip1 = VideoFileClip("video1.mp4").subclip(0, 10) # 选择前10秒
clip2 = VideoFileClip("video2.mp4").subclip(0, 10)
# 创建文本片段
txt_clip = TextClip("Hello, this is MoviePy!", fontsize=70, color='white')
txt_clip = txt_clip.set_position('center').set_duration(10)
# 合成视频:将两个视频片段和文本合成在一起
composite_clip = CompositeVideoClip([clip1, clip2.set_position(("right", "bottom")), txt_clip])
# 导出合成视频
composite_clip.write_videofile("composite_video.mp4", fps=24)
示例 ➓ :单帧保存
可以用于截取视频内容做preview封面
from moviepy.editor import *
clip = VideoFileClip("video.mp4")
#clip.show(10.5, interactive = True) #单击框架中的某个位置,它将打印像素的位置和颜色position, color。按esc可退出。
clip.preview(fps=22000) # 单击正在预览的视频剪辑帧中的某个位置,它将打印time, position, color。按esc中止预览。
clip.save_frame("frame.png", t=2) # save t=2s
用 moviepy 来实现帧提取,并通过控制台输入时间来保存指定帧。
from moviepy.editor import VideoFileClip
import imageio
# 加载视频文件
clip = VideoFileClip("video.mp4")
# 播放视频并询问输入时间
clip.preview()
while True:
# 获取用户输入的时间(以秒为单位)
user_input = input("输入时间(秒)以保存帧,或输入 'exit' 退出:")
if user_input.lower() == 'exit':
break
try:
frame_time = float(user_input) # 将输入转为浮点数
if 0 <= frame_time <= clip.duration:
# 提取并保存当前帧
frame = clip.get_frame(frame_time)
imageio.imwrite(f"frame_at_{frame_time:.2f}.png", frame)
print(f"保存帧 at {frame_time:.2f} seconds")
else:
print("时间超出范围,请输入有效的时间。")
except ValueError:
print("请输入有效的数字或 'exit' 退出。")
# 关闭视频
clip.close()
𝟽. 使用实例 · 动画
示例 ⓫ :动态函数
从另一个库生成的帧制作动画
与matplotlib联动
import matplotlib.pyplot as plt
import numpy as np
from moviepy.editor import VideoClip
from moviepy.video.io.bindings import mplfig_to_npimage
x = np.linspace(-2, 2, 200)
duration = 2
fig, ax = plt.subplots()
def make_frame(t):
ax.clear()
ax.plot(x, np.sinc(x**2) + np.sin(x + 2*np.pi/duration * t), lw=3)
ax.set_ylim(-1.5, 2.5)
return mplfig_to_npimage(fig)
animation = VideoClip(make_frame, duration=duration)
# animation.write_gif('matplotlib.gif', fps=20) # 保存为 gif
animation.write_videofile('matplotlib.mp4', fps=20, codec='libx264') # 保存为 mp4 格式
import matplotlib.pyplot as plt
import numpy as np
from moviepy.editor import VideoClip
from moviepy.video.io.bindings import mplfig_to_npimage
# 设置时间范围
duration = 2
fps = 20
# 创建图形和坐标轴
fig, ax = plt.subplots()
ax.set_xlim(0, 128)
ax.set_ylim(0, 128)
ax.set_aspect('equal') # 设置坐标轴比例相等
# 定义半径随时间变化的函数
def make_frame(t):
ax.clear() # 清除先前的图形
radius = (1 + (t / duration) * (2 - (t / duration))) * 128 / 6 # 半径随时间变化
circle = plt.Circle((64, 64), radius, color='red') # 创建红色圆
ax.add_artist(circle) # 添加圆形到坐标轴
ax.set_xlim(0, 128)
ax.set_ylim(0, 128)
ax.set_aspect('equal') # 确保圆形比例正确
return mplfig_to_npimage(fig) # 返回当前帧的图像
# 创建动画
animation = VideoClip(make_frame, duration=duration)
# 保存为 gif 或 mp4 格式
animation.write_gif('matplotlib.gif', fps=fps) # 保存为 GIF
# animation.write_videofile('matplotlib_circle.mp4', fps=fps, codec='libx264') # 保存为 mp4 格式
# plt.close(fig) # 关闭绘图窗口
import numpy as np
import matplotlib.pyplot as plt
from moviepy.editor import *
# 创建3D图像并保存为文件
def create_3d_plot(frame_number):
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# 生成数据
x = np.linspace(-5, 5, 100)
y = np.linspace(-5, 5, 100)
x, y = np.meshgrid(x, y)
z = np.sin(np.sqrt(x ** 2 + y ** 2) + frame_number * 0.2) # 动态变化的Z值
# 绘制表面图
ax.plot_surface(x, y, z, cmap='viridis')
ax.set_title(f'Frame {frame_number}')
# 保存图像
#plt.savefig(f'frame_{frame_number:03d}.png') # 过程图
plt.close()
# 生成多个3D图像帧
for i in range(30): # 生成30帧
create_3d_plot(i)
# 将生成的帧制作成视频
clips = []
for i in range(30):
clip = ImageClip(f'frame_{i:03d}.png').set_duration(0.1) # 每帧持续0.1秒
clips.append(clip)
# 合并所有帧
video = concatenate_videoclips(clips, method='compose')
# video.write_gif('rotating_image.gif', fps=30)
video.write_videofile("3d_plot_video.mp4", fps=30)
示例 ⓬ :旋转的图片
与matplotlib联动
import cv2
# import numpy as np
from moviepy.editor import VideoClip
from moviepy.video.io.bindings import mplfig_to_npimage
import matplotlib.pyplot as plt
# 读取正方形的图片
# 在线图像工具箱 https://phototool.cn/circle/
img = cv2.imread('image2.jpg') # 替换为你的图片路径
h, w = img.shape[:2]
# 增加持续时间以减慢旋转速度
duration = 72 # 原为2,现改为72秒
fps = 20
# 创建图形和坐标轴
fig, ax = plt.subplots()
def make_frame(t):
# angle = t * 360 # 逆时针旋转360度
# angle = t * -360 # 顺时针旋转360度
angle = t * -10 # 减慢旋转速度
# 计算旋转矩阵
center = (w // 2, h // 2)
rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0) # 1.0表示缩放比例
rotated_image = cv2.warpAffine(img, rotation_matrix, (w, h), flags=cv2.INTER_LINEAR) # 使用更高质量的插值方法
ax.clear()
ax.imshow(cv2.cvtColor(rotated_image, cv2.COLOR_BGR2RGB))
# 去除坐标轴和标题
ax.axis('off') # 去除坐标轴
# ax.set_title("") # 不再需要设置标题
return mplfig_to_npimage(fig)
# 创建动画
animation = VideoClip(make_frame, duration=duration)
animation.write_gif('rotating_image.gif', fps=fps)
#plt.close(fig)
示例 ⓭ :动态文字
import numpy as np
from moviepy.editor import *
from moviepy.video.tools.segmenting import findObjects
from moviepy.config import change_settings
change_settings({"IMAGEMAGICK_BINARY": r"C:\Program Files\ImageMagick-7.1.1-Q16\magick.exe"})
# WE CREATE THE TEXT THAT IS GOING TO MOVE, WE CENTER IT.
screensize = (720, 460)
txtClip = TextClip('Cool effect', color='white', font="Amiri-Bold",
kerning=5, fontsize=100)
cvc = CompositeVideoClip([txtClip.set_pos('center')],
size=screensize)
# THE NEXT FOUR FUNCTIONS DEFINE FOUR WAYS OF MOVING THE LETTERS
# helper function
rotMatrix = lambda a: np.array([[np.cos(a), np.sin(a)],
[-np.sin(a), np.cos(a)]])
def vortex(screenpos, i, nletters):
d = lambda t: 1.0 / (0.3 + t ** 8) # damping
a = i * np.pi / nletters # angle of the movement
v = rotMatrix(a).dot([-1, 0])
if i % 2: v[1] = -v[1]
return lambda t: screenpos + 400 * d(t) * rotMatrix(0.5 * d(t) * a).dot(v)
def cascade(screenpos, i, nletters):
v = np.array([0, -1])
d = lambda t: 1 if t < 0 else abs(np.sinc(t) / (1 + t ** 4))
return lambda t: screenpos + v * 400 * d(t - 0.15 * i)
def arrive(screenpos, i, nletters):
v = np.array([-1, 0])
d = lambda t: max(0, 3 - 3 * t)
return lambda t: screenpos - 400 * v * d(t - 0.2 * i)
def vortexout(screenpos, i, nletters):
d = lambda t: max(0, t) # damping
a = i * np.pi / nletters # angle of the movement
v = rotMatrix(a).dot([-1, 0])
if i % 2: v[1] = -v[1]
return lambda t: screenpos + 400 * d(t - 0.1 * i) * rotMatrix(-0.2 * d(t) * a).dot(v)
# WE USE THE PLUGIN findObjects TO LOCATE AND SEPARATE EACH LETTER
letters = findObjects(cvc) # a list of ImageClips
# WE ANIMATE THE LETTERS
def moveLetters(letters, funcpos):
return [letter.set_pos(funcpos(letter.screenpos, i, len(letters)))
for i, letter in enumerate(letters)]
clips = [CompositeVideoClip(moveLetters(letters, funcpos),
size=screensize).subclip(0, 5)
for funcpos in [vortex, cascade, arrive, vortexout]]
# WE CONCATENATE EVERYTHING AND WRITE TO A FILE
final_clip = concatenate_videoclips(clips)
final_clip.write_gif('coolTextEffects.gif', fps=25)
# final_clip.write_videofile('coolTextEffects.avi', fps=25, codec='mpeg4')
创建一个简单的文字动画,文本会在屏幕自上而下移动。
from moviepy.editor import *
from moviepy.config import change_settings
change_settings({"IMAGEMAGICK_BINARY": r"C:\Program Files\ImageMagick-7.1.1-Q16\magick.exe"})
txt_clip = TextClip("Moving Text Animation测试", font='./font/A73.ttf', fontsize=40, color='white') # 文字剪辑
# 设置文字的起始和结束位置
txt_clip = txt_clip.set_position(lambda t: ('center', 100 + 200 * t)).set_duration(2)
background = ColorClip(size=(640, 480), color=(0, 0, 0), duration=2) # 黑色背景
final_clip = CompositeVideoClip([background, txt_clip]) # 合成视频
final_clip.write_gif('moving_text.gif', fps=24)
#final_clip.write_videofile("moving_text.mp4", fps=24) # 导出视频
示例 ⓮ :带音频的动态文本
此示例包含动态文本和背景音乐。
from moviepy.editor import *
from moviepy.config import change_settings
change_settings({"IMAGEMAGICK_BINARY": r"C:\Program Files\ImageMagick-7.1.1-Q16\magick.exe"})
# 创建背景和文本
background = ColorClip(size=(640, 480), color=(0, 0, 0), duration=2)
txt_clip = TextClip("Enjoy the music!聆", font='./font/A73.ttf', fontsize=40, color='white').set_duration(2)
# 文本动态变化
txt_clip = txt_clip.set_position(lambda t: ('center', 100 + 200 * t)).set_duration(2)
audio_clip = AudioFileClip("background_music.mp3").set_duration(2) # 背景音乐
final_clip = CompositeVideoClip([background, txt_clip]) # 合成视频
final_clip = final_clip.set_audio(audio_clip)
final_clip.write_videofile("music_video.mp4", fps=24) # 导出视频
示例 ⓯ :使用参数化运动效果创建动画
使用参数化运动,提高动画的复杂性和可定制性。
小球的圆周运动
import numpy as np
from moviepy.editor import *
# 视频参数
width, height = 640, 480
duration = 5 # 视频持续时间(秒)
fps = 30 # 帧率
radius = 100 # 圆的半径
ball_radius = 10 # 小球的半径
# 创建一个背景图像
#bg_color = (255, 255, 255) # 背景色:白色
bg_color = (0, 0, 0)
background = ColorClip(size=(width, height), color=bg_color, duration=duration)
# 创建一个小球的运动函数
def make_frame(t):
# 计算小球的圆周运动位置
angle = 2 * np.pi * (t / duration) # 当前角度
x = width / 2 + radius * np.cos(angle) # 计算 x 坐标
y = height / 2 + radius * np.sin(angle) # 计算 y 坐标
# 创建一个透明的帧数组
#frame = np.ones((height, width, 3), dtype=np.uint8) * 255 # 白色背景
frame = np.ones((height, width, 3), dtype=np.uint8) * [17, 209, 124] # 使用背景色 #11d17c
# 画小球
y_min, y_max = int(y - ball_radius), int(y + ball_radius)
x_min, x_max = int(x - ball_radius), int(x + ball_radius)
# 使用数组操作填充小球区域
for i in range(max(0, y_min), min(height, y_max)):
for j in range(max(0, x_min), min(width, x_max)):
if np.sqrt((j - x) ** 2 + (i - y) ** 2) <= ball_radius:
frame[i, j] = [255, 0, 0] # 红色小球
return frame
# 生成视频片段
motion_ball_clip = VideoClip(make_frame, duration=duration)
# 合并背景和小球动画
final_clip = CompositeVideoClip([background, motion_ball_clip])
# 输出视频文件
final_clip.write_gif('circle_motion_ball.gif', fps=fps)
final_clip.write_videofile("circle_motion_ball.mp4", fps=fps)
𝟾. 使用实例 · 特效
示例 ⓰ :淡入淡出
from moviepy.editor import *
clip1 = VideoFileClip("video.mp4") # 12s
clip2 = VideoFileClip("rotated_video.mp4").subclip(5,10) # 5s
clip3 = VideoFileClip("video.mp4") # 12s
final_clip = CompositeVideoClip([clip1, # starts at t=0
clip2.set_start(5).crossfadein(1),
clip3.set_start(9).crossfadein(1.5)])
final_clip.write_videofile("composition.mp4")
合成多个视频片段,并在它们之间添加转场效果。
from moviepy.editor import *
# 加载多个视频片段
clip1 = VideoFileClip("video.mp4").subclip(0, 5)
clip2 = VideoFileClip("video.mp4").subclip(2, 5)
# 创建转场效果
fade_out = clip1.fx(vfx.fadeout, 1) # clip1 结尾渐出
fade_in = clip2.fx(vfx.fadein, 1) # clip2 开头渐入
final_clip = concatenate_videoclips([fade_out, fade_in])
final_clip.write_videofile("transitions_video.mp4", fps=24)
示例 ⓱ :高斯模糊
—— 模糊视频的所有帧
from skimage.filters import gaussian
from moviepy.editor import VideoFileClip
def blur(image):
""" Returns a blurred (radius=2 pixels) version of the image """
return gaussian(image.astype(float), sigma=2)
clip = VideoFileClip("video.mp4")
clip_blurred = clip.fl_image( blur )
clip_blurred.write_videofile("blurred_video.mp4")
示例 ⓲ :图像多重曝光效果
合成多张图片形成多重曝光效果:
from moviepy.editor import *
# 加载两个图像
image3 = ImageClip("image3.jpg").set_duration(5).resize(height=480)
image4 = ImageClip("image4.jpg").set_duration(5).resize(height=480)
# 调整透明度
image3 = image3.set_opacity(0.6)
image4 = image4.set_opacity(0.4)
# 合成图像
final_clip = CompositeVideoClip([image3, image4])
final_clip.write_gif('double_exposure.gif', fps=24)
final_clip.write_videofile("double_exposure.mp4", fps=24)
示例 ⓳ :图像剪切和拼接效果
创建图像拼接效果,以产生动态的拼图效果:
from moviepy.editor import *
# 加载图像并制作为视频片段
image1 = ImageClip("image1.jpg").set_duration(2).resize((240, 240))
image2 = ImageClip("image2.jpg").set_duration(2).resize((240, 240))
image3 = ImageClip("image3.jpg").set_duration(2).resize((240, 240))
image4 = ImageClip("image4.jpg").set_duration(2).resize((240, 240))
final_clip = concatenate_videoclips([image1, image2, image3, image4]) # 合并
final_clip.write_videofile("image_puzzle.mp4", fps=24) # 导出
示例 ⓴:动态二维码生成和合成
实时生成二维码并添加到视频中(需要安装 qrcode
库):
pip install qrcode
import qrcode
# from PIL import Image
from moviepy.editor import *
# 生成二维码
def generate_qr_code(data):
qr = qrcode.QRCode(version=1, box_size=1, border=1)
qr.add_data(data)
qr.make(fit=True)
img = qr.make_image(fill='black', back_color='white').convert("RGB") # 转换为 RGB 格式
# QR 代码是以单通道图像的形式生成的,而 MoviePy 来处理图像时期望的是 RGB 格式的图像
img.save("qrcode.png")
# 创建二维码
generate_qr_code("https://zulko.github.io/moviepy")
# 加载视频片段
clip = VideoFileClip("video.mp4").subclip(0, 5)
# 加载二维码
qr_code = ImageClip("qrcode.png").set_duration(5).set_position(("right", "bottom"))
# 创建合成视频
final_clip = CompositeVideoClip([clip, qr_code])
final_clip.write_gif('video_with_qr.gif', fps=24)
#final_clip.write_videofile("video_with_qr.mp4")