代码
from moviepy.editor import *
import os
import math
import numpy as np
from enum import Enum
from PIL import Image, ImageDraw, ImageFont, ImageColor
class BackgroundGradient(Enum):
skyline = ['#1488CC', '#2B32B2']
cool_brown = ['#603813', '#b29f94']
rose_water = ['#E55D87', '#5FC3E4']
crystal_clear = ['#159957', '#155799']
midnight_city = ['#232526', '#414345']
deep_space = ['#000000', '#434343']
joint = None
def _display_gradient_bg(base_img: Image, bg_gradient: BackgroundGradient, type=0):
img_w, img_h = base_img.size
draw = ImageDraw.Draw(base_img)
start_color, end_color = bg_gradient.value
if '#' in start_color:
start_color = ImageColor.getrgb(start_color)
if '#' in end_color:
end_color = ImageColor.getrgb(end_color)
len = None
if type == 0: # 水平方向渐变,渐变步长
len = img_w
elif type == 1: # v
len = img_h
# 水平方向渐变,渐变步长
step_r = (end_color[0] - start_color[0]) / len
step_g = (end_color[1] - start_color[1]) / len
step_b = (end_color[2] - start_color[2]) / len
for i in range(0, len):
bg_r = round(start_color[0] + step_r * i)
bg_g = round(start_color[1] + step_g * i)
bg_b = round(start_color[2] + step_b * i)
if type == 0:
draw.line([(i, 0), (i, img_h)], fill=(bg_r, bg_g, bg_b))
elif type == 1:
draw.line([(0, i), (img_w, i)], fill=(bg_r, bg_g, bg_b))
start_color = ImageColor.getrgb(BackgroundGradient.rose_water.value[1])
shape_color_1 = (start_color[0], start_color[1], start_color[2], 20)
fnt = ImageFont.truetype("/Users/admin/PycharmProjects/video_process/videos/ttf/明兰.ttf", 50)
draw.multiline_text((int(img_w * 0.05), int(img_h * 0.05)), "三角 ▶", font=fnt, fill=shape_color_1)
def draw_one_circle(the_draw: ImageDraw, bounding_circle, shape_color, width):
the_draw.ellipse(bounding_circle, outline=shape_color, width=width)
def draw_one_arc(the_draw: ImageDraw, xy, start, end, fill, width):
the_draw.arc(xy, start, end, fill, width)
def draw_one_regular_pro(the_draw: ImageDraw, bounding_circle, n_sides, rotation=0, fill=None, outline=None, width=1):
the_draw.regular_polygon(bounding_circle, n_sides, rotation=rotation, fill=fill, outline=outline, width=width)
def draw_one_line(the_draw: ImageDraw, xy, fill=None, width=1, joint=None):
the_draw.line(xy, fill=fill, width=width, joint=joint)
def _add_rotate(base_img: Image, t, duration):
img_w, img_h = base_img.size
draw = ImageDraw.Draw(base_img)
min_w_h = min(img_w, img_h)
radis = int(min_w_h * 0.3)
center = (img_w // 2, img_h // 2)
bounding_circle = (center, radis)
start_color = ImageColor.getrgb(BackgroundGradient.rose_water.value[0])
shape_color_1 = (start_color[0], start_color[1], start_color[2], 120)
start_color = ImageColor.getrgb(BackgroundGradient.cool_brown.value[0])
fill = (start_color[0], start_color[1], start_color[2], 120)
end_arge = 120
rotation = int(end_arge / duration * t) if t < duration else end_arge
draw_one_regular_pro(draw, bounding_circle, n_sides=3, rotation=rotation, fill=fill, outline=shape_color_1, width=5)
def _add_regular_polygon(base_img: Image, t, duration):
img_w, img_h = base_img.size
draw = ImageDraw.Draw(base_img)
min_w_h = min(img_w, img_h)
radis = int(min_w_h * 0.3)
center = (img_w // 2, img_h // 2)
bounding_circle = (center, radis)
start_color = ImageColor.getrgb(BackgroundGradient.rose_water.value[0])
shape_color_1 = (start_color[0], start_color[1], start_color[2], 120)
start_color = ImageColor.getrgb(BackgroundGradient.cool_brown.value[0])
cur = int(120 / duration * t)
fill = (start_color[0], start_color[1], start_color[2], cur)
draw_one_regular_pro(draw, bounding_circle, n_sides=3, rotation=0, fill=fill, outline=shape_color_1, width=5)
def _add_line(base_img: Image, t, duration):
img_w, img_h = base_img.size
draw = ImageDraw.Draw(base_img)
center = (img_w // 2, img_h // 2)
start_color = ImageColor.getrgb(BackgroundGradient.rose_water.value[0])
shape_color_1 = (start_color[0], start_color[1], start_color[2], 120)
min_w_h = min(img_w, img_h)
radis = int(min_w_h * 0.3)
theta = 30 * math.pi / 180
sin_theta = math.sin(theta)
cos_theta = math.cos(theta)
point_1 = (center[0], center[1] - radis)
point_2 = (center[0] - int(cos_theta * radis), center[1] + int(sin_theta * radis))
point_3 = (center[0] + int(cos_theta * radis), center[1] + int(sin_theta * radis))
w = point_1[0] - point_2[0]
h = - (point_1[1] - point_2[1])
tan_theta = math.tan(60 * math.pi / 180)
dw = (w / duration)
cur_dw = int(dw * t)
cur_w = point_1[0] - cur_dw
dh = int(cur_dw * tan_theta)
cur_h = point_1[1] + dh
draw_one_line(draw, [point_1, (cur_w, cur_h)], shape_color_1, 5, joint)
draw_one_line(draw, [point_3, (point_3[0] - cur_dw, point_3[1] - dh)], shape_color_1, 5, joint)
w = point_3[0] - point_2[0]
dw = w / duration
cur_dw = dw * t
cur_w = point_2[0] + int(cur_dw)
draw_one_line(draw, [point_2, (cur_w, point_3[1])], shape_color_1, 5, joint)
def _add_circle2(base_img: Image, t, duration):
img_w, img_h = base_img.size
draw = ImageDraw.Draw(base_img)
dt = 20 / duration
cur = int(dt * t)
start_color = ImageColor.getrgb(BackgroundGradient.rose_water.value[1])
shape_color_1 = (start_color[0], start_color[1], start_color[2], cur)
min_w_h = min(img_w, img_h)
first = int(min_w_h * 0.1)
offset = 100
first = int(1.5 * first)
center_three = (0 + offset + first, img_h - offset - first)
coords_three = [(center_three[0] - first, center_three[1] - first),
(center_three[0] + first, center_three[1] + first)]
draw_one_circle(draw, coords_three, shape_color_1, 5)
def _add_circle(base_img: Image, t, duration):
img_w, img_h = base_img.size
draw = ImageDraw.Draw(base_img)
dt = 20 / duration
cur = int(dt * t)
start_color = ImageColor.getrgb(BackgroundGradient.rose_water.value[0])
shape_color_1 = (start_color[0], start_color[1], start_color[2], cur)
min_w_h = min(img_w, img_h)
first = int(min_w_h * 0.1)
offset = 40
center_first = (0 + offset + first, img_h - offset - first)
coords_first = [(center_first[0] - first, center_first[1] - first),
(center_first[0] + first, center_first[1] + first)]
draw_one_circle(draw, coords_first, shape_color_1, 5)
def _add_upper(base_img: Image, t):
img_w, img_h = base_img.size
draw = ImageDraw.Draw(base_img)
dt = 20 / 0.5
cur = int(dt * t)
start_color = ImageColor.getrgb(BackgroundGradient.skyline.value[0])
shape_color_1 = (start_color[0], start_color[1], start_color[2], cur)
min_w_h = min(img_w, img_h)
center_second = (img_w, 0)
radius_second = int(min_w_h * 0.3)
coords_second = [(center_second[0] - radius_second, center_second[1] - radius_second),
(center_second[0] + radius_second, center_second[1] + radius_second)]
draw_one_arc(draw, coords_second, 90, 180, shape_color_1, 5)
def _add_cover(base_img: Image):
img_w, img_h = base_img.size
draw = ImageDraw.Draw(base_img)
shape_color_1 = (255, 255, 255, 120)
shape_color_2 = (255, 255, 255, 60)
shape_color_3 = (255, 255, 255, 40)
min_w_h = min(img_w, img_h)
first = int(min_w_h * 0.05)
offset = 30
center_first = (0 + offset + first, img_h - offset - first)
coords_first = [(center_first[0] - first, center_first[1] - first),
(center_first[0] + first, center_first[1] + first)]
center_second = (img_w, 0)
radius_second = int(min_w_h * 0.3)
coords_second = [(center_second[0] - radius_second, center_second[1] - radius_second),
(center_second[0] + radius_second, center_second[1] + radius_second)]
offset = 50
first = int(1.5 * first)
center_three = (0 + offset + first, img_h - offset - first)
coords_three = [(center_three[0] - first, center_three[1] - first),
(center_three[0] + first, center_three[1] + first)]
draw_one_circle(draw, coords_first, shape_color_2, 3)
draw_one_arc(draw, coords_second, 90, 180, shape_color_3, 5)
draw_one_circle(draw, coords_three, shape_color_1, 4)
radis = int(min_w_h * 0.3)
center = (img_w // 2, img_h // 2)
bounding_circle = (center, radis)
draw_one_regular_pro(draw, bounding_circle, n_sides=3, rotation=0, fill=shape_color_3, outline=None, width=5)
theta = 30 * math.pi / 180
sin_theta = math.sin(theta)
cos_theta = math.cos(theta)
point_1 = (center[0], center[1] - radis)
point_2 = (center[0] - int(cos_theta * radis), center[1] + int(sin_theta * radis))
point_3 = (center[0] + int(cos_theta * radis), center[1] + int(sin_theta * radis))
draw_one_line(draw, [point_1, point_2, point_3, point_1], shape_color_2, 5, "curve")
all_duration = 6.0
class My_Basic():
def __init__(self):
gb_w = 1080
gb_h = 1440
img_bg = Image.new("RGBA", (gb_w, gb_h))
_display_gradient_bg(img_bg, BackgroundGradient.deep_space, type=1)
self.img_bg = img_bg
def get_frame(self, img=None):
if img is not None:
temp = Image.alpha_composite(self.img_bg, img).convert("RGB")
return np.array(temp)
temp = self.img_bg.convert("RGB")
return np.array(temp)
def copy_bg(self):
return self.img_bg.copy()
def update(self, img):
self.img_bg = Image.alpha_composite(self.img_bg, img)
my_basic = My_Basic()
def make_frame(t):
if t == 0:
return my_basic.get_frame()
if t <= 0.5:
img_copy = my_basic.copy_bg()
_add_upper(img_copy, t)
my_basic.update(img_copy)
return my_basic.get_frame()
if t <= 1:
img_copy = my_basic.copy_bg()
_add_circle(img_copy, t - 0.5, 0.5)
my_basic.update(img_copy)
return my_basic.get_frame()
if t <= 1.5:
img_copy = my_basic.copy_bg()
_add_circle2(img_copy, t - 1.0, 1.0)
my_basic.update(img_copy)
return my_basic.get_frame()
if t <= 2.5:
img_copy = my_basic.copy_bg()
_add_line(img_copy, t - 1.5, 1)
return my_basic.get_frame(img_copy)
if t <= 3.5:
img_copy = my_basic.copy_bg()
_add_regular_polygon(img_copy, t - 2.5, 1)
return my_basic.get_frame(img_copy)
if t <= all_duration:
img_copy = my_basic.copy_bg()
_add_rotate(img_copy, t - 3.5, 1)
return my_basic.get_frame(img_copy)
return my_basic.get_frame()
vc = VideoClip(make_frame=make_frame, duration=all_duration)
source = '/Users/admin/刘德华-忘情水.mp3'
audio = AudioFileClip(source)
audio = audio.subclip(8 - vc.duration, 8)
audio =audio.fx(afx.audio_fadeout, 0.4)
vc = vc.set_audio(audio)
res_file = "{}.mp4".format(os.path.basename(__file__))
vc.write_videofile(res_file, audio_codec="aac", codec="libx264", threads=1, fps=30, verbose=False,
logger=None)
结果
movie.py