背景需求
在处理音频中,我们可能会有这样的场景:随着语音设备的能力越来越强,音频数据越来越大。但实际上,音频中的有效部分却很少,抑或是音频的背景声过大,非目标声音。在这样的场景下,我们希望得到人声,去掉噪声,提高信噪比。
问题界定
这里将问题进行界定,进行子任务拆分:
- 将音频的背景声音去除,
- 去除“无声”阶段。
解决方案
要提高信噪比,这需求在很多场景中有见:比如课堂录音的提取,或者是录音笔的数据存储。
在使用本领域“高深”的技术前,一定要思考,切莫手上有锤子,就看啥都像钉子。想想该领域的专家会怎么做,如何从专业角度看待该问题;其次想想普通人会怎么做,防止落入经验主义陷阱。
背景声音的剥离,最简单的其实是音轨分离。其前提是两种声音存为了不同的音轨,在一些场景很合适。比如电话录音。
背景声分离
但是若只有一个音轨呢?别担心,机器学习来帮助你。spleeter 基于 tensorflow,训练了一套音乐检索系统,能够有效的分离人声和背景音乐声。
该工具已经进行封装,对于简单的人声分离,采用直接调取的方式即可。代码如下
# Use audio loader explicitly for loading audio waveform :
from spleeter.audio.adapter import get_default_audio_adapter
audio_loader = get_default_audio_adapter()
sample_rate = 44100
waveform, _ = audio_loader.load('/path/to/audio/file', sample_rate=sample_rate)
# Perform the separation :
prediction = separator.separate(waveform)
空白切割
在分离之后,得到人声和背景声。人声分离后,仔细听,就会发现里面有很多空白。对于空白部分,进行切割分离。
这里参考 stackoverflow 的代码
from pydub import AudioSegment
from pydub.utils import db_to_float
# Let's load up the audio we need...
podcast = AudioSegment.from_mp3("podcast.mp3")
intro = AudioSegment.from_wav("intro.wav")
outro = AudioSegment.from_wav("outro.wav")
# Let's consider anything that is 30 decibels quieter than
# the average volume of the podcast to be silence
average_loudness = podcast.rms
silence_threshold = average_loudness * db_to_float(-30)
# filter out the silence
podcast_parts = (ms for ms in podcast if ms.rms > silence_threshold)
# combine all the chunks back together
podcast = reduce(lambda a, b: a + b, podcast_parts)
# add on the bumpers
podcast = intro + podcast + outro
# save the result
podcast.export("podcast_processed.mp3", format="mp3")
最后,得到完整的人声部分。
其它参考
Noise reduction using spectral gating in python