为了帮助剪辑小姐姐少熬夜,我用 Python 硬肝了一次短视频音频创作

Irene181
• 阅读 1919

本文转载自公众号【AirPython】,详情可以点击上方卡片,关注该公众号,获取更多好文推荐。

为了帮助剪辑小姐姐少熬夜,我用 Python 硬肝了一次短视频音频创作

1. 前言

最近一个小姐姐在后台给我留言,说自己的工作是短视频剪辑,经常需要熬夜剪片子,其中,音频处理费时费力,问我能不能利用自动化减轻她的工作

前面很多文章都使用了一款非常强大的依赖库,即:moviepy,它能非常快捷地完成视频剪辑

装逼篇 | 抖音超火的九宫格视频是如何生成的,Python 告诉你答案

短视频篇 | Python 带你进行短视频二次创作

视频剪辑什么鬼?Python 带你高效创作短视频

10万+的短视频被批量生产了,Python表示不服

本篇文章推荐另外一个超级强大的音频处理库:pydub

2. 介绍

pydub 是一款简单、方便且强大的 Python 音频处理库

项目地址:

https://github.com/jiaaro/pydub

日常音频剪辑处理工具,都可以使用它来完成,比如:提取音频、音频切断、音效处理、响度控制、声道配置、音频合成等

首先,安装依赖包

# 安装依赖  
pip3 install pydub

3. 常见操作

接下来,我们来聊聊 pydub 常见的操作

3-1 AudioSegment 对象

pudub 最重要的一个类是:AudioSegment

它是一个不可变的对象,代表一个音频段对象

为了帮助剪辑小姐姐少熬夜,我用 Python 硬肝了一次短视频音频创作

首先,我们实例化一个 AudioSegment 对象,它内置有多种实现方式

比如,我们从本地加载一个 wav 的音频文件

from pydub import AudioSegment  

# 音频路径  
audio_path = "./raw/1.wav"  

# 指定音频格式,这里以wav音频为例  
format='wav'  

# 实例化一个AudioSegment对象  
audio_segment = AudioSegment.from_file(audio_path, format)  

3-2 裁剪某段音频

针对 AudioSegment 对象,使用中括号指定开始时间和结束时间,即可以快速提取某一段音频

PS:时间以毫秒为单位

# 某一段音频文件  
# 指定开始时间、结束时间  
# 时间以毫秒为单位  
audio_part = audio_segment[start_time:end_time]  

3-3 合并音频

使用 pydub 合并多段音频非常便捷,只需要使用符号 +,将三段音频的 AudioSegment 对象加起来即可

def sound_compound(one_audio_segment, *other):  
    """  
    合并两段音频  
    :param one_audio_segment:  
    :param other_audio_segment:  
    :return:  
    """  
    result = one_audio_segment  

    # 使用符号+,一段一段合并  
    for segment in other:  
        result += segment  
    return result  

# 合并3段音频  
audio_segment1 = AudioSegment.from_file('./1.wav', 'wav')  
audio_segment2 = AudioSegment.from_file('./2.wav', 'wav')  
audio_segment3 = AudioSegment.from_file('./3.wav', 'wav')  

# 合并3段音频文件  
audio_segment_result = sound_compound(audio_segment1, audio_segment2, audio_segment3)

3-4 音频常见属性

音频比较常见的属性包含:

  • 时长

  • 响度

  • 声道数

  • 帧速率

  • 原始数据

对于音频的时长,有 2 种获取方式,即:

# 音频常见属性  
# 实例化AudioSegment对象  
as = AudioSegment.from_file("sound1.wav")  

# duration_seconds:在内部调用了 len() ,单位为秒  
# 方式一,duration_seconds,以秒为单位  
as_duration1 = as.duration_seconds  

# 方式二:len(as),以毫秒为单位  
as_duration2 = (len(as) / 1000.0)  

其他原始数据都可以从 AudioSegment 对象相应的属性中获取 :

# 音频常见属性  
# 实例化AudioSegment对象  
as = AudioSegment.from_file("sound1.wav")  

# 2、音频响度  
as_loudness = as.dBFS  

# 3、声道数  
as_channel_num = as.channels  

# 4、帧速率  
# 一般值为 44100 (CD), 48000 (DVD), 22050, 24000, 12000 和 11025  
as_frame_rate = sound.frame_rate  

# 5、音频的原始数据  
as_raw_data = sound.raw_data  

3-5 单条音频淡入淡出

视频剪辑中,经常需要对音频做淡入淡出处理,使音效播放更加自然

比如:针对单个音频,在开头使用淡入,结束使用淡出,并指定淡入和淡出的时间

PS:单位以毫秒为单位

def sound_fade_in_and_out(one_audio_segment, fade_in=0, fade_out=0):  
    """  
    单段音频设置开头淡入、结尾淡出  
    可以把许多运算符连成一串使用,因为运算符都会返回一个AudioSegment对象  
    :param one_audio_segment:  
    :param fade_in:淡入时间(毫秒)  
    :param fade_out:淡出时间(毫秒)  
    :return:  
    """  
    return one_audio_segment.fade_in(fade_in).fade_out(fade_out)  

audio_segment = AudioSegment.from_file("./raw/1.wav", format='wav')  

# 单条视频开头淡入,结束淡出  
sound_fade_in_and_out(audio_segment,2000,2000)  

需要指出的是,AudioSegment 对象内置的 fade() 函数,可以更加灵活地实现淡入淡出效果

sound = AudioSegment.from_file("./sound.wav")  

# fade实现淡入/淡出效果  
# 1、从1s开始,持续2s,执行淡化效果,并从0dB逐渐增加到3dB  
sound_fade1 = sound.fade(to_gain=+3.0, start=1000, duration=2000)  

# 2、从1s开始,一直到4s,中间1s的时间内执行淡化效果,从0db逐渐降低-2dB  
sound_fade2 = sound1.fade(to_gain=-2, start=1000, end=4000)  

3-6 调整音频播放速度

视频剪辑中,音频速度的调整很常见

比如:在视频结尾,调整最后的画面帧为慢动作,同样需要同步调慢音频的播放速度

def speed_change(sound, speed=1.0):  
    """  
    改变音频的速度  
    :param sound:  
    :param speed:  
    :return:  
    """  
    sound_with_altered_frame_rate = sound._spawn(sound.raw_data, overrides={  
        "frame_rate": int(sound.frame_rate * speed)  
    })  
    return sound_with_altered_frame_rate.set_frame_rate(sound.frame_rate)  

# 改变音频的播放速度  
# 比如:0.8调整为之前速度的0.8  
audio_new = speed_change(self.audio_segment, 0.8)  

3-7 播放音频

AudioSegment 对象使用 pydub 内置的 play() 方法,可以播放音频,在调试代码的时候非常方便
from pydub.playback import play  

sound1 = AudioSegment.from_file("./1.wav")  

# 播放音频  
play(sound1)  
3-8 音量增益及降低  
要调整一段音频的音量,可以直接对 AudioSegment 实例加、减对应的分贝数目即可
def sound_gain(audio_segment, db_value):  
    """  
    声音增益  
    :param audio_segment:  
    :param db_value 分贝  
    :return:  
    """  
    return audio_segment + db_value  


def sound_reduce(audio_segment, db_value):  
    """  
    降低音量  
    :param audio_segment:  
    :param db_value 分贝  
    :return:  
    """  
    return audio_segment - db_value  

# 降低音量,-10分贝  
audio_segment_temp = sound_reduce(audio_segment, 10)  

# 增加音量,+10分贝  
audio_segment_temp1 = sound_gain(audio_segment, 10)  

3-9 交叉淡化效果

使用 append() 方法,可以将多段音频对象进行合并,并添加交叉淡化的效果
PS:使用 crossfade 参数指定交叉淡化的持续时间,单位为毫秒
def sound_overlap_effect(one_audio_segment, other_audio_segment, overlap_during):  
    """  
    两段音频合并的同时,使用交叉淡化的效果  
    :param one_audio_segment:第一段  
    :param other_audio_segment:第二段  
    :param overlap_during:单位毫秒  
    :return:  
    """  
    return one_audio_segment.append(other_audio_segment, crossfade=overlap_during)  

# 两段音频  
audio_segment1 = AudioSegment.from_file('./1.wav', 'wav')  
audio_segment2 = AudioSegment.from_file('./2.wav', 'wav')  

# 合并两段音频,并添加效果  
# 持续时间:2000毫秒  
result = sound_overlap_effect(audio_segment1, audio_segment2, 2000)  

3-10 多声道音频

利用 from_mono_audiosegments() 函数,可以一个轨道上创建多声道音频

def create_multichannel_as(self):  
    """  
    创建多声道音频(支持2个或者多个)  
    :return:  
    """  
    # PS:每个单声道音频段都应该有相同的时长以及帧速率  
    one_as = AudioSegment.from_wav("./1.wav")  
    other_as = AudioSegment.from_wav("./2.wav")  

    # 合成多声道音频  
    return AudioSegment.from_mono_audiosegments(one_as, other_as)  

3-11 提取音频及导出音频

在 3-1 中实例化 AudioSegment 方式,方法同样适用于视频,即:我们可以从视频中提取 AudioSegment 音频对象

使用 AudioSegment 对象的 export(filename,format) 方法,就可以将音频保存到本地了

# 1、从视频中提取一个AudioSegment音频对象  
audio_segment = AudioSegment.from_file(video)  

def save_audio(audio_segment, filename, format):  
    """  
    保存音频文件到本地  
    :param audio_segment:  
    :param filename:  
    :param format:  
    :return:  
    """  
    audio_segment.export(filename, format=format)  

# 2、导出音频到本地  
save_audio(result, './result.wav', 'wav')

4. 实战一下

对搞笑类短视频,经常会采用这种剪辑手法,即:将视频尾部,对最后一段对话降低速度并重新播放一次

准备一段视频素材,下面通过 pydub 来实现它

video_path = './raw.mp4'  

# 注意:加载视频不需要指定format  
audio_sgement = AudioSegment.from_file(video_path)  

# 截取尾部内容  
audio_end = audio_sgement[70 * 1000:70 * 1000 + 3000]  

# 变慢速度,具体根据视频速度去调整  
audio_end2 = speed_change(audio_end, 0.55)  

# 合并两段音频  
audio_result = audio_end + audio_end2  

# 尾部淡出处理  
audio_result.fade_out(1000)  

# 视频导出  
audio_result.export("result.wav", format='wav')  

最后生成的音频内容如下:

5. 最后

文中仅仅对 pydub 常用的操作进行了讲解,更多骚操作可以阅读官方文档去解锁

音视频的一些常见操作都可以做成自动化,让自己从重复的剪辑工作中抽离出来。

我已经将文中完整源码文件传到后台,关注公众号,后台回复「 210106 」即可获得

如果你觉得文章还不错,请大家 点赞、分享、留言 下,因为这将是我持续输出更多优质文章的最强动力!

想要学习更多网络爬虫知识,请点击阅读原文前往爬虫网站。

**-----**------**-----**---**** End **-----**--------**-----**-****

为了帮助剪辑小姐姐少熬夜,我用 Python 硬肝了一次短视频音频创作

往期精彩文章推荐:

为了帮助剪辑小姐姐少熬夜,我用 Python 硬肝了一次短视频音频创作

欢迎各位大佬点击链接加入群聊【helloworld开发者社区】:https://jq.qq.com/?_wv=1027&k=mBlk6nzX进群交流IT技术热点。

本文转自 https://mp.weixin.qq.com/s/NSwiDzmjzuryM8Tco2WOgQ,如有侵权,请联系删除。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Irene181 Irene181
3年前
60行Python代码开发在线markdown编辑器
本文转载自公众号【python大数据分析】,详情可以点击上方卡片,关注该公众号,获取更多好文推荐。❝本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes❞1简介这是我的系列教程「PythonDash快速web应用开发」的第六期,在上一期的文章中,我们完成了对
Irene181 Irene181
3年前
秀的一批,那些你不得不知的 PyCharm 高效操作
本文转载自公众号【Python技术】,详情可以点击上方卡片,关注该公众号,获取更多好文推荐。文|豆豆来源:Python技术「ID:pythonall」熟话说,工欲善其事,必先利其器,PyCharm作为最好用的IDE工具,有着各种各样的骚操作,这是高级开发工程师必须熟悉的基本技能。今天就给大家推荐一些秀的一批的高效操作。让你脱离CV
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Python之time模块的时间戳、时间字符串格式化与转换
Python处理时间和时间戳的内置模块就有time,和datetime两个,本文先说time模块。关于时间戳的几个概念时间戳,根据1970年1月1日00:00:00开始按秒计算的偏移量。时间元组(struct_time),包含9个元素。 time.struct_time(tm_y
Stella981 Stella981
3年前
Docker 部署SpringBoot项目不香吗?
  公众号改版后文章乱序推荐,希望你可以点击上方“Java进阶架构师”,点击右上角,将我们设为★“星标”!这样才不会错过每日进阶架构文章呀。  !(http://dingyue.ws.126.net/2020/0920/b00fbfc7j00qgy5xy002kd200qo00hsg00it00cj.jpg)  2
Stella981 Stella981
3年前
200的大额人民币即将面世?央行:Yes!
点击上方蓝字关注我们!(https://oscimg.oschina.net/oscnet/2a1c2ac00bf54458a78c48a6c2e547d5.png)点击上方“印象python”,选择“星标”公众号重磅干货,第一时间送达!!(
可莉 可莉
3年前
200的大额人民币即将面世?央行:Yes!
点击上方蓝字关注我们!(https://oscimg.oschina.net/oscnet/2a1c2ac00bf54458a78c48a6c2e547d5.png)点击上方“印象python”,选择“星标”公众号重磅干货,第一时间送达!!(