背景需求

在处理音频中,我们可能会有这样的场景:随着语音设备的能力越来越强,音频数据越来越大。但实际上,音频中的有效部分却很少,抑或是音频的背景声过大,非目标声音。在这样的场景下,我们希望得到人声,去掉噪声,提高信噪比。

问题界定

这里将问题进行界定,进行子任务拆分:

  1. 将音频的背景声音去除,
  2. 去除“无声”阶段。

解决方案

以保持最高的信噪比。这以需求在很多场景中有见:比如课堂录音的提取,或者是录音笔的数据存储。

在使用本领域“高深”的技术前,一定要思考,切莫手上有锤子,就看啥都像钉子。想想该领域的专家会怎么做,如何从专业角度看待该问题;其次想想普通人会怎么做,防止落入经验主义陷阱。

背景声音的剥离,最简单的其实是音轨分离。其前提是两种声音存为了不同的音轨,在一些场景很合适。比如电话录音。

背景声分离

但是若只有一个音轨呢?别担心,机器学习来帮助你。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

Udacity 2018 Machine Learning Nanodegree Capstone project

关于作者