筆者最近在挑選開(kāi)源的語(yǔ)音識(shí)別模型,首要測(cè)試的是百度的paddlepaddle;
測(cè)試之前,肯定需要了解一下音頻解析的一些基本技術(shù)點(diǎn),于是有此篇先導(dǎo)文章。
筆者看到的音頻解析主要有幾個(gè):
- soundfile
- ffmpy
- librosa
1 librosa
安裝代碼:
!pip install librosa -i https://mirror.baidu.com/pypi/simple
!pip install soundfile -i https://mirror.baidu.com/pypi/simple
參考文檔:librosa
1.1 音頻讀入
文檔位置:https://librosa.org/doc/latest/core.html#audio-loading
signal, sr = librosa.load(path, sr=None)
其中l(wèi)oad的參數(shù)包括:
librosa.load(path, *, sr=22050, mono=True, offset=0.0, duration=None, dtype=<class 'numpy.float32'>, res_type='kaiser_best')
其中sr = None,‘None’ 保留原始采樣頻率,設(shè)置其他采樣頻率會(huì)進(jìn)行重采樣,有點(diǎn)耗時(shí)
可以讀 .wav 和 .mp3;
1.2 音頻寫(xiě)出
在網(wǎng)絡(luò)上其他幾篇:python音頻采樣率轉(zhuǎn)換 和 python 音頻文件采樣率轉(zhuǎn)換在導(dǎo)出音頻文件時(shí)候,會(huì)出現(xiàn)錯(cuò)誤,貼一下他們的代碼
代碼片段一:
def resample_rate(path,new_sample_rate = 16000):
signal, sr = librosa.load(path, sr=None)
wavfile = path.split('/')[-1]
wavfile = wavfile.split('.')[0]
file_name = wavfile + '_new.wav'
new_signal = librosa.resample(signal, sr, new_sample_rate) #
librosa.output.write_wav(file_name, new_signal , new_sample_rate)
代碼片段二:
import librosa
import os
noise_name="/media/dfy/fc0b6513-c379-4548-b391-876575f1493f/home/dfy/PycharmProjects/noise_data/"
noise_name_list=os.listdir(noise_name)
for one_name in noise_name_list:
data=librosa.load(noise_name+one_name,16000)
librosa.output.write_wav(noise_name+one_name,data[0],16000,norm=False)
if __name__ == '__main__':
pass
上述都是使用 librosa.output
進(jìn)行導(dǎo)出,最新的librosa已經(jīng)摒棄了這個(gè)函數(shù)。出現(xiàn)報(bào)錯(cuò):
AttributeError: module librosa has no attribute output No module named numba.decorators錯(cuò)誤解決
0.8.0版本的將output的api屏蔽掉了,所以要么就是librosa降低版本,比如到0.7.2,要么使用另外的方式。
于是來(lái)到官方文檔:librosa
推薦使用write的方式,是使用這個(gè)庫(kù):PySoundFile
1.3 librosa 讀入 + PySoundFile寫(xiě)出
如果出現(xiàn)報(bào)錯(cuò):
Input audio file has sample rate [44100], but decoder expects [16000]
就是音頻采樣比不對(duì),需要修改一下。
筆者將1+2的開(kāi)源庫(kù)結(jié)合,微調(diào)了python音頻采樣率轉(zhuǎn)換 和 python 音頻文件采樣率轉(zhuǎn)換,得到以下,切換音頻采樣頻率的函數(shù):
import librosa
import os
import numpy as np
import soundfile as sf
def resample_rate(path,new_sample_rate = 16000):
signal, sr = librosa.load(path, sr=None)
wavfile = path.split('/')[-1]
wavfile = wavfile.split('.')[0]
file_name = wavfile + '_new.wav'
new_signal = librosa.resample(signal, sr, new_sample_rate) #
#librosa.output.write_wav(file_name, new_signal , new_sample_rate)
sf.write(file_name, new_signal, new_sample_rate, subtype='PCM_24')
print(f'{file_name} has download.')
# wav_file = 'video/xxx.wav'
resample_rate(wav_file,new_sample_rate = 16000)
改變?yōu)閟ample_rate 為16000
的音頻文件
1.4 從其他庫(kù)轉(zhuǎn)為librosa格式
參考:https://librosa.org/doc/latest/generated/librosa.load.html#librosa.load
第一種:
# Load using an already open SoundFile object
import soundfile
sfo = soundfile.SoundFile(librosa.ex('brahms'))
y, sr = librosa.load(sfo)
第二種:
# Load using an already open audioread object
import audioread.ffdec # Use ffmpeg decoder
aro = audioread.ffdec.FFmpegAudioFile(librosa.ex('brahms'))
y, sr = librosa.load(aro)
2 PySoundFile
python-soundfile是一個(gè)基于libsndfile、CFFI和NumPy的音頻庫(kù)。
可以直接使用函數(shù)read()和write()來(lái)讀寫(xiě)聲音文件。要按塊方式讀取聲音文件,請(qǐng)使用blocks()。另外,聲音文件也可以作為SoundFile對(duì)象打開(kāi)。
PySoundFile的官方文檔:readthedocs
下載:
!pip install soundfile -i https://mirror.baidu.com/pypi/simple
2.1 讀入音頻
read files from zip compressed archives:
import zipfile as zf
import soundfile as sf
import io
with zf.ZipFile('test.zip') as myzip:
with myzip.open('stereo_file.wav') as myfile:
tmp = io.BytesIO(myfile.read())
data, samplerate = sf.read(tmp)
Download and read from URL:
import soundfile as sf
import io
from six.moves.urllib.request import urlopen
url = "https://raw.githubusercontent.com/librosa/librosa/master/tests/data/test1_44100.wav"
data, samplerate = sf.read(io.BytesIO(urlopen(url).read()))
2.2 導(dǎo)出音頻
導(dǎo)出音頻的:
import numpy as np
import soundfile as sf
rate = 44100
data = np.random.uniform(-1, 1, size=(rate * 10, 2))
# Write out audio as 24bit PCM WAV
sf.write('stereo_file.wav', data, samplerate, subtype='PCM_24')
# Write out audio as 24bit Flac
sf.write('stereo_file.flac', data, samplerate, format='flac', subtype='PCM_24')
# Write out audio as 16bit OGG
sf.write('stereo_file.ogg', data, samplerate, format='ogg', subtype='vorbis')
3 ffmpy
Python 批量轉(zhuǎn)換視頻音頻采樣率(附代碼) | Python工具
下載:
pip install ffmpy -i https://pypi.douban.com/simple
具體代碼見(jiàn)原文,只截取其中一段:
def transfor(video_path: str, tmp_dir: str, result_dir: str):
file_name = os.path.basename(video_path)
base_name = file_name.split('.')[0]
file_ext = file_name.split('.')[-1]
ext = 'wav'
audio_path = os.path.join(tmp_dir, '{}.{}'.format(base_name, ext))
print('文件名:{},提取音頻'.format(audio_path))
ff = FFmpeg(
inputs={
video_path: None}, outputs={
audio_path: '-f {} -vn -ac 1 -ar 16000 -y'.format('wav')})
print(ff.cmd)
ff.run()
if os.path.exists(audio_path) is False:
return None
video_tmp_path = os.path.join(
tmp_dir, '{}_1.{}'.format(
base_name, file_ext))
ff_video = FFmpeg(inputs={video_path: None},
outputs={video_tmp_path: '-an'})
print(ff_video.cmd)
ff_video.run()
result_video_path = os.path.join(result_dir, file_name)
ff_fuse = FFmpeg(inputs={video_tmp_path: None, audio_path: None}, outputs={
result_video_path: '-map 0:v -map 1:a -c:v copy -c:a aac -shortest'})
print(ff_fuse.cmd)
ff_fuse.run()
return result_video_path
4 AudioSegment / pydub
參考文章:
Python | 語(yǔ)音處理 | 用 librosa / AudioSegment / soundfile 讀取音頻文件的對(duì)比
另外一篇對(duì)pydub的參數(shù)介紹:
pydub簡(jiǎn)單介紹
官網(wǎng)地址:pydub
from pydub import AudioSegment #需要導(dǎo)入pydub三方庫(kù),第一次使用需要安裝
audio_path = './data/example.mp3'
t = time.time()
song = AudioSegment.from_file(audio_path, format='mp3')
# print(len(song)) #時(shí)長(zhǎng),單位:毫秒
# print(song.frame_rate) #采樣頻率,單位:赫茲
# print(song.sample_width) #量化位數(shù),單位:字節(jié)
# print(song.channels) #聲道數(shù),常見(jiàn)的MP3多是雙聲道的,聲道越多文件也會(huì)越大。
wav = np.array(song.get_array_of_samples())
sr = song.frame_rate
print(f"sr={sr}, len={len(wav)}, 耗時(shí): {time.time()-t}")
print(f"(min, max, mean) = ({wav.min()}, {wav.max()}, {wav.mean()})")
wav
輸出結(jié)果為:
sr=16000, len=64320, 耗時(shí): 0.04667925834655762
(min, max, mean) = (-872, 740, -0.6079446517412935)
array([ 1, -1, -2, ..., -1, 1, -2], dtype=int16)
5 paddleaudio
安裝:
! pip install paddleaudio -i https://mirror.baidu.com/pypi/simple
paddle官方封裝的一個(gè),音頻基本操作應(yīng)該是librosa的庫(kù)
具體參考:
https://paddleaudio-doc.readthedocs.io/en/latest/index.html
import paddleaudio
audio_file = 'XXX.wav'
paddleaudio.load(audio_file, sr=None, mono=True, normal=False)
得出:
(array([-3.9100647e-04, -3.0159950e-05, 1.1110306e-04, ...,
1.4603138e-04, 2.5625229e-03, -7.6780319e-03], dtype=float32),
16000)
音頻數(shù)值 + 采樣率
6 音頻切分 - auditok
參考的是:【超簡(jiǎn)單】之基于PaddleSpeech搭建個(gè)人語(yǔ)音聽(tīng)寫(xiě)服務(wù)
!pip install auditok
切分原因上面交代過(guò),因?yàn)镻addleSpeech識(shí)別最長(zhǎng)語(yǔ)音為50s,故需要切分,這里直接調(diào)用好了。
from paddlespeech.cli.asr.infer import ASRExecutor
import csv
import moviepy.editor as mp
import auditok
import os
import paddle
from paddlespeech.cli import ASRExecutor, TextExecutor
import soundfile
import librosa
import warnings
warnings.filterwarnings('ignore')
# 引入auditok庫(kù)
import auditok
# 輸入類別為audio
def qiefen(path, ty='audio', mmin_dur=1, mmax_dur=100000, mmax_silence=1, menergy_threshold=55):
audio_file = path
audio, audio_sample_rate = soundfile.read(
audio_file, dtype="int16", always_2d=True)
audio_regions = auditok.split(
audio_file,
min_dur=mmin_dur, # minimum duration of a valid audio event in seconds
max_dur=mmax_dur, # maximum duration of an event
# maximum duration of tolerated continuous silence within an event
max_silence=mmax_silence,
energy_threshold=menergy_threshold # threshold of detection
)
for i, r in enumerate(audio_regions):
# Regions returned by `split` have 'start' and 'end' metadata fields
print(
"Region {i}: {r.meta.start:.3f}s -- {r.meta.end:.3f}s".format(i=i, r=r))
epath = ''
file_pre = str(epath.join(audio_file.split('.')[0].split('/')[-1]))
mk = 'change'
if (os.path.exists(mk) == False):
os.mkdir(mk)
if (os.path.exists(mk + '/' + ty) == False):
os.mkdir(mk + '/' + ty)
if (os.path.exists(mk + '/' + ty + '/' + file_pre) == False):
os.mkdir(mk + '/' + ty + '/' + file_pre)
num = i
# 為了取前三位數(shù)字排序
s = '000000' + str(num)
file_save = mk + '/' + ty + '/' + file_pre + '/' + \
s[-3:] + '-' + '{meta.start:.3f}-{meta.end:.3f}' + '.wav'
filename = r.save(file_save)
print("region saved as: {}".format(filename))
return mk + '/' + ty + '/' + file_pre
其中核心的 auditok.split
代碼,參數(shù)詳解在auditok.core.split ,其輸入的是音頻文件名,不能是音頻的data格式。
7 一個(gè)比較難解決的報(bào)錯(cuò)
AudioParameterError: Sample width must be one of: 1, 2 or 4 (bytes)
筆者在跑語(yǔ)音模型的識(shí)別遇到了以上的報(bào)錯(cuò),
但是網(wǎng)上找了一圈,沒(méi)找到對(duì)的解決方案。
在快要放棄的時(shí)候,無(wú)意間看到AudioSegment
庫(kù)的神奇功能。
Sample width
是什么?
取樣量化位寬(sampwidth)
import wave
file ='asr_example.wav'
with wave.open(file) as fp:
channels = fp.getnchannels()
srate = fp.getframerate()
swidth = fp.getsampwidth()
data = fp.readframes(-1)
swidth,srate
通過(guò)wave
可以查詢到一個(gè)音頻的比較重要的幾個(gè)參數(shù)。
分別為:
- nchannels:聲道數(shù)
- sampwidth:返回該實(shí)例每一幀的字節(jié)寬度。
- framerate:采樣頻率
- nframes:采樣點(diǎn)數(shù)
那遇到上述報(bào)錯(cuò)就需要重新調(diào)整,這里AudioSegment
庫(kù)直接有
from pydub import AudioSegment
file_in ='asr_example.wav' # 輸入的音頻名稱
file_out = 'asr_example_3.wav' # 輸出的音頻名稱
sound = AudioSegment.from_file(file_in)
sound = sound.set_frame_rate(48000) # 可以修改音頻采樣率
sound = sound.set_sample_width(4) # 重新設(shè)置字節(jié)寬度
sound.export(file_out, format="wav")
以上就可以完美解決。
8 從網(wǎng)址URL下載音頻
幾種讀入方式:
8.1 soundfile
import soundfile as sf
def save_audio_func(video_url,save_samplerate = 16000):
'''
音頻導(dǎo)出
'''
save_name = video_url.split('/')[-1]
data, samplerate = sf.read(io.BytesIO(urlopen(video_url).read()))
# Write out audio as 24bit PCM WAV
sf.write(save_name, data, save_samplerate, subtype='PCM_24')
#print('')
return save_name
讀入、讀出都是通過(guò)soundfile
9 如何讀取mp3
參考:https://blog.csdn.net/qq_37851620/article/details/127149729
soundfile.read:
只能讀 .wav ,不能讀 .mp3;
默認(rèn) dtype = ‘float64’,輸出為 (-1, 1) 之間的數(shù)據(jù) (做了 32768 歸一化);修改為 dtype = ‘int16’,輸出為 (-215, 215-1) 之間;
保留原始采樣頻率。
librosa.load:
可以讀 .wav 和 .mp3;
輸出為 (-1, 1);
sr=None 保留原始采樣頻率,設(shè)置其他采樣頻率會(huì)進(jìn)行重采樣,有點(diǎn)耗時(shí);文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-787066.html
pydub.AudioSegment.from_file:
可以讀 .wav 和 .mp3;
輸出為 (-215, 215-1),手動(dòng)除以32768(=2**15),可得到同2一樣的結(jié)果;
保留原始采樣頻率,重采樣可借助 librosa.resample。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-787066.html
到了這里,關(guān)于語(yǔ)音識(shí)別系列︱用python進(jìn)行音頻解析(一)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!