Python处理音频文件的实用姿势
每天叫醒我的不是理想,是楼下广场舞的音乐。
音乐是人类的通用语言,不分国界不分种族。
抖音短视频爆火的关键因素之一,就是普通人也能便捷地使用BGM表达自我。
从感性角度看,音乐可以有很多种解释,如:
- 音乐是有逻辑的声音。
- 音乐是以声音和时间为材料的艺术。
- 音乐是思想情感的表达,是精神的延续。
- ……
而从数学角度看,音乐就是时间和频率的关系。
声音的本质是波,人类听觉的原理就是波引起了耳朵鼓膜的振动。
人们用不同乐器、不同力度,在一段连续时间里敲击,就组合出了时间和频率的关系。
一切物体都有自己的频率,所以整个世界也可以理解为一篇乐章。
当音乐被计算机数字化后,我们就可以用文件的形式保存它。但现实世界的声音是连续的,而计算机世界是离散(由0和1组成)的。想要用计算机捕捉声音,就得把连续信息转为离散的数据,这个过程就是信号的“模数转化”。
处理过程中最关键的参数就是“采样率”,即每秒钟用多少份数据表达声音信号。此外每份数据大小以及声道数,与采样率一起,决定了保存后声音和原声间的差距。
和图像一样,音乐也有很多种压缩算法。所谓“无损音乐”,就是确保源文件信息不丢失情况下压缩数据,常见格式如flac
、ape
、wav
;更常见的音乐格式是mp3
,是一种有损压缩格式,虽然老旧,但依旧流行。
Python标准模块wave
支持wav
文件读写,但涉及到压缩算法时,都需要借助外部模块。其中功能最全也最流行的就是ffmpeg
,它是开源视频处理软件,支持绝大多数的音视频格式编码,被广泛引用于各大视频网站和商业软件。
ffmpeg
ffmpeg安装
ffmpeg
需要独立安装,网上大部分教程都已过时,最好参考官方文档。
比如在MacOS上通过Homebrew
的安装方法:
brew install ffmpeg
brew tap homebrew-ffmpeg/ffmpeg
brew install homebrew-ffmpeg/ffmpeg/ffmpeg
以上就是ffmepg
的完全安装,也可以根据自己需要定制选项:
- 查看可选项:
brew options homebrew-ffmpeg/ffmpeg/ffmpeg
- 安装关联选项:
brew install homebrew-ffmpeg/ffmpeg/ffmpeg --with-libvorbis --with-sdl2 --with-theora
安装完后,通过ffprobe
可以获取音视频文件的详细信息:ffprobe -i 音视频文件
。
ffmpeg基本使用
通过ffmpeg
命令可以对音视频文件进行格式转换、拼接、切割、放大缩小、提取图片/音频/字幕等操作。
ffmpeg
的命令格式:
$ ffmpeg [全局选项] {
[输入文件选项] -i 输入_url_地址} {
[输出文件选项] 输出_url_地址} ...
其中,常用命令行参数如下:
- -c:指定编码器
- -c copy:直接复制不编码更快
- -c:v:指定视频编码器
- -c:a:指定音频编码器
- -i:指定输入文件
- -an:去除音频流
- -vn: 去除视频流
- -preset:指定输出视频质量
使用ffmpeg -formats
可列出支持的文件格式。
比如,想要转换音视频文件格式:
$ ffmpeg -i video.mp4 video.avi
比如要从视频里提取音频:
$ ffmpeg -i input.mp4 -vn output.mp3
音视频几乎所有的基本剪辑操作都可以用ffmpeg
完成。ffmpeg
养活了不少视频剪辑软件公司。
音频处理场景
如果仅仅是需要批量转格式,或者按固定标准剪辑音视频,ffmpeg
足够应付,最多就是多些几行shell
命令,比如增加个循环实现批量文件处理。
但如果涉及到对音视频内容处理,如实现视频效果、提取音频高潮等场景,就需要借助三方模块了。
Python处理音频数据等常见模块有2个:
librosa
,擅长音频信号处理,内部用numpy
存储数据,读写文件依赖soundfile
模块(不支持mp3)。pydub
,底层基于ffmpeg
读写文件,代码简洁,支持切割、格式转换、音量、ID3等常用功能,门槛低。
模块安装:
pip install librosa
pip install pydub
使用建议:日常用pydub
足够应付,更强大的信号处理则需要librosa
,但有一定数学门槛,需要了解信号处理原理,掌握傅立叶变换等基本算法。
本文重点介绍pydub
模块使用,包括如下常见音频处理场景:
- 基本操作:切割、合并、音量增减、过渡效果
- 提取背景音乐:从视频提取音频、说话声与背景音乐分离
- 提取音乐高潮
- 语音智能处理:语音识别、合成、克隆
基本操作
pydub
最核心的类是AudioSegment
,几乎包含所有基本操作。
pydub基本文件读写
import pathlib
import pydub
from pydub import AudioSegment
from pydub.utils import mediainfo
path = list(pathlib.Path.cwd().parents)[1].joinpath('data/automate/007audio')
mp3_path = path.joinpath('1.mp3')
out_path = path.joinpath('007audio_pydub_export.mp3')
# 默认采样率44100Hz
snd = AudioSegment.from_mp3(mp3_path)
info = mediainfo(mp3_path)
print(info) # ID3信息
print(snd.duration_seconds, snd.frame_rate) # 音频时长,采样率
snd.export(out_path, format='mp3', bitrate='32k') # 转成mp3格式
切割、合并、音量、过渡效果
import pathlib
from pydub import AudioSegment
path = list(pathlib.Path.cwd().parents)[1].joinpath('data/automate/007audio')
mp3_path = path.joinpath('1.mp3')
cover_path = path.joinpath('cover.jpg')
snd = AudioSegment.from_mp3(mp3_path)
# 获取时长、分贝数、采样率
print(snd.duration_seconds, snd.dBFS, snd.frame_rate)
# 剪30秒核心片段,单位为毫秒
snd_mid = snd[120000:150000]
# 调大音量,单位分贝
snd_mid += 6
# 剪最后30秒片段
snd_end = snd[-30000:]
# 淡入淡出效果
snd_final = snd_mid.append(snd_end, crossfade=1500