音视频剪辑库moviepy及其应用

news2024/11/15 6:48:27

思维导图

moviepy是一个用于视频编辑的Python库,可以处理视频和音频文件。其常见用途:

  1. 视频剪辑和合并:剪辑/将多个视频文件合并成一个视频。

  2. 视频转换:将视频转换为不同的格式,比如将MP4文件转换为GIF。

  3. 文字和图形叠加:提供了添加文字、图形和动画效果到视频中的功能。

  4. 视频剪裁和调整大小:裁剪视频的特定部分或调整视频的大小。

  5. 视频特效:提供了一些内置的特效功能,比如模糊、颜色调整等。

  6. 视频和音频剪辑:提取视频的音频,或者将音频添加到视频中。

官方文档提供了详细的 API 参考和示例: https://zulko.github.io/moviepy/ ↩


𝟶. 安装 moviepy

首先,确保已安装 moviepy:

pip install moviepy

𝟷. 基本语法

  1. 导入库

    from moviepy.editor import *
    
  2. 加载视频

    video = VideoFileClip("input_video.mp4")
    
  3. 视频截取

    subclip = video.subclip(10, 20)  # 从10秒到20秒
    
  4. 改变分辨率

    resized = video.resize(height=360)  # 按高度调整
    
  5. 音量调节

    video = video.volumex(0.5)  # 音量降为原来的一半
    
  6. 视频旋转

    rotated_clip = clip.rotate(180) # 视频旋转 180°
    
  7. 添加文本

    txt_clip = TextClip("Hello World", fontsize=70, color='white')
    txt_clip = txt_clip.set_position('center').set_duration(10)
    
  8. 颜色剪辑

    color_clip = ColorClip(size =(460, 380), color =[100, 255, 100])
    
  9. 合成视频

    final = CompositeVideoClip([video, txt_clip])
    
  10. 添加音乐

    audio_background = AudioFileClip("audio.mp3")
    final = final.set_audio(audio_background)
    
  11. 导出视频

    final.write_videofile("output_video.mp4", fps=24)
    

𝟸. 高级用法

  1. 动态图像

    image_clip = ImageClip("image.jpg").set_duration(2)
    
  2. 图像拼接

    clips = [ImageClip(f"image{i}.jpg").set_duration(1) for i in range(1, 5)]
    video_with_images = concatenate_videoclips(clips)
    
  3. 加特效

    from moviepy import vfx
    video_with_effect = video.fx(vfx.fadein, 2).fx(vfx.fadeout, 2)
    
  4. 创建 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 应用

解决方法:

  1. 下载并安装 ImageMagick ↩
  2. 在代码中添加
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
.mp4libx264 (视频编解码器), aac (音频编解码器)
.avilibxvid (视频编解码器), mp3 (音频编解码器)
.mkvlibx264 (视频编解码器), aacmp3 (音频编解码器)
.wmvwmv2wmv1 (视频编解码器), wma2 (音频编解码器)
.mxfmpeg2videolibx264(根据需求调整),无特定规定的音频编解码器,通常可用 aacpcm_s16le
.gif不需要指定 codec,因为GIF是一种图像格式,相当于直接从帧生成 GIF。
.dpglibx264 是最常用的,有时可用 mpeg1video
.mtvmpeg1video(在某些情况下)或 libxvid
.amvlibxvid(与 AVI 类似,但特定于 AMV 格式)
.swfSWF文件通常以 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")

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1990409.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

arcgis pro批量修改多个矢量的属性

在arcgis pro中&#xff0c;我想批量修改多个矢量的属性值。 比如&#xff1a; 我有两个要素&#xff1a;2021年县级和2022年县级&#xff0c;它们都有“区划码”、“曾用名”、“备注信息”这两个属性。 现在我想使用arcgis pro的脚本功能&#xff0c;使得2021年县级和2022年县…

凯特与戴安娜两位王妃:风采各异 凯特王妃虽未及婆婆影响力但效仿很有成效

最显而易见的也是必须了解的前提:戴安娜王妃是现任凯特王妃已故的婆婆 不过她们是没有见过面的婆媳,戴安娜王妃去世的那年,凯特才15岁!从阶级来看,当时的课题家族应该没有机会见到戴安娜。 凯特还没有像戴安娜一样对世界产生那么多的影响力 在英国王室的璀璨星空中,凯…

AI人工智能为企业带来的优势及应用例子

自2022年知名大型语言模型及其他 AI 产品面世至今&#xff0c;无论商界、政府以至社会各界都逐渐关注人工智能的发展&#xff0c;并纷纷引入 AI 技术&#xff0c;全球正式踏入人工智能的新纪元。根据 Statista 一份有关全球人工智能软件的数据研究&#xff0c;至2025年预测各国…

uni-app中如何使用日期选择器

uni-app中如何使用日期选择器&#xff0c;分别实现日&#xff0c;月&#xff0c;年 日 <picker mode"date" fields"day">是日的内容</picker> 月 <picker mode"date" fields"month">日期选择器</picker> 年…

Java设计模式(桥接模式)

定义 将抽象部分与它的实现部分解耦&#xff0c;使得两者都能够独立变化。 角色 抽象类&#xff08;Abstraction&#xff09;&#xff1a;定义抽象类&#xff0c;并包含一个对实现化对象的引用。 扩充抽象类&#xff08;RefinedAbstraction&#xff09;&#xff1a;是抽象化角…

软件测试工作流程(三)

软件测试的基本流程 测试需求分析阶段 阅读需求&#xff0c;理解需求&#xff0c;主要就是对业务的学习&#xff0c;分析需求点。参与需求评审会议 – 需求规格说明书测试计划阶段 编写测试计划&#xff0c;参考软件需求规格说明书&#xff0c;项目总体计划&#xff0c;内容包括…

OpenNebula-6.9.80中文详细部署安装

目录 OpenNebula介绍 主要特点 应用场景 一. 虚拟机准备 二. 下载安装 1. 导入yum源 2. 数据库配置 3. 安装包 4. 设置配置 数据存放位置 端口介绍 命令介绍 OpenNebula介绍 OpenNebula 是一个开源的云计算平台&#xff0c;主要用于创建和管理虚拟化环境。它被设…

LVS-NAT

概述 LVS&#xff08;Linux Virtual Server&#xff09;是一种常见的负载均衡技术。LVS允许客户端的请求通过负载均衡器&#xff08;Director Server&#xff09;转发到后端多台服务器&#xff08;Real Servers&#xff09;。在NAT模式下&#xff0c;负载均衡器会修改请求报文的…

Sqlilabs靶场报错注入:less1~6

报错注入&#xff1a; less-1&#xff1a;报错后的GET单引号字注入 首先做SQL注入&#xff0c;需要知道注入参数是什么&#xff0c;不是所有的参数都是id&#xff0c;也能是file等等。判断注入点&#xff0c;注入点很重要&#xff0c;如果找不到注入的地方&#xff0c;测试什么…

如何避免项目发布后用户从浏览器WebPack中看到源码

打包前在config->index.js中设置productionSourceMap为false productionSourceMap: false,

【Hive】学习笔记

Hive学习笔记 【一】Hive入门【1】什么是Hive【2】Hive的优缺点&#xff08;1&#xff09;优点&#xff08;2&#xff09;缺点 【3】Hive架构原理&#xff08;1&#xff09;用户接口&#xff1a;Client&#xff08;2&#xff09;元数据&#xff1a;Metastore&#xff08;3&…

Augmentation for small object detection

Abstract 我们对MS COCO数据集上的当前最先进模型Mask-RCNN进行了分析。我们发现小物体的ground-truth与预测的锚框之间的重叠远远低于预期的IoU阈值。我们推测这是由两个因素造成的&#xff1a;&#xff08;1&#xff09;只有少数图像包含小物体&#xff0c;&#xff08;2&am…

英特尔18A制程技术分析解读

#### 引言 尽管第二季度净亏损16亿美元以及大规模裁员计划引发了一些担忧&#xff0c;英特尔还是在8月6日宣布了其下一代18A制程技术取得重大里程碑的消息&#xff0c;并计划在2025年开始生产。 #### 技术进展 - **里程碑**&#xff1a;英特尔表示&#xff0c;这一里程碑是在…

IoTDB组件AI Node发布9个月,如何使用你了解了吗?

数据 x AI &#xff0c;第一批用户已认可&#xff01; 在工业智能化转型中&#xff0c;时序数据库与 AI 技术的结合对故障和异常预测场景的准确性和效率至关重要&#xff0c;逐渐成为行业前沿关注热点。在此方面&#xff0c;IoTDB 已迈出支持 AI 深度分析的重要一步&#xff0c…

240806-在Linux/RHEL开机中自动启动bash脚本

A. 常规方法 要在Red Hat Enterprise Linux (RHEL) 中设置开机启动的bash脚本&#xff0c;可以使用以下方法之一&#xff1a; 方法1&#xff1a;使用/etc/rc.d/rc.local 打开/etc/rc.d/rc.local文件&#xff1a; sudo vi /etc/rc.d/rc.local在文件末尾添加你想要执行的bash脚…

Plus机型成为历史?iPhone 17系列带来全新阵容

苹果公司一直以来都是科技创新的领航者&#xff0c;每一次新品发布都会引发全球消费者的热烈关注。据最新消息&#xff0c;苹果计划于2024年秋季推出全新的iPhone 17系列&#xff0c;这一代iPhone将以其独特的设计、卓越的性能和创新的功能再次刷新人们对智能手机的认知。 一、…

【算法设计题】基于front、rear和count的循环队列初始化、入队和出队操作,第6题(C/C++)

目录 第3题 基于front、rear和count的循环队列初始化、入队和出队操作 得分点&#xff08;必背&#xff09; 题解&#xff1a;基于front、rear和count的循环队列初始化、入队和出队操作 数据结构定义 代码解答 详细解释 1. 循环队列初始化 2. 循环队列入队 3. 循环队列…

分库分表的使用场景和中间件

文章目录 一、为什么要分库分表&#xff1f;分库分表的使用场景&#xff1f;二、分库分表常用中间件1、Cobar2、TDDL3、Atlas4、Sharding-jdbc5、Mycat6、总结 一、为什么要分库分表&#xff1f;分库分表的使用场景&#xff1f; 场景1&#xff1a;注册用户就 20 万&#xff0c…

1.4 C 程序的编译过程与 CLion 调试技巧

目录 1 程序的编译过程 1.1 编写源代码 1.2 预处理&#xff08;Preprocessing&#xff09; 1.3 编译&#xff08;Compilation&#xff09; 1.4 汇编&#xff08;Assembly&#xff09; 1.5 链接&#xff08;Linking&#xff09; 1.6 执行 2 编译过程的输入输出文件概览 …

7-1 深度学习硬件:CPU和GPU

L 3 L3 L3、 L 2 L2 L2、 L 1 L1 L1为cache&#xff0c;数据只有进入寄存器的时候&#xff0c;才能开始运算。 &#xff08;此图错误&#xff0c;一个矩阵应该是按行存储的&#xff01;&#xff09; GPU的核要远远多于CPU&#xff0c;从而TFLOPS&#xff0c;GPU每秒能做的…