Skip to content

使用 Python 进行 AI – 语音识别

使用 Python 进行现代 AI – 语音识别

Section titled “使用 Python 进行现代 AI – 语音识别”

在本章中,我们将使用 Python 探索迷人的语音识别世界,它是人工智能(AI)的一个关键组成部分。我们将介绍机器如何理解人类语音以及其中涉及的现代技术。

语音是人类交流的基础。人工智能(AI)中的语音处理主要目标是实现人类与机器之间的无缝交互。这涉及几个相互关联的任务:

  • 首先,自动语音识别(ASR),它允许机器将语音中的词、短语和句子转录成文本。
  • 其次,自然语言处理(NLP),使机器能够理解转录文本背后的含义和意图。
  • 第三,语音合成(Text-to-Speech, TTS),它允许机器从文本生成类似人类的语音。

本章主要关注自动语音识别(ASR)。我们将深入探讨如何由麦克风捕获或从文件读取的原始音频信号,经过系统处理和解释以识别 spoken words(说出的词语)。

自动语音识别(ASR)是许多人工智能(AI)应用的基础技术,从像 Siri 和 Alexa 这样的语音助手到听写软件和车载控制系统。构建一个强大的 ASR 系统是一项复杂的任务,因为人类语音固有的多变性。

创建一个高准确度的 ASR 系统面临诸多挑战。这些挑战可以从几个维度进行分类:

  • 词汇量大小:针对小而固定词汇(例如语音菜单中的“是”、“否”、“下一项”)设计的系统,比针对大词汇量(例如包含数万词汇的通用听写)设计的系统更容易构建。
  • 通道和录音质量:来自近距离麦克风的高保真音频比来自远距离麦克风或低带宽电话通话的嘈杂音频更容易处理。
  • 说话模式:孤立的词语比连贯的词语(短语)或连续的、会话性的语音更容易识别,会话性语音通常包含不流畅和语速变化(coarticulation)。
  • 说话风格:朗读的语音(例如有声书)通常比自发的、会话性的语音更清晰、更正式,后者更具挑战性。
  • 说话人变异性:系统可以是说话人依赖型的(为特定用户训练),说话人自适应型的(随时间适应新用户),或说话人独立型的(旨在适用于任何用户)。说话人独立型系统最复杂,但也最通用。
  • 噪声水平:信噪比(SNR)显著影响性能。高 SNR (>30dB) 环境是理想的,而低 SNR (<10dB) 且有明显背景噪音的环境则是一个主要障碍。
  • 口音和方言:地区口音、方言和个人说话习惯增加了复杂性。

尽管存在这些挑战,但重大的进步,特别是深度学习的发展,已经催生了高效的 ASR 系统。构建或理解一个语音识别器的基本步骤包括信号处理、特征提取、声学模型和语言模型。

任何音频处理任务的第一步是加载和理解音频信号的结构。现代 ASR 系统通常处理数字音频。

当声音被录制时,它是一个模拟波。为了由计算机处理,它必须被数字化。这包括:

  • 采样:模拟信号以规则间隔进行采样。每秒的样本数是采样率(例如,CD 质量为 44100 Hz,语音常用 16000 Hz)。更高的采样率捕获更多细节。
  • 量化:每个样本的振幅被映射到一个离散的数值。位深(例如 16 位、24 位)决定了这些值的分辨率。

我们将使用 librosa 库,这是一个用于音频和音乐分析的强大 Python 包。如果您尚未安装它,可以使用 pip 进行安装:

pip install librosa matplotlib numpy

让我们加载一个音频文件(例如,一个 WAV 文件)并可视化其波形。请确保您的工作目录中有一个名为 example_audio.wav 的音频文件,或提供正确的路径。

首先,导入必要的库:

import librosa
import librosa.display
import matplotlib.pyplot as plt
import numpy as np

现在,加载音频文件。librosa.load() 返回音频时间序列(作为 NumPy 数组)和采样率。

# Replace 'example_audio.wav' with the path to your audio file
audio_file_path = 'example_audio.wav'
try:
audio_signal, sampling_rate = librosa.load(audio_file_path, sr=None) # sr=None to preserve original sampling rate
except FileNotFoundError:
print(f"Error: The file {audio_file_path} was not found.")
print("Please ensure you have a valid audio file and path.")
# As a fallback for the tutorial, create a dummy signal if file not found
sampling_rate = 22050 # A common default
duration = 3 # seconds
audio_signal = np.sin(2 * np.pi * 440 * np.linspace(0, duration, int(sampling_rate * duration)))
print("Using a dummy sine wave for demonstration.")
print(f'Signal Shape: {audio_signal.shape}')
print(f'Sampling Rate (Hz): {sampling_rate}')
print(f'Signal Datatype: {audio_signal.dtype}')
print(f'Signal Duration (s): {librosa.get_duration(y=audio_signal, sr=sampling_rate):.2f}')

librosa.load 会自动将音频信号归一化到 -1 到 1 之间。让我们可视化波形:

plt.figure(figsize=(12, 4))
librosa.display.waveshow(audio_signal, sr=sampling_rate)
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.title('Audio Waveform')
plt.tight_layout()
plt.show()

此图显示了音频信号的振幅随时间的变化。您将看到对应于声音强度的变化。对于语音,这些变化代表 spoken words(说出的词语)和静默。

预期输出(文本,实际图表将由 matplotlib 显示):

Signal Shape: (some_number,)
Sampling Rate (Hz): your_audio_sampling_rate (e.g., 22050 or 44100)
Signal Datatype: float32
Signal Duration (s): duration_of_your_audio_file (e.g., 3.00 seconds)

该图将是一个显示振幅随时间波动的波形图。

虽然时域波形很有用,但语音中的大部分信息在频域中更容易理解。短时傅里叶变换(STFT)常用于分析信号的频率内容如何随时间变化。结果通常被可视化为声谱图。

使用先前示例中的 audio_signal 和 sampling_rate:

# Compute STFT
stft_signal = librosa.stft(audio_signal)
# Convert amplitude to decibels (dB) for better visualization
स्पेक्टrogram_db = librosa.amplitude_to_db(abs(stft_signal), ref=np.max)
# Plot the spectrogram
plt.figure(figsize=(12, 6))
librosa.display.specshow(स्पेक्टrogram_db, sr=sampling_rate, x_axis='time', y_axis='hz') # or y_axis='log' for logarithmic frequency
plt.colorbar(format='%+2.0f dB')
plt.title('Spectrogram (Hz scale)')
plt.tight_layout()
plt.show()

该声谱图在 x 轴上显示时间,在 y 轴上显示频率,并使用颜色表示每个频率分量(单位为分贝,dB)的强度。颜色较深的区域表示这些频率的能量较高。对于语音,您通常可以看到共振峰(声道的共振频率)显示为水平条带。

一种常见的变体是梅尔声谱图,它使用梅尔尺度来表示频率,模仿人类听觉感知。这是提取梅尔频率倒谱系数(MFCCs)的关键步骤。

# Compute Mel spectrogram
mel_spectrogram = librosa.feature.melspectrogram(y=audio_signal, sr=sampling_rate, n_mels=128, fmax=8000) # n_mels: number of Mel bands
mel_spectrogram_db = librosa.power_to_db(mel_spectrogram, ref=np.max)
# Plot the Mel spectrogram
plt.figure(figsize=(12, 6))
librosa.display.specshow(mel_spectrogram_db, sr=sampling_rate, x_axis='time', y_axis='mel', fmax=8000)
plt.colorbar(format='%+2.0f dB')
plt.title('Mel Spectrogram')
plt.tight_layout()
plt.show()

这些声谱图图将显示音频的时频表示。第一个将具有线性或对数频率轴,而梅尔声谱图将使用梅尔频率尺度,这对语音通常更具信息量。

理解信号生成有助于巩固概念。让我们创建一个简单的正弦波(一个纯音)并将其保存为 WAV 文件。我们将使用 NumPy 进行生成,并使用 soundfile 库进行保存(因为 scipy.io.wavfile.write 处理浮点数据或归一化有时会比较麻烦)。

如果您还没有安装 soundfile,请安装:pip install soundfile

pip install soundfile
import numpy as np
import matplotlib.pyplot as plt
import soundfile as sf # For saving audio files
# Parameters for the tone
duration_tone = 3 # seconds
sampling_rate_tone = 44100 # Hz
frequency_tone = 440 # Hz (A4 note)
# Generate time axis
time_axis = np.linspace(0, duration_tone, int(sampling_rate_tone * duration_tone), endpoint=False)
# Generate sine wave
tone_signal = 0.5 * np.sin(2 * np.pi * frequency_tone * time_axis) # 0.5 amplitude to avoid clipping
# Save the generated audio to a file
output_file = 'generated_tone.wav'
try:
sf.write(output_file, tone_signal, sampling_rate_tone)
print(f"Generated tone saved to {output_file}")
except Exception as e:
print(f"Error saving audio file: {e}")
# Visualize a small portion of the generated signal
plt.figure(figsize=(10, 4))
plt.plot(time_axis[:500], tone_signal[:500]) # Plot first 500 samples
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.title(f'Generated Sine Wave ({frequency_tone} Hz)')
plt.grid(True)
plt.show()

这段代码生成了一个 3 秒的 440 Hz 纯音音频信号并将其保存。该图将显示一个完美的正弦波,代表生成的纯音。

原始音频甚至声谱图都是高维的。对于 ASR,我们需要提取紧凑且信息丰富的特征。梅尔频率倒谱系数(MFCCs)是广泛使用的传统特征,它们捕获声道的基本特征,并且对变化具有一定的鲁棒性。

继续使用我们加载的音频文件中的 audio_signal 和 sampling_rate:

# Extract MFCCs
# Common parameters: n_mfcc (number of coefficients), hop_length, win_length
mfccs = librosa.feature.mfcc(y=audio_signal, sr=sampling_rate, n_mfcc=13)
print(f'MFCCs Shape: {mfccs.shape}') # (n_mfcc, number_of_frames)
# Visualize the MFCCs
plt.figure(figsize=(12, 4))
librosa.display.specshow(mfccs, sr=sampling_rate, x_axis='time')
plt.colorbar()
plt.title('MFCCs')
plt.tight_layout()
plt.show()

mfccs 数组将有 n_mfcc 行(系数)和与时间帧对应的列数。该可视化显示了这些系数如何随时间变化,代表语音的语音内容。

预期输出(文本):

MFCCs Shape: (13, number_of_frames_in_your_audio)

该图将显示随时间变化的 MFCC 特征,不同的颜色表示系数的值。这是用于识别模型的语音特征的标准表示方法。

虽然 MFCCs 是基础,但现代 ASR 系统,特别是深度学习模型,通常直接从声谱图甚至原始音频学习特征,或使用更高级的特征表示,如感知线性预测(PLP)系数或滤波器组能量。

使用 SpeechRecognition 库进行语音识别

Section titled “使用 SpeechRecognition 库进行语音识别”

现在,让我们进行实际的语音识别。SpeechRecognition 库提供了一种方便的方式来使用各种语音识别引擎,包括在线 API(如 Google Web Speech API, Wit.ai)和离线引擎(如 CMU Sphinx)。

安装库:pip install SpeechRecognition PyAudio(PyAudio 需要用于麦克风输入)。如果您在安装 PyAudio 时遇到问题,请查阅其文档以获取特定平台的说明(例如,在 Windows 上您可能需要预编译的二进制文件,或者在 Linux 上需要 portaudio 开发库)。

此示例将使用您的麦克风捕获音频,并使用 Google Web Speech API 进行识别。需要互联网连接。

import speech_recognition as sr
# Initialize the recognizer
recognizer = sr.Recognizer()
# Use the default microphone as the audio source
with sr.Microphone() as source:
print("正在校准麦克风以适应环境噪音... 请稍候。")
# Adjust for ambient noise for 1-2 seconds for better accuracy
recognizer.adjust_for_ambient_noise(source, duration=1)
print("麦克风已校准。请清晰地说些话!")
try:
audio_data = recognizer.listen(source, timeout=5, phrase_time_limit=10) # Listen for up to 5s, max 10s phrase
print("正在识别您的语音...")
# Recognize speech using Google Web Speech API
text = recognizer.recognize_google(audio_data)
print(f"您说的是:{text}")
except sr.WaitTimeoutError:
print("在超时时间内未检测到语音。")
except sr.UnknownValueError:
print("Google Web Speech API 无法理解音频。")
except sr.RequestError as e:
print(f"无法从 Google Web Speech API 请求结果;{e}")
except Exception as e:
print(f"发生了一个意外错误:{e}")

运行此代码时,它将监听您的声音。您说完话后,它将尝试转录您所说的话。

示例交互(文本):

正在校准麦克风以适应环境噪音... 请稍候。
麦克风已校准。请清晰地说些话!
(您说:“Hello world AI”)
正在识别您的语音...
您说的是:hello world AI

您还可以从现有的音频文件(例如 WAV 格式)识别语音。请确保文件清晰。

# Assuming 'example_audio.wav' is a clear recording of speech
audio_file_for_recognition = 'example_audio.wav'
with sr.AudioFile(audio_file_for_recognition) as source:
try:
audio_data_file = recognizer.record(source) # Read the entire audio file
print(f"正在识别音频文件 {audio_file_for_recognition} 中的语音...")
text_from_file = recognizer.recognize_google(audio_data_file)
print(f"音频文件包含:{text_from_file}")
except FileNotFoundError:
print(f"错误:未找到文件 {audio_file_for_recognition}。")
except sr.UnknownValueError:
print("Google Web Speech API 无法理解文件中的音频。")
except sr.RequestError as e:
print(f"无法从 Google Web Speech API 请求结果;{e}")
except Exception as e:
print(f"发生了一个意外错误:{e}")

SpeechRecognition 库也支持其他引擎。例如,recognizer.recognize_sphinx(audio_data) 可用于使用 CMU Sphinx 进行离线识别(需要安装 PocketSphinx:pip install pocketsphinx)。这对于没有互联网访问或出于隐私考虑的应用非常有用。

对于更高级或定制的 ASR 解决方案,可以考虑探索像 Kaldi 这样的工具包,或来自 Hugging Face Transformers(例如 Wav2Vec2, Whisper)、TensorFlow 或 PyTorch 的预训练深度学习模型。这些通常能提供更高的准确率,但需要更多的设置和计算资源。

进一步学习资源: