第5篇-AI的耳朵

计算机如何"听"声音?

语音识别的过程可以类比为“翻译”:

语音数字化:把语音信号“翻译”成计算机能理解的数字信号。
特征提取:从数字信号中提取“关键信息”,就像提取语音的“指纹”。
模型匹配:用预训练的模型将这些“指纹”与已知的语音模式进行匹配,找到对应的文本。
文本输出:把匹配到的文本“翻译”出来,就像把语音“翻译”成文字一样。

1 声音的数字化表示

声音在计算机中是如何表示的?
可以有多种形式表示声音:

  • 波形图
  • 梅尔频谱图(频域图)
  • 显示色谱图(音高特征)
    也有很多声音的特征来辅助分析声音:
  • 响度:反映声音的响亮程度
  • 过零率:反映信号频率变化的快慢,对语音检测很有用
  • BPM (Beats Per Minute):每分钟节拍数,反映音乐节奏的快慢
# 基础音频处理示例
# 这个程序可以分析音频文件的各种特征,包括波形、频谱和音高等

# 导入必要的库
import librosa  # 音频处理的主要库
import librosa.display  # 用于显示音频相关的图形
import matplotlib.pyplot as plt  # 绘图库
import numpy as np  # 数值计算库
from matplotlib import font_manager  # 字体管理
import soundfile as sf  # 音频文件读取库,支持更多音频格式

# 在运行这个程序之前,需要安装以下依赖:
# pip install soundfile numpy matplotlib librosa

# 设置中文字体,解决中文显示问题
try:
    # macOS 常用中文字体,按优先级排序
    plt.rcParams['font.sans-serif'] = ['PingFang HK', 'Arial Unicode MS', 'SimHei']
    plt.rcParams['axes.unicode_minus'] = False  # 解决负号'-'显示为方块的问题
except:
    print("警告: 未找到合适的中文字体,可能会显示乱码")

def analyze_audio(audio_path):
    """
    分析音频文件的主函数
    参数:
        audio_path: 音频文件的路径
    """
    try:
        # 第一步:加载音频文件
        print("正在加载音频文件...")
        try:
            # 首先尝试使用 soundfile 加载(支持更多音频格式)
            audio, sr = sf.read(audio_path)
            # 如果是立体声(多声道),转换为单声道
            if len(audio.shape) > 1:
                audio = np.mean(audio, axis=1)  # 对所有声道取平均
        except Exception as e:
            # 如果 soundfile 加载失败,使用 librosa 的新方法加载
            # 使用 load_audio 替代已弃用的 audioread_load
            audio, sr = librosa.load(audio_path, sr=None, mono=True)
            print(f"注意: 使用备选方法加载音频 - {str(e)}")
        
        # 计算音频时长(采样点数/采样率)
        duration = len(audio) / sr
        
        # 打印音频基本信息
        print(f"\n音频信息:")
        print(f"采样率: {sr} Hz")  # 每秒采样次数
        print(f"时长: {duration:.2f} 秒")
        print(f"采样点数: {len(audio)}")
        
        # 第二步:创建图形窗口
        plt.figure(figsize=(15, 10))  # 设置图形大小
        
        # 2.1 显示波形图(时域图)
        plt.subplot(311)  # 3行1列的第1个子图
        # 创建时间轴:将采样点转换为实际时间(秒)
        times = np.arange(len(audio)) / sr
        plt.plot(times, audio)
        plt.title('音频波形图', fontsize=12)
        plt.xlabel('时间 (秒)', fontsize=10)
        plt.ylabel('振幅', fontsize=10)
        plt.grid(True)  # 显示网格线
        
        # 2.2 显示梅尔频谱图(频域图)
        plt.subplot(312)  # 3行1列的第2个子图
        # 计算梅尔频谱图(模拟人耳对声音的感知)
        mel_spect = librosa.feature.melspectrogram(y=audio, sr=sr)
        # 转换为分贝单位
        mel_spect_db = librosa.power_to_db(mel_spect, ref=np.max)
        # 显示频谱图
        img = librosa.display.specshow(mel_spect_db, 
                                     x_axis='time',  # x轴显示时间
                                     y_axis='mel',   # y轴显示梅尔频率
                                     sr=sr)
        plt.colorbar(img, format='%+2.0f dB')  # 添加颜色条,显示分贝值
        plt.title('梅尔频谱图 (频率特征)', fontsize=12)
        plt.xlabel('时间 (秒)', fontsize=10)
        plt.ylabel('频率', fontsize=10)
        
        # 2.3 显示色谱图(音高特征)
        plt.subplot(313)  # 3行1列的第3个子图
        # 计算色谱图(显示音高特征)
        chromagram = librosa.feature.chroma_stft(y=audio, sr=sr)
        librosa.display.specshow(chromagram,
                               x_axis='time',   # x轴显示时间
                               y_axis='chroma') # y轴显示音高
        plt.colorbar()  # 添加颜色条
        plt.title('音高特征图', fontsize=12)
        plt.xlabel('时间 (秒)', fontsize=10)
        plt.ylabel('音高', fontsize=10)
        
        # 调整子图布局
        plt.tight_layout(pad=2.0)  # 设置子图间距
        plt.suptitle('音频分析结果', fontsize=14, y=1.02)  # 添加总标题
        
        # 保存和显示图形
        plt.savefig('audio_analysis.png', dpi=300, bbox_inches='tight')
        print("\n分析图已保存为 'audio_analysis.png'")
        plt.show()
        
        # 第三步:计算和显示音频特征
        print("\n音频特征分析:")
        print("-" * 40)
        
        # 3.1 计算音频的响度(音量大小)
        rms = librosa.feature.rms(y=audio)[0]  # 均方根能量
        print(f"平均响度: {float(np.mean(rms)):.4f}")
        
        # 3.2 计算过零率(信号正负变化的频率)
        zero_crossings = librosa.zero_crossings(audio, pad=False)
        print(f"过零率: {int(sum(zero_crossings))}")
        
        # 3.3 检测音频节奏
        try:
            tempo, _ = librosa.beat.beat_track(y=audio, sr=sr)
            # 修复:确保我们获取数组中的单个值
            tempo_value = tempo.item() if hasattr(tempo, 'item') else tempo
            print(f"估计节奏: {int(tempo_value)} BPM")
        except:
            print("无法检测节奏")
            
        print("-" * 40)
        
        # 添加特征解释
        print("\n特征说明:")
        print("- 响度:反映声音的响亮程度")
        print("- 过零率:反映信号频率变化的快慢,对语音检测很有用")
        print("- BPM (Beats Per Minute):每分钟节拍数,反映音乐节奏的快慢")
        
    except FileNotFoundError:
        print(f"找不到音频文件: {audio_path}")
    except Exception as e:
        print(f"处理音频时出错: {str(e)}")

# 程序入口
if __name__ == "__main__":
    # 设置要分析的音频文件路径
    audio_path = "test.m4a"  # 可以替换为其他音频文件
    print(f"正在分析音频文件: {audio_path}")
    analyze_audio(audio_path) 

1.2、运行结果

正在分析音频文件: test.m4a
正在加载音频文件...
/Users/jayliu/Downloads/文章分享/大白话说AI/4-3-audio_basic.py:41: UserWarning: PySoundFile failed. Trying audioread instead.
  audio, sr = librosa.load(audio_path, sr=None, mono=True)
/Users/jayliu/Downloads/文章分享/大白话说AI/venv/lib/python3.11/site-packages/librosa/core/audio.py:184: FutureWarning: librosa.core.audio.__audioread_load
        Deprecated as of librosa version 0.10.0.
        It will be removed in librosa version 1.0.
  y, sr_native = __audioread_load(path, offset, duration, dtype)
注意: 使用备选方法加载音频 - Error opening 'test.m4a': Format not recognised.

音频信息:
采样率: 48000 Hz
时长: 6.65 秒
采样点数: 319424

分析图已保存为 'audio_analysis.png'

在这里插入图片描述

2 语音识别实例

使用python简单的语音库和google的语音转文字的库:

# 语音识别程序
import sounddevice as sd
import numpy as np
import speech_recognition as sr
from scipy.io import wavfile

def record_audio(duration=5, sample_rate=44100):
    """
    录制音频
    duration: 录制时长(秒)
    sample_rate: 采样率
    """
    print(f"开始录音,持续 {duration} 秒...")
    # 使用 sounddevice 录制音频
    recording = sd.rec(
        int(duration * sample_rate),
        samplerate=sample_rate,
        channels=1,
        dtype=np.int16
    )
    sd.wait()  # 等待录音完成
    print("录音完成!")
    return recording, sample_rate

def save_audio(recording, sample_rate, filename="recording.wav"):
    """保存录音为 WAV 文件"""
    wavfile.write(filename, sample_rate, recording)
    return filename

def transcribe_audio(audio_file):
    """将音频转换为文字"""
    recognizer = sr.Recognizer()
    with sr.AudioFile(audio_file) as source:
        audio = recognizer.record(source)
        try:
            # 使用Google的在线语音识别服务,免费但有限制:
            # - 每天有配额限制
            # - 需要网络连接
            # - 可能不够稳定
            text = recognizer.recognize_google(audio, language='zh-CN')  # 免费API,但建议替换为付费的商业API以获得更好的服务
            return text
        except sr.UnknownValueError:
            return "无法识别音频内容"
        except sr.RequestError as e:
            return f"无法连接到语音识别服务:{e}"

def main():
    """主函数"""
    try:
        # 安装依赖提示
        print("确保已安装必要的依赖:")
        print("pip install sounddevice numpy scipy SpeechRecognition")
        
        input("按回车键开始录音...")
        
        # 录制音频
        recording, sample_rate = record_audio()
        
        # 保存音频文件
        audio_file = save_audio(recording, sample_rate)
        
        # 识别音频内容
        print("\n正在识别音频...")
        text = transcribe_audio(audio_file)
        print("\n识别结果:")
        print(text)
        
    except Exception as e:
        print(f"发生错误: {str(e)}")
        print("可能的原因:")
        print("1. 麦克风未正确连接")
        print("2. 系统没有麦克风访问权限")

if __name__ == "__main__":
    main() 

3、运行结果

确保已安装必要的依赖:
pip install sounddevice numpy scipy SpeechRecognition
按回车键开始录音...
开始录音,持续 5 秒...
录音完成!

正在识别音频...

识别结果:
hello everyone my name is
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值