1. 程式人生 > 實用技巧 >【AI模型測試】使用Python實現語音檔案的特徵提取

【AI模型測試】使用Python實現語音檔案的特徵提取

參考地址:https://blog.csdn.net/qq_30091945/article/details/80941820

概述

語音識別是當前人工智慧的比較熱門的方向,技術也比較成熟,各大公司也相繼推出了各自的語音助手機器人,如百度的小度機器人、阿里的天貓精靈等。語音識別演算法當前主要是由RNN、LSTM、DNN-HMM等機器學習和深度學習技術做支撐。但訓練這些模型的第一步就是將音訊檔案資料化,提取當中的語音特徵。


MP3檔案轉化為WAV檔案

錄製音訊檔案的軟體大多數都是以mp3格式輸出的,但mp3格式檔案對語音的壓縮比例較重,因此首先利用ffmpeg將轉化為wav原始檔案有利於語音特徵的提取。其轉化程式碼如下:

from pydub import AudioSegment
import pydub

def MP32WAV(mp3_path,wav_path):
    """
    這是MP3檔案轉化成WAV檔案的函式
    :param mp3_path: MP3檔案的地址
    :param wav_path: WAV檔案的地址
    """
    pydub.AudioSegment.converter = "D:\\ffmpeg\\bin\\ffmpeg.exe"
    MP3_File = AudioSegment.from_mp3(file=mp3_path)
    MP3_File.export(wav_path,format="wav")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

讀取WAV語音檔案,對語音進行取樣

利用wave庫對語音檔案進行取樣。程式碼如下:

import wave
import json

def Read_WAV(wav_path):
    """
    這是讀取wav檔案的函式,音訊資料是單通道的。返回json
    :param wav_path: WAV檔案的地址
    """
    wav_file = wave.open(wav_path,'r')
    numchannel = wav_file.getnchannels()          # 聲道數
    samplewidth = wav_file.getsampwidth()      # 量化位數
    framerate = wav_file.getframerate()        # 取樣頻率
    numframes = wav_file.getnframes()           # 取樣點數
    print("channel", numchannel)
    print("sample_width", samplewidth)
    print("framerate", framerate)
    print("numframes", numframes)
    Wav_Data = wav_file.readframes(numframes)
    Wav_Data = np.fromstring(Wav_Data,dtype=np.int16)
    Wav_Data = Wav_Data*1.0/(max(abs(Wav_Data)))        #對資料進行歸一化
    # 生成音訊資料,ndarray不能進行json化,必須轉化為list,生成JSON
    dict = {"channel":numchannel,
            "samplewidth":samplewidth,
            "framerate":framerate,
            "numframes":numframes,
            "WaveData":list(Wav_Data)}
    return json.dumps(dict)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

繪製聲波折線圖與頻譜圖

程式碼如下:

from matplotlib import pyplot as plt

def DrawSpectrum(wav_data,framerate):
    """
    這是畫音訊的頻譜函式
    :param wav_data: 音訊資料
    :param framerate: 取樣頻率
    """
    Time = np.linspace(0,len(wav_data)/framerate*1.0,num=len(wav_data))
    plt.figure(1)
    plt.plot(Time,wav_data)
    plt.grid(True)
    plt.show()
    plt.figure(2)
    Pxx, freqs, bins, im = plt.specgram(wav_data,NFFT=1024,Fs = 16000,noverlap=900)
    plt.show()
    print(Pxx)
    print(freqs)
    print(bins)
    print(im)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

首先利用百度AI開發平臺的語音合API生成的MP3檔案進行上述過程的結果。
聲波折線圖

頻譜圖


全部程式碼

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time    : 2018/7/5 13:11
# @Author  : DaiPuwei
# @FileName: VoiceExtract.py
# @Software: PyCharm
# @E-mail  :[email protected]
# @Blog    :https://blog.csdn.net/qq_30091945

import numpy as np
from pydub import AudioSegment
import pydub
import os
import wave
import json
from matplotlib import pyplot as plt

def MP32WAV(mp3_path,wav_path):
    """
    這是MP3檔案轉化成WAV檔案的函式
    :param mp3_path: MP3檔案的地址
    :param wav_path: WAV檔案的地址
    """
    pydub.AudioSegment.converter = "D:\\ffmpeg\\bin\\ffmpeg.exe"            #說明ffmpeg的地址
    MP3_File = AudioSegment.from_mp3(file=mp3_path)
    MP3_File.export(wav_path,format="wav")

def Read_WAV(wav_path):
    """
    這是讀取wav檔案的函式,音訊資料是單通道的。返回json
    :param wav_path: WAV檔案的地址
    """
    wav_file = wave.open(wav_path,'r')
    numchannel = wav_file.getnchannels()          # 聲道數
    samplewidth = wav_file.getsampwidth()      # 量化位數
    framerate = wav_file.getframerate()        # 取樣頻率
    numframes = wav_file.getnframes()           # 取樣點數
    print("channel", numchannel)
    print("sample_width", samplewidth)
    print("framerate", framerate)
    print("numframes", numframes)
    Wav_Data = wav_file.readframes(numframes)
    Wav_Data = np.fromstring(Wav_Data,dtype=np.int16)
    Wav_Data = Wav_Data*1.0/(max(abs(Wav_Data)))        #對資料進行歸一化
    # 生成音訊資料,ndarray不能進行json化,必須轉化為list,生成JSON
    dict = {"channel":numchannel,
            "samplewidth":samplewidth,
            "framerate":framerate,
            "numframes":numframes,
            "WaveData":list(Wav_Data)}
    return json.dumps(dict)

def DrawSpectrum(wav_data,framerate):
    """
    這是畫音訊的頻譜函式
    :param wav_data: 音訊資料
    :param framerate: 取樣頻率
    """
    Time = np.linspace(0,len(wav_data)/framerate*1.0,num=len(wav_data))
    plt.figure(1)
    plt.plot(Time,wav_data)
    plt.grid(True)
    plt.show()
    plt.figure(2)
    Pxx, freqs, bins, im = plt.specgram(wav_data,NFFT=1024,Fs = 16000,noverlap=900)
    plt.show()
    print(Pxx)
    print(freqs)
    print(bins)
    print(im)

def run_main():
    """
        這是主函式
    """
    # MP3檔案和WAV檔案的地址
    path1 = './MP3_File'
    path2 = "./WAV_File"
    paths = os.listdir(path1)
    mp3_paths = []
    # 獲取mp3檔案的相對地址
    for mp3_path in paths:
        mp3_paths.append(path1+"/"+mp3_path)
    print(mp3_paths)

    # 得到MP3檔案對應的WAV檔案的相對地址
    wav_paths = []
    for mp3_path in mp3_paths:
       wav_path = path2+"/"+mp3_path[1:].split('.')[0].split('/')[-1]+'.wav'
       wav_paths.append(wav_path)
    print(wav_paths)

    # 將MP3檔案轉化成WAV檔案
    for(mp3_path,wav_path) in zip(mp3_paths,wav_paths):
        MP32WAV(mp3_path,wav_path)
    for wav_path in wav_paths:
        Read_WAV(wav_path)

    # 開始對音訊檔案進行資料化
    for wav_path in wav_paths:
        wav_json = Read_WAV(wav_path)
        print(wav_json)
        wav = json.loads(wav_json)
        wav_data = np.array(wav['WaveData'])
        framerate = int(wav['framerate'])
        DrawSpectrum(wav_data,framerate)

if __name__ == '__main__':
    run_main()