Python - MoviePy 处理音视频

article/2025/9/19 12:34:41

在这里插入图片描述

文章目录

    • 一、关于 MoviePy
      • 相关教程
      • 安装
      • 工作原理
    • 二、音频
      • 获取音频信息
      • 切割
      • 拼接
      • 音频叠加
      • 音频循环播放
      • 格式转换
      • 视频提取音频
    • 三、视频
      • 获取视频信息
      • 预览视频
      • 视频/Gif 提取图片
      • 图片生成视频 / gif
      • 图片 + 音乐合成视频
      • 视频提取 gif
      • 视频添加文字
      • 视频拼接 concatenate_videoclips
      • 堆叠 clips_array
      • 合成 CompositeVideoClip
      • 设置起始和终止时间 set_start
      • 设置视频的位置 set_pos
      • 音视频合成
      • 设置音频 set_audio
    • 四、其他使用示例
      • 使用MoviePy生成的剪辑基本类型
      • VideoClip
      • ImageSequenceClip
      • 模糊视频中的所有帧


一、关于 MoviePy

  • Github : https://zulko.github.io/moviepy/

相关教程

  • moviepy_guide>
    https://github.com/makelove/moviepy_guide
  • 中文手册
    https://github.com/APhun/moviepy-cn
    https://moviepy-cn.readthedocs.io/zh/latest/
  • ucsheep:MoviePy实战应用 专栏
    https://blog.csdn.net/ucsheep/category_9283153.html
  • play4fun/moviepy_chinese_font
    https://hub.docker.com/r/play4fun/moviepy_chinese_font

教程和文档有很多,但还是喜欢整理成符合我个人阅读习惯的资料,方便后续查阅。

如果你和我阅读、写代码习惯相似,欢迎点赞、继续关注~


安装

pip install moviepy 

工作原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wdF8iDDk-1660361039556)(images/moviepy.jpeg)]


MoviePy 的核心对象是 剪辑

  • 剪辑使用类:AudioClips, VideoClips。基本类:VideoClip。

  • 剪辑可被修改(剪切、降低速度、变暗等)或与其他剪辑混合组成新剪辑。

  • 剪辑可被预览(使用PyGame或IPython Notebook)

  • 剪辑也可生成文件(如MP4文件、GIF文件、MP3文件等)。


二、音频

获取音频信息

你可以使用 AudioFileClip 获得音频对象,读取对象信息,操作此对象。

还可以通过更深的 FFMPEG_AudioReader 类,查看更深的信息。

from moviepy.editor import *mp3_path = '/Users/xx/Music/00.mp3'audio_f = AudioFileClip(mp3_path)
print('filename : ', audio_f.filename) # /Users/xx/Music/00.mp3
print('duration : ', audio_f.duration) # 7.03
print('buffersize : ', audio_f.buffersize) # 200000
print('nchannels : ', audio_f.nchannels) # 2 双声道
print('fps : ', audio_f.fps) # 44100  采样率print('\n------ reader ------')
print('reader : ', audio_f.reader) # <moviepy.audio.io.readers.FFMPEG_AudioReader object at 0x7fddaf6b2210>
print('infos : ', audio_f.reader.infos) #  {'duration': 7.03, 'video_found': False, 'audio_found': True, 'audio_fps': 44100} 
print('buffersize : ', audio_f.reader.buffersize) #  200000
print('nbytes : ', audio_f.reader.nbytes) #  2
print('acodec : ', audio_f.reader.acodec) #  pcm_s16le
print('nframes : ', audio_f.reader.nframes) #  310023

切割

src_path = '/Users/xx/Music/05.mp3'
save_path = '/Users/xx/Music/05_01.mp3'audio_f = AudioFileClip(src_path)
audio_f = audio_f.subclip(0, 6)
audio_f.write_audiofile(save_path) 

拼接

src_path1 = '/Users/xx/Music/05_01.mp3'
src_path2 = '/Users/xx/Music/05_02.mp3'
save_path = '/Users/xx/Music/05_03.mp3'audio_files = [src_path1, src_path2]# audio_clips = [AudioFileClip(src_path1), AudioFileClip(src_path2)]
audio_clips = [AudioFileClip(audio_path) for audio_path in audio_files]audio = concatenate_audioclips(audio_clips)
audio.write_audiofile(save_path)

音频叠加


音频循环播放


格式转换


视频提取音频

from moviepy.editor import VideoFileClipfile_path = '/Users/xx/Music/00.mov'
# file_path = '/Users/xx/Music/01.mp4' 
save_audio_path = '/Users/xx/Music/00.mp3'
save_video_path = '/Users/xx/Music/001.mp4'video_f = VideoFileClip(file_path).subclip(5,12) # 裁剪 5-12s 之间的数据
# video = VideoFileClip(file_path) 获取全部
print('-- video : ', video_f) #  <moviepy.video.io.VideoFileClip.VideoFileClip object at 0x7f9b07f09f90>video_f = video_f.volumex(0.8) # 设置音量为原来的 0.8video_f.audio.write_audiofile(save_audio_path) # 保存音频
video_f.write_videofile(save_video_path) # 保存视频

三、视频


获取视频信息

file_path = '/Users/xx/Music/00.mov'
video_c = VideoFileClip(file_path) print('-- filename : ', video_c.filename) # /Users/xx/Music/00.mov
print('-- duration : ', video_c.duration) # 13.39
print('-- fps : ', video_c.fps) # 59.0
print('-- size : ', video_c.size) # [960, 720]
print('\n---- reader')
print('-- duration : ', video_c.reader.infos) # {'duration': 13.39, 'video_found': True, 'video_size': [960, 720], 'video_fps': 59.0, 'video_nframes': 791, 'video_duration': 13.39, 'video_rotation': 0, 'audio_found': True, 'audio_fps': 44100}
print('-- nframes : ', video_c.reader.nframes) # 791
print('-- depth : ', video_c.reader.depth) # 3
print('-- bufsize : ', video_c.reader.bufsize) # 2073700

预览视频


# video_c.preview() # 预览视频,默认 fps=15
video_c.preview(fps=60) # 
# video_c.preview(fps=15, audio=False) # 不播放音乐
# my_audio_clip.preview(fps=22000) 

视频/Gif 提取图片

file_path = '/Users/xx/Music/00.mov'
# file_path = "/Users/xx/Pictures/beauty/lyf.gif"video_c = VideoFileClip(file_path) video_c.save_frame("frame.png", t=2) # 查看 2s 处的图片, t 默认为0# video_c.show(3) # 显示 3s 处的图片,显示一秒后自动关闭
video_c.show(3, interactive = True) # 需要手动关闭my_clip.preview() # preview with default fps=15
my_clip.preview(fps=25)
my_clip.preview(fps=15, audio=False) # don't generate/play the audio.
my_audio_clip.preview(fps=22000) 

图片生成视频 / gif

import os
from moviepy.editor import *
from moviepy.editor import ImageSequenceClipimgs_dir = '/Users/xx/Pictures/beauty/lyf/01'
video_path = '/Users/xx/Pictures/beauty/lyf.mp4'
video_path2 = '/Users/xx/Pictures/beauty/lyf2.mp4'
gif_path = '/Users/xx/Pictures/beauty/lyf.gif'imgs_name = sorted(os.listdir(imgs_dir))
imgs_path = [os.path.join(imgs_dir , image_name) for image_name in imgs_name] video_c = ImageSequenceClip(imgs_path, fps=2) # 1s 显示2张图# 写入视频
video_c.write_videofile(video_path, codec='libx264')# 写入 gif
video_c.write_gif(gif_path)

图片 + 音乐合成视频

# 添加音乐写入视频
mp3_path = '/Users/xx/Music/00.mp3'
audio_c = AudioFileClip(mp3_path) # audio_c = afx.audio_loop(audio_c, duration=video_c.duration) print(id(video_c))
video_c = video_c.set_audio(audio_c) # 需要重新赋值,因为已经不是一个对象;原对象没有声音
print(id(video_c))
video_c.write_videofile(video_path2, codec='libx264')

视频提取 gif

from moviepy.editor  import *video_path = '/Users/xx/Music/00.mov'
gif_path = '/Users/xx/Music/00.gif'clip=(VideoFileClip(video_path).subclip(0, 5).resize(0.2))
# 使用subclip截取视频片段
# resize缩放为原来的20%# 预览(播放)截取片段
# clip.preview()#转为gif
clip.write_gif(gif_path)

如果报错:clip.preview requires Pygame installed, 安装 Pygame 即可:

pip install pygame

视频添加文字

from moviepy.editor import *video_c = VideoFileClip("001.mp4")# 指定文字大小、颜色和位置
txt_c = TextClip("2020",fontsize=70,color='red')
# 设置水印位置,持续时间
txt_c = txt_c.set_position('center').set_duration(video.duration) # 在视频上覆盖文本
video_c2 = CompositeVideoClip([video_c, txt_c])
# fps:视频文件中每秒的帧数
video_c2.write_videofile("002.mp4",fps=25)

视频拼接 concatenate_videoclips

from moviepy.editor import VideoFileClip, concatenate_videoclips
clip1 = VideoFileClip("myvideo.mp4")
clip2 = VideoFileClip("myvideo2.mp4").subclip(50,60)
clip3 = VideoFileClip("myvideo3.mp4")
final_clip = concatenate_videoclips([clip1,clip2,clip3])
final_clip.write_videofile("my_concatenation.mp4")
  • 如果各剪辑尺寸不同,那么它们将被居中播放,而画面大小足够包含最大的剪辑;
  • 而且你可以选择一种颜色来填充边界部分。
  • 你还有许多其它可选项(详见函数的文档),例如你可以通过transition=my_clip选项来在剪辑之间加一个过场。

堆叠 clips_array

from moviepy.editor import VideoFileClip, clips_array, vfxclip1 = VideoFileClip("myvideo.mp4").margin(10) # add 10px contour
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=480).write_videofile("my_stack.mp4")

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rl2HsVyN-1660361039557)(MoviePy.assets/stacked.jpeg)]


合成 CompositeVideoClip

video = CompositeVideoClip([clip1,clip2,clip3])# 剪辑在更大的合成视频里浮动,需要特意修改最终合成视频的尺寸
# video = CompositeVideoClip([clip1,clip2,clip3], size=(720,460))
  • 当前video播放clip1
  • clip2clip1的上层,而clip3clip1clip2的上层。
  • 举例来说,如果clip2clip3clip1有同样的尺寸,那么只有在顶层的clip3能在视频中可见,除非clip3clip2被遮罩隐藏了一部分。
  • 注意,在默认情况下,合成的视频和第一个剪辑的尺寸相同(因为它通常是一个背景)。

设置起始和终止时间 set_start

clip1 = clip1.set_start(5) # start after 5 seconds# 设置各视频的入场时间
video = CompositeVideoClip([clip1, # starts at t=0clip2.set_start(5), # start at t=5sclip3.set_start(9)]) # start at t=9s

video = CompositeVideoClip([clip1, # starts at t=0clip2.set_start(5).crossfadein(1),clip3.set_start(9).crossfadein(1.5)])

clip2可能先于clip1的结束时间开始,这种情况可以给clip2添加一个1秒钟的淡入效果

video = CompositeVideoClip([clip1, # starts at t=0clip2.set_start(5).crossfadein(1),clip3.set_start(9).crossfadein(1.5)])

设置视频的位置 set_pos

指定了剪辑左上角像素的坐标:

video = CompositeVideoClip([clip1,clip2.set_pos((45,150)),clip3.set_pos((90,100))])

clip2.set_pos((45,150)) # x=45, y=150 , in pixelsclip2.set_pos("center") # automatically centered# clip2 is horizontally centered, and at the top of the picture
clip2.set_pos(("center","top"))# clip2 is vertically centered, at the left of the picture
clip2.set_pos(("left","center"))# clip2 is at 40% of the width, 70% of the height of the screen:
clip2.set_pos((0.4,0.7), relative=True)# clip2's position is horizontally centered, and moving down !
clip2.set_pos(lambda t: ('center', 50+t) )

坐标系 y坐标的0位置在图片的最上方


音视频合成

当你将视频剪辑混合在一起时,MoviePy将会把它们各自的音轨自动合成为最终剪辑的音轨。

如果你想使用许多音频源来自定义音轨,可以使用CompositeAudioClipconcatenate_audioclips来进行混音。

from moviepy.editor import *
# ... make some audio clips aclip1, aclip2, aclip3
concat = concatenate_audioclips([aclip1, aclip2, aclip3])

compo = CompositeAudioClip([aclip1.volumex(1.2),aclip2.set_start(5), # start at t=5saclip3.set_start(9)])

设置音频 set_audio

videoclip2 = videoclip.set_audio(my_audioclip)

四、其他使用示例


使用MoviePy生成的剪辑基本类型

# VIDEO CLIPS
clip = VideoClip(make_frame, duration=4) # for custom animations (see below)
clip = VideoFileClip("my_video_file.mp4") # or .avi, .webm, .gif ...
clip = ImageSequenceClip(['image_file1.jpeg', ...], fps=24)
clip = ImageClip("my_picture.png") # or .jpeg, .tiff, ...
clip = TextClip("Hello !", font="Amiri-Bold", fontsize=70, color="black")
clip = ColorClip(size=(460,380), color=[R,G,B])# AUDIO CLIPS
clip = AudioFileClip("my_audiofile.mp3") # or .ogg, .wav... or a video !
clip = AudioArrayClip(numpy_array, fps=44100) # from a numerical array
clip = AudioClip(make_frame, duration=3) # uses a function make_frame(t)

VideoClip

import gizeh
import moviepy.editor as mpydef make_frame(t):surface = gizeh.Surface(128,128) # width, heightradius = W*(1+ (t*(2-t))**2 )/6 # the radius varies over timecircle = gizeh.circle(radius, xy = (64,64), fill=(1,0,0))circle.draw(surface)return surface.get_npimage() # returns a 8-bit RGB arrayclip = mpy.VideoClip(make_frame, duration=2) # 2 seconds
clip.write_gif("circle.gif",fps=15)

ImageSequenceClip

clip = ImageSequenceClip(images_list, fps=25)

模糊视频中的所有帧

from skimage.filter import gaussian_filter
from moviepy.editor import VideoFileClipdef blur(image):""" Returns a blurred (radius=2 pixels) version of the image """return gaussian_filter(image.astype(float), sigma=2)clip = VideoFileClip("my_video.mp4")
clip_blurred = clip.fl_image( blur )
clip_blurred.write_videofile("blurred_video.mp4")

2022-08-13(六) 伊织


http://chatgpt.dhexx.cn/article/3ADgV3Vr.shtml

相关文章

音视频处理

问题背景&#xff1a;h265格式的视频转码之后ios存在兼容问题 原转码命令&#xff1a; /usr/local/bin/ffmpeg -y -i /data/tmp/1672385812000-tks3wa.mp4 -vf scale720:1281 -r 30 /data/tmp/1672385812000-tks3wa_720.mp4 -hide_banner解决办法&#xff1a; // 原视频格式为…

tune a video:one-shot tuning of image diffusion models for text-to-video generation

【Diffusion Models】新加坡国立大学、腾讯强强联手Tune-A-Video&#xff1a;One-Shot微调图像扩散模型用于文本到图像的生成&#xff01;_哔哩哔哩_bilibili【Diffusion Models】新加坡国立大学、腾讯强强联手Tune-A-Video&#xff1a;One-Shot微调图像扩散模型用于文本到图像…

视频 处理

案例 Fu Xianjun. All Rights Reserved. 一.视频信号 视频信号&#xff08;以下称为视频&#xff09;是非常重要的视频信息来源&#xff0c;它是信息处理过程中经常要处理的一类信号。实际上&#xff0c;视频是由一系列图像构成的。这一系列图像被称为帧&#xff0c;帧是以固定…

用Python剪辑视频?太简单了

人生苦短&#xff0c;快学Python&#xff01; 最近我在网上下载一个视频&#xff0c;结果下载到本地是近百个视频片段&#xff0c;为了方便观看只能将这些片段合并为一个视频整体。 不过我并没有搜到能够处理类似情况的小工具&#xff0c;只是发现剪映等软件可以实现视频合并功…

图片与视频的处理

1.首先需要在mac上安装ffmpeg&#xff08;参考社区的安装教程&#xff09; 需要先安装drew 然后再安装ffmpeg 2.使用dlib工具进行人脸识别&#xff0c;获取特征点&#xff0c;并输出人脸坐标 import cv2 import dlib import numpy as np import matplotlib.pyplot as pltpat…

基本全局阈值处理

基本全局阈值处理 1、全局阈值处理 &#xff08;1&#xff09;计算步骤 通常&#xff0c;在图像处理中首选的方法是使用一种能基于图像数据自动地选择阈值的算法&#xff0c;为了自动选阈值&#xff0c;下列迭代过程采用的就是这样的方法&#xff1a; (1) 针对全局阈值选择初…

基本的全局阈值处理Otsu方法进行最佳全局阈值处理

前言 图像阈值处理在图像分割中处于核心地位&#xff01;本节将重点介绍一些常见的阈值处理方法。 一、基本的全局阈值处理 选取阈值往往是通过直方图来选择的&#xff0c;一方面我们可以人为的设置一个阈值进行一次二值化处理达到全局阈值处理的目的&#xff0c;但这样的阈值…

阈值调整

1.不平衡分类问题的阈值调整 如上图所示&#xff0c;正负例样本不平衡&#xff0c;负样本多&#xff0c;分类器就会更容易把图片分成负样本&#xff0c;因此要设置阈值&#xff0c; 如何选择阈值&#xff1a; 1.ROC曲线上的最优阈值 2.PR曲线上的最优阈值

神经网络阈值是什么意思,神经网络阈值如何确定

BP神经网络中初始权值和阈值的设定 1、首先需要了解BP神经网络是一种多层前馈网络。2、以看一下在matlab中BP神经网络的训练函数&#xff0c;有梯度下降法traingd,弹性梯度下降法trainrp&#xff0c;自适应lr梯度下降法traingda等。 3、在matlab中命令行窗口中定义输入P&…

图像的阈值处理

一般情况下&#xff0c;一张图片分为前景和背景&#xff0c;我们感兴趣的一般的是前景部分&#xff0c;所以我们一般使用阈值将前景和背景分割开来&#xff0c;使我们感兴趣的图像的像素值为1&#xff0c;不感兴趣的我0&#xff0c;有时一张图我们会有几个不同的感兴趣区域&…

神经网络阈值是什么意思,神经网络的权值和阈值

神经网络权值怎么确定&#xff1f; 神经网络的权值是通过对网络的训练得到的。如果使用MATLAB的话不要自己设定&#xff0c;newff之后会自动赋值。也可以手动&#xff1a;{};{}。一般来说输入归一化&#xff0c;那么w和b取0-1的随机数就行。 神经网络的权值确定的目的是为了让…

opencv c++ 二值图像、阈值计算方法、全局阈值、自适应阈值

1、图像定义&#xff1a; 彩色图像 &#xff1a;三通道&#xff0c;像素值一般为0~255&#xff1b; 灰度图像&#xff1a;单通道&#xff0c;像素值一般为0~255&#xff1b; 二值图像&#xff1a;单通道&#xff0c;像素值一般为0&#xff08;黑色&#xff09;、255&#xff08…

图像分割 - 阈值处理 - 全局阈值处理

目录 1. 介绍 2. 代码实现 3. 代码讲解 1. 介绍 当目标和背景像素的灰度分布非常不同的时候&#xff0c;可以对整个图像使用全局阈值 在大多数的应用中&#xff0c;图像之间通常存在足够的变化&#xff0c;全局阈值是一种合适的办法。所以&#xff0c;需要一种对图像做阈值…

硬阈值 软阈值

1 定义 1.1 硬阈值 硬阈值的定义如下&#xff1a; 相当于 1.2 软阈值 软阈值的定义如下&#xff1a; 相当于 1.3 二者对比&#xff08;可视化解释&#xff09; 这是一张很经典地表述软阈值和硬阈值区别的图&#xff0c;其中软阈值是蓝色的线&#xff0c;他没有突变&#xff1…

神经网络阈值是什么意思,神经网络阈值怎么设置

BP神经网络中初始权值和阈值的设定 1、首先需要了解BP神经网络是一种多层前馈网络。2、以看一下在matlab中BP神经网络的训练函数&#xff0c;有梯度下降法traingd,弹性梯度下降法trainrp&#xff0c;自适应lr梯度下降法traingda等。 3、在matlab中命令行窗口中定义输入P&…

图像处理--阈值处理

图像二值化 图像二值化就是将图像上的像素点的灰度值设置为两个值&#xff0c;一般为0&#xff08;表示黑色&#xff09;和255&#xff08;表示白色&#xff09;&#xff0c;可以将整个图像呈现出明显的黑白效果。 最常用的方法就是先将图像灰度处理&#xff0c;然后设定一个阈…

两种划分阈值的方法

风险等级划分的时候可以降低主观性的一些系统方法 方法一&#xff1a;分层聚类法 凝聚层次聚类/分裂层次聚类 重点&#xff1a;确定层次聚类的簇数&#xff0c;画出树状图&#xff0c;基本就能得到你的区间范围&#xff0c;但数据量大的时候还是得再用代码跑 方法二&#xf…

“阀值”与“阈值”的区别

真相请看下图红色框里内容&#xff08;手动微笑&#xff09; 啥&#xff1f;&#xff1f;你跟我说没看懂&#xff0c;好吧&#xff0c;说的再明白点&#xff0c;“阀&#xff08;f&#xff09;值”是一个错误的用词&#xff0c;其正确用法是“阈&#xff08;y&#xff09;值”。…

【p116】

#查询score表中为196004&#xff0c;课程号为1201的学生成绩 #查询student表中姓周的学生情况 #查询数学成绩第2~5名的信息 #查询通信专业最高分的学生的情况 #查询1004课程的最高分,最低分&#xff0c;平均成绩 #查询至少有3名学生选修且以4开头的课程号和平均分数 #将计算机专…

《JDK学习》使用JDK的keytool生成p12证书

由于前段时间在研究itext技术中的签章技术中遇到了数字签名的问题&#xff0c;需要用到p12证书&#xff0c;因此就撰写一篇用我们jdk自带的keytool 工具生成p12证书的方法供各位交流。 keytool 简介 keytool 是java 用于管理密钥和证书的工具. 其功能包括&#xff1a; 创建并管…