语音识别入门——常用软件及python运用

工具以及使用到的库

  • ffmpeg
  • sox
  • audacity
  • pydub
  • scipy
  • librosa
  • pyAudioAnalysis
  • plotly

本文分为两个部分:

P1如何使用ffmpeg和sox处理音频文件
P2如何编程处理音频文件并执行基本处理


P1 处理语音数据——命令行方式


格式转换

ffmpeg -i video.mkv audio.mp3

使用ffmpeg将输入mkv文件转为mp3文件


降采样、通道转换

ffmpeg -i audio.wav -ar 16000 -ac 1 audio_16K_mono.wav
  • ar:声频采样率(audio rate)
  • ac:声频通道(audio channel)
    此处是将原来44.1kHz的双通道wav文件转为单通道wav文件

获取音频信息

ffmpeg -i audio_16K_mono.wav

将得到

Input #0, wav, from ‘audio_16K_mono.wav’:
Metadata:
encoder : Lavf57.71.100
Duration: 00:03:10.29, bitrate: 256 kb/s
Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 16000 Hz,
mono, s16, 256 kb/s
  • #0表示只有一个通道
  • encoder:为libavformat支持的一种容器
  • Duration:时长
  • bitrate:比特率256kb/s,表示音频每秒传输的数据量,高质量音频一般比较大
  • Stram:流
  • #0:0:单通道
  • pcm_s16le:
    • pcm(脉冲编码调制,pulse-code modulation)
    • signed integer 16:(16位有符号整型)格式采样
    • le表示小端(little endian),高位数据存地址高位,地位数据存地址地位,有如[1][0][0][0] / 0x0001。
  • mono:单通道

小插曲

最近看到一道数据类型题
题目:为什么float类型 ( 1 e 10 + 3.14 ) − 1 e 10 = 0 ? \mathbf{(1e10+3.14)-1e10=0?} (1e10+3.14)1e10=0?
解题如下:
1 e 10 \mathbf{1e10} 1e10二进制表示为:
001 0 ′ 010 1 ′ 010 0 ′ 000 0 ′ 101 1 ′ 111 0 ′ 010 0 ′ 000 0 ′ 0000 \mathbf{0010'0101'0100'0000'1011'1110'0100'0000'0000} 001001010100000010111110010000000000
或者表示为
1.001 0 ′ 101 0 ′ 000 0 ′ 010 1 ′ 111 1 ′ 001 0 ′ 000 0 ′ 000 0 ′ 0 2 ∗ 2 33 \mathbf{1.0010'1010'0000'0101'1111'0010'0000'0000'0_2*2^{33}} 1.0010101000000101111100100000000002233

浮点数三要素

  • 首位:0表示正数,1表示负数
  • 中间位,8位,为科学计数法指数部分,上例为33与偏置量(127)的和,此例为160,二进制为1010’0000
  • 尾部:23位,二进制表示的小数部分的前23位,此例为0010’1010’0000’0101’1111’001
    1 e 10 \mathbf{1e10} 1e10的浮点数为:
    0 ′ 101 0 ′ 000 0 ′ 001 0 ′ 101 0 ′ 000 0 ′ 010 1 ′ 111 1 ′ 001 \mathbf{0'1010'0000'0010'1010'0000'0101'1111'001} 01010000000101010000001011111001
    到此为止,可知舍去了科学计数法中小数部分的后10位

小数的二进制表示两个要素

  • 整数部分:正常表示,3.14整数部分为0011
  • 小数部分:乘以2取整数部分,
    • 0.14*2=0.28 取0
    • 0.28*2=0.56 取0
    • 0.56*2=1.12 取1
    • 0.12*2=0.24 取0
    • 0.24*2=0.48 取0
    • 0.48*2=0.96 取0
    • 0.96*2=1.92 取1

3.14的二进制表示为:
11.0010001... \mathbf{11.0010001...} 11.0010001...
综上, 1 e 10 + 3.14 \mathbf{1e10+3.14} 1e10+3.14的二进制表示为:
1.001 0 ′ 101 0 ′ 000 0 ′ 010 1 ′ 111 1 ′ 001 0 ′ 000 0 ′ 000 1 ′ 1001 ’ 000 1 2 ∗ 2 33 \mathbf{1.0010'1010'0000'0101'1111'0010'0000'0001'1001’0001_2*2^{33}} 1.001010100000010111110010000000011001’00012233
转为浮点数,为
0 ′ 101 0 ′ 000 0 ′ 001 0 ′ 101 0 ′ 000 0 ′ 010 1 ′ 111 1 ′ 001 \mathbf{0'1010'0000'0010'1010'0000'0101'1111'001} 01010000000101010000001011111001
1 e 10 \mathbf{1e10} 1e10一样,故float类型 ( 1 e 10 + 3.14 ) − 3.14 = 0 \mathbf{(1e10+3.14)-3.14}=0 (1e10+3.14)3.14=0


修剪音频

ffmpeg -i audio.wav -ss 60 -t 20 audio_small.wav
  • i:输入音频audio.wav
  • ss: 截取起始秒
  • t:截取段时长
  • audio_small.wav:输出文件

串联视频

新建一个list_of_files_to_concat的txt文档,内容如下:

file 'file1.wav'
file 'file2.wav'
file 'file3.wav'

采用以下命令行,可将三个文件串联输出,编码方式为复制

ffmpeg -f concat -i list_of_files_to_concat -c copy output.wav

分割视频

以下命令行将输入视频分割为1s一个

ffmpeg -i output.wav -f segment -segment_time 1 -c copy out%05d.wav

交换声道

ffmpeg -i stereo.wav -map_channel 0.0.1 -map_channel 0.0.0 stereo_inverted.wav
  • 0.0.1输入文件音频流右声道
  • 0.0.0输入文件音频流左声道

合并声道

ffmpeg -i left.wav -i right.wav -filter_complex "[0:a][1:a]join=inputs=2:channel_layout=stereo[a]" -map "[a]" mix_channels.wav
  • filter_complex:复杂音频滤波器图
  • [0:a],[1:a]:第一个和第二个文件的音频流
  • join=inputs=2:表示两个输入流混合
  • channel_layout=stereo:混合后输出为立体声
  • [a]:输出音频流标签
  • map ”[a]":将‘[a]'标签的音频流映射到输出文件

分割立体声音频为左右单声道文件

ffmpeg -i stereo.wav -map_channel 0.0.0 left.wav -map_channel 0.0.1 right.wav
  • map_channel 0.0.0:将左声道映射到第一个输出文件
  • map_channel 0.0.1:将右声道映射到第二个输出文件

将某个声道静音

ffmpeg -i stereo.wav -map_channel -1 -map_channel 0.0.1 muted.wav
  • map_channel -1:忽略某声道
  • map_channel 0.0.1:将右声道映射到输出文件

音量调节

ffmpeg -i data/music_44100.wav -filter:a “volume=0.5” data/music_44100_volume_50.wav
ffmpeg -i data/music_44100.wav -filter:a “volume=2.0” data/music_44100_volume_200.wav
  • filter:a:使用音频过滤器
  • “volume=0.5”:将音频音量变为原来一半
  • “volume=2”:将音频音量变为原来两倍
    声量调节
图1 原声,半声,倍声(自上而下)
由图1可知,二倍声出现削波(失真)现象。

sox音量调节

sox -v 0.5 data/music_44100.wav data/music_44100_volume_50_sox.wav
sox -v 2.0 data/music_44100.wav data/music_44100_volume_200_sox.wav

sox -v n \text{sox -v n} sox -v n 输入文件路径 输出文件路径

  • v n:音量调节系数,n可理解为倍数。

P2 处理语音数据——编程方式


  • wav: scipy.io.wavfile
  • mp3:pydub

以数组形式加载音频文件

# 以数组形式读取wav和mp3
from pydub import AudioSegment
import numpy as np
from scipy.io import wavfile# 用 scipy.io.wavfile 读取wav文件
fs_wav, data_wav = wavfile.read("resampled.wav")# 用 pydub 读取mp3
audiofile = AudioSegment.from_file("resampled.mp3")
data_mp3 = np.array(audiofile.get_array_of_samples())
fs_mp3 = audiofile.frame_rateprint('Sq Error Between mp3 and wav data = {}'.format(((data_mp3 - data_wav)**2).sum()/len(data_wav)))
print('Signal Duration = {} seconds'.format(data_wav.shape[0] / fs_wav))
# 输出,我使用ffmpeg将wav转成MP3,比特率将为24kb
Sq Error Between mp3 and wav data = 3775.2859044790266
Signal Duration = 34.5513125 seconds

显示左右声道

import numpy as np
from scipy.io import wavfile
import matplotlib.pyplot as plt
fs,data=wavfile.read('resampled_double.wav')
time=np.arange(0,len(data))/fs
fig,axs=plt.subplots(2,1,figsize=(10,6),sharex=True)
axs[0].plot(time,data[:,0],label='Left Channel',color='blue')
axs[0].set_ylabel('Amplitude')
axs[0].legend()
axs[1].plot(time,data[:,1],label='Right Channel',color='orange')
axs[1].set_ylabel('Amplitute')
axs[1].set_xlabel('Time(seconds)')
axs[1].legend()
plt.suptitle("Stereo Audio Waveform")
plt.show()

左右声道

图2 左右声道展示

正则化

import matplotlib.pyplot as plt
from scipy.io import wavfile
import numpy as np
fs,data = wavfile.read("resampled_double.wav")
time=np.arange(0,len(data))/fs
plt.figure(figsize=(10,4))
plt.plot(time,data[:,0]/2^15)
plt.xlabel('Time(seconds)')
plt.ylabel('Amplitude')
plt.title('Stereo Audio Waveform')

量化后的波形图

图3 数据量化后的波形图

修剪音频

# 显示2到4秒的波形
import numpy as np
import matplotlib.pyplot as plt
from scipy.io import wavfile
fs,data=wavfile.read('resampled_double.wav')
time=np.arange(0,len(data[2*fs:4*fs]))/fs
plt.figure(figsize=(10,4))
plt.plot(time,data[2*fs:4*fs])
plt.xlabel('Time/s')
plt.ylabel('Amplitude')
plt.title('Stereo Audio Waveform')
plt.show()

剪辑音频

图4 剪辑后音频波形

分割为固定大小

import numpy as np
from scipy.io import wavfile
import IPython
fs,signal=wavfile.read("resampled.wav")
segment_size_t=1
segment_size=segment_size_t*fs
segments=[signal[x:x+segment_size]for x in range(0,len(signal),segment_size)]
for i,s in enumerate(segments):if len(s)<segment_size:s=np.pad(s,(0,(segment_size-len(s))),'constant')		# 这里是为了每个clip都为1swavfile.write(f"resampled_segment_{i}_{i+1}.wav",fs,s)
IPython.display.display(IPython.display.Audio("resampled_segment_34_35.wav"))
# 输出,成功输出35个1s的wav文件

简单算法——删去无声片段

import IPython
import matplotlib.pyplot as plt
import numpy as np
energies=[((s/2**15)**2).sum()/len(s) for s in segments]	# 防止溢出
thres=np.percentile(energies,20)
indices_of_segments_to_keep=(np.where(energies>thres)[0])
segments2=np.array(segments)[indices_of_segments_to_keep]
new_signal=np.concatenate(segments2)
wavfile.write("processed_new.wav",fs,new_signal.astype(np.int16))	# 转成int
plt.figure(figsize=(10,6))
plt.plot(energies,label="Energies",color="red")
plt.plot(np.ones(len(energies))*thres,label="Thresholds",color="blue")
plt.title("Energies VS Thresholds")
plt.legend()
plt.show()
IPython.display.display(IPython.display.Audio("processed_new.wav"))
IPython.display.display(IPython.display.Audio("resampled.wav"))

过滤静音片段
音频的时长

图5 根据能量无声片段的删除及删除后的时长

往单声道音频中加入节拍

import numpy as np
import scipy.io.wavfile as wavfile
import librosa
import IPython
import matplotlib.pyplot as plt# 加载文件并提取节奏和节拍:
[Fs, s] = wavfile.read('resampled.wav')
tempo, beats = librosa.beat.beat_track(y=s.astype('float'), sr=Fs, units="time")
beats -= 0.05# 在每个节拍的第二个声道上添加小的220Hz声音
s = s.reshape(-1, 1)
s = np.array(np.concatenate((s, np.zeros(s.shape)), axis=1))
for ib, b in enumerate(beats):t = np.arange(0, 0.2, 1.0 / Fs)amp_mod = 0.2 / (np.sqrt(t)+0.2) - 0.2amp_mod[amp_mod < 0] = 0x = s.max() * np.cos(2 * np.pi * t * 220) * amp_mods[int(Fs * b): int(Fs * b) + int(x.shape[0]), 1] = x.astype('int16')# 写入一个wav文件,其中第二个声道具有估计的节奏:
wavfile.write("tempo.wav", Fs, np.int16(s))# 在笔记本中播放生成的文件:
IPython.display.display(IPython.display.Audio("tempo.wav"))# 绘制波形图
time = np.arange(0, len(s)) / Fs
fig, axs = plt.subplots(2, 1, figsize=(10, 6), sharex=True)
axs[0].plot(time, s[:, 0], label='左声道', color='orange')
axs[0].set_ylabel('振幅')
axs[0].legend()
axs[1].plot(time, s[:, 1], label='右声道', color='blue')
axs[1].set_xlabel("时间/秒")
axs[1].set_ylabel("振幅")
axs[1].legend()
plt.show()

tempo&beats音频

图6 添加tempo的左右声道及音频

实时录制以及频率分析

# paura_lite:
# 一个超简单的命令行音频录制器,具有实时频谱可视化import numpy as np
import pyaudio
import struct
import scipy.fftpack as scp
import termplotlib as tpl
import os# 获取窗口尺寸
rows, columns = os.popen('stty size', 'r').read().split()buff_size = 0.2          # 窗口大小(秒)
wanted_num_of_bins = 40  # 要显示的频率分量数量# 初始化声卡进行录制:
fs = 8000
pa = pyaudio.PyAudio()
stream = pa.open(format=pyaudio.paInt16, channels=1, rate=fs,input=True, frames_per_buffer=int(fs * buff_size))while 1:  # 对于每个录制的窗口(直到按下Ctrl+C)# 获取当前块并将其转换为short整数列表,block = stream.read(int(fs * buff_size))format = "%dh" % (len(block) / 2)shorts = struct.unpack(format, block)# 然后进行归一化并转换为numpy数组:x = np.double(list(shorts)) / (2**15)seg_len = len(x)# 获取当前窗口的总能量并计算归一化因子# 用于可视化最大频谱图值energy = np.mean(x ** 2)max_energy = 0.02  # 条形设置为最大的能量max_width_from_energy = int((energy / max_energy) * int(columns)) + 1if max_width_from_energy > int(columns) - 10:max_width_from_energy = int(columns) - 10# 获取FFT的幅度和相应的频率X = np.abs(scp.fft(x))[0:int(seg_len/2)]freqs = (np.arange(0, 1 + 1.0/len(X), 1.0 / len(X)) * fs / 2)# ... 并重新采样为固定数量的频率分量(用于可视化)wanted_step = (int(freqs.shape[0] / wanted_num_of_bins))freqs2 = freqs[0::wanted_step].astype('int')X2 = np.mean(X.reshape(-1, wanted_step), axis=1)# 将(频率,FFT)作为水平直方图绘制:fig = tpl.figure()fig.barh(X2, labels=[str(int(f)) + " Hz" for f in freqs2[0:-1]],show_vals=False, max_width=max_width_from_energy)fig.show()# 添加足够多的新行以清除屏幕在下一次迭代中:print("\n" * (int(rows) - freqs2.shape[0] - 1))

频谱

图7 实时录制并获取频谱直方图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/161381.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

shell 脚本循环语句

目录 循环 echo 命令 for 循环次数 for 第二种格式 命令举例 while 脚本举例 双重循环及跳出循环 脚本举例 更改文件和目录的后缀名的脚本 画三角形的脚本 乘法口诀表的脚本 面试例题 补充命令 let 命令 循环 —— 一定要有跳出循环的条件 已知循环的次数 未知…

英语六级范文模板

目录 现象解释 观点选择 问题解决 六级只考议论文&#xff0c;我们将从现象解释&#xff0c;观点选择&#xff0c;问题解决三个角度给出范文&#xff1a; 多次使用的句子&#xff0c;就可以作为模板记下来~~ 现象解释 In the contemporary world, the ability to meet cha…

SQLite3

数据库简介 常用的数据库 大型数据库&#xff1a;Oracle 中型数据库&#xff1a;Server 是微软开发的数据库产品&#xff0c;主要支持 windows 平台。 小型数据库&#xff1a;mySQL 是一个小型关系型数据库管理系统&#xff0c;开放源码 。(嵌入式不需要存储太多数据。) SQL…

Seaborn画图颜色和给定的RGB hex code不一致

使用以下代码画图&#xff1a; import seaborn as sns import matplotlib.pyplot as plt plt.figure(dpi150) x [A,B,C,D] y [164, 86, 126, 53] sns.barplot(xx, yy, color#3a923a) 得到的颜色如下图所示&#xff1a; 这是因为seaborn默认降低了颜色的饱和度&#xff0c;即…

UDP中connect的作用

udpclientNoConnect.c里边的内容如下&#xff1a; #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<arpa/inet.h> #include<sys/socket.h> #include <errno.h> #include <syslog.h…

基于 Flink CDC 打造企业级实时数据集成方案

本文整理自Flink数据通道的Flink负责人、Flink CDC开源社区的负责人、Apache Flink社区的PMC成员徐榜江在云栖大会开源大数据专场的分享。本篇内容主要分为四部分&#xff1a; CDC 数据实时集成的挑战Flink CDC 核心技术解读基于 Flink CDC 的企业级实时数据集成方案实时数据集…

独立版求职招聘平台小程序开发

小程序招聘系统开发 我们开发了一款高效、便捷的互联网招聘平台。在这里&#xff0c;可以轻松实现企业入驻、职位发布、在线求职、精准匹配职位和人才&#xff0c;以及参与招聘会等功能。目标是为求职者和企业搭建一个连接彼此的桥梁&#xff0c;帮助您更快地找到满意的工作&…

SpringMVC(五)SpringMVC的视图

SpringMVC中的视图是View接口&#xff0c;视图的作用渲染数据&#xff0c;将模型Model中的数据展示给用户 SpringMVC视图的种类很多&#xff0c;默认有转发视图(InternalResourceView)和重定向视图(RedirectView) 当工程引入jstl的依赖&#xff0c;转发视图会自动转换为JstlV…

深度学习 loss 是nan的可能原因

1 loss 损失值非常大&#xff0c;超过了浮点数的范围&#xff0c;所以表示为overflow 状态下的男。 解决办法&#xff1a; 减小学习率&#xff0c;观察loss值是不是还是nan 在将数据输入模型前&#xff0c;进行恰当的归一化 缩放 2 loss 的计算中存在除以0&#xff0c; log(0…

Java架构师软件架构开发

目录 1 基于架构的软件开发导论2 ABSD架构方法论3 ABSD方法论具体实现4 ABSD金融业案例5 基于特定领域的软件架构开发导论6 DSSA领域分析7 DSSA领域设计和实现8 DSSA国际电商平台架构案例9 架构思维方法论概述10 AT方法论和案例想学习架构师构建流程请跳转:Java架构师系统架构…

Unity UI设计 软件构造实验报告

实验1: 仿真系统的UI主界面设计 1.实验目的 &#xff08;1&#xff09;熟悉Unity中UI界面的设计与编写&#xff1b; &#xff08;2&#xff09;熟悉UI界面中场景转换,UI与场景内容相互关联的方式。 &#xff08;3&#xff09;熟悉Unity中MySQL数据库的操作 2.实验内容 新建…

生成式AI与大语言模型,东软已经准备就绪

伴随着ChatGPT的火爆全球&#xff0c;数以百计的大语言模型也争先恐后地加入了这一战局&#xff0c;掀起了一场轰轰烈烈的“百模大战”。毋庸置疑的是&#xff0c;继方兴未艾的人工智能普及大潮之后&#xff0c;生成式AI与大语言模型正在全球开启新一轮生产力革新的科技浪潮。 …

【C语言】深入理解指针(四)

&#x1f308;write in front :&#x1f50d;个人主页 &#xff1a; 啊森要自信的主页 ✏️真正相信奇迹的家伙&#xff0c;本身和奇迹一样了不起啊&#xff01; 欢迎大家关注&#x1f50d;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;>希望看完我的文章对你有小小的帮助&am…

帝国cms开发一个泛知识类的小程序的历程记录

#帝国cms小程序# 要开发一个泛知识类的小程序&#xff0c;要解决以下几个问题。 1。知识内容的分类。 2。知识内容的内容展示。 3。知识内容的价格设置。 4。用户体系&#xff0c;为简化用户的操作&#xff0c;在用户进行下载的时候&#xff0c;请用户输入手机号&#xff…

【HarmonyOS】API6上JS实现视频播放全屏播放时,会回到之前界面

【关键字】 API6 / 视频播放 / 全屏播放异常 【问题现象】 开发者在API6上用JS实现视频播放器点全屏播放后&#xff0c;不是全屏效果&#xff0c;实际效果是变成了横屏并返回到首页。 具体代码实现是参考video媒体组件指南。 【问题分析】 JS实现视频播放器有Codelab代码示…

DedeBIZ 管理系统 DedeV6 v6.2.6 社区版 免费授权版

DedeBIZ 系统&#xff1a;开源、安全、高效的 DedeV6 v6.2.6 社区版 DedeBIZ 系统是基于 PHP 7 版本开发的&#xff0c;具有强大的可扩展性&#xff0c;并且完全开放源代码。它采用现流行的 Go 语言设计开发&#xff0c;不仅拥有简单易用、灵活扩展的特性&#xff0c;还具备更…

Niushop 开源商城 v5.1.7:支持PC、手机、小程序和APP多端电商的源码

Niushop 系统是一款基于 ThinkPHP6 开发的电商系统&#xff0c;提供了丰富的功能和完善的商品机制。该系统支持普通商品和虚拟商品&#xff0c;并且针对虚拟商品还提供了完善的核销机制。同时&#xff0c;它也支持新时代的商业模式&#xff0c;如拼团、分销和多门店砍价等营销活…

Log4j

通过Log4j&#xff0c;我们可以控制日志信息输送到目的地是控制台、文件、GUI组件&#xff0c;甚至是套接口服务器、NT的事件记录器。我们可以控制每一条日志的输出格式。通过定义每一条日志信息的级别&#xff0c;能更加细致地控制日志的生成过程。 1 log4j、log4j2与SLF4J …

pikachu靶场Table pikachu.member doesn’t exist:解决

背景&#xff1a; 第一次搭建pikachu靶场&#xff0c;搭建好后访问index.php后&#xff0c;尝试练习&#xff0c;发现界面显示Table pikachu.member doesn t exist&#xff0c;后来找了很多教程&#xff0c;没有解决&#xff0c;后来发现是自己没有进行初始化&#xff0c;给大家…

VMware 系列:ESXI6.7升级7.0

ESXI6.7升级7.0 一、下载补丁二、上传文件三 启用Shell四、登录Shell后台五、删除不兼容驱动六、正常升级最近,将一台使用ESXI6.7的虚拟机升级到了7.0版本,下面记录一下自己的升级过程。 升级条件 首先确保硬件是否能升级到7.0版本,物理网卡驱动为e1000e不能升级,如果是ig…