baiduaip
一、百度AI入手
預備資料:
1.FFmpeg:
鏈接:https://pan.baidu.com/s/1jonSAa_TG2XuaJEy3iTmHg
密碼:w6hk
2.baidu-aip:
pip install baidu-aip
終于進入主題了,此篇是人工智能應用的重點,只用現成的技術不做底層算法,也是讓初級程序員快速進入人工智能行業的捷徑
目前市面上主流的AI技術提供公司有很多,比如百度,阿里,騰訊,主做語音的科大訊飛,做只能問答的圖靈機器人等等
這些公司投入了很大一部分財力物力人力將底層封裝,提供應用接口給我們,尤其是百度,完全免費的接口
開啟人工智能技術的大門 : http://ai.baidu.com/ 封裝好的接口如下:
首先進入控制臺,注冊一個百度的賬號(百度賬號通用)
開通一下我們百度AI開放平臺的授權,然后找到已開通服務中的百度語音。
打開百度語音,進入語音應用管理界面,創建一個新的應用
創建語音應用App
就可以創建應用了,回到應用列表我們可以看到已創建的應用了
這里面有三個值 AppID , API Key , Secret Key 記住可以從這里面看到。
1.安裝百度的人工智能SDK:
pip install baidu-aip
安裝完成之后就來測試一下:
在工程目錄下,就可以看到 s1.mp3 這個文件了,來聽一聽
上面咱們測試了一個語音合成的例子,那么就從語音合成開始入手
2.語音合成:
baidu-aip Python SDK 語音合成技術文檔 : https://ai.baidu.com/docs#/TTS-Online-Python-SDK/top
這是與百度進行一次加密校驗 , 認證你是合法用戶 合法的應用
AipSpeech 是百度語音的客戶端 認證成功之后,客戶端將被開啟,這里的client 就是已經開啟的百度語音的客戶端了
用百度語音客戶端中的synthesis方法,并提供相關參數
成功可以得到音頻文件,失敗則返回一段錯誤信息
重點看一下 synthesis 這個方法 , 從 https://ai.baidu.com/docs#/TTS-Online-Python-SDK/top 來獲得答案吧
從參數入手分析:
按照這些參數,從新發起一個語音合成
這次聲音是不是與一點點蘿莉了呢?
這都是語音語調的作用 0 - 9 其實就是 御姐音 - 蘿莉音
這就是人工智能中的語音合成技術.
3.語音識別:
聲音這個東西格式太多樣化了,如果要想讓百度的SDK識別咱們的音頻文件,就要想辦法轉變成百度SDK可以識別的格式PCM
目前DragonFire已知可以實現自動化轉換格式并且屢試不爽的工具 : FFmpeg 這個工具的下載地址是 : 鏈接:https://pan.baidu.com/s/1jonSAa_TG2XuaJEy3iTmHg 密碼:w6hk
FFmpeg 環境變量配置:
首先你要解壓縮,然后找到bin目錄,我的目錄是 C:\ffmpeg\bin
然后 以 windows 10 為例,配置環境變量
嘗試一下,是否配置成功
看到這個界面就算配置成功了,配置成功有什么用呢, 這個工具可以將wav wma mp3 等音頻文件轉換為 pcm 無壓縮音頻文件
做一個測試,首先要打開windows的錄音機,錄制一段音頻(說普通話)
現在假設錄制的音頻文件的名字為 audio.wav 放置在 D:\DragonFireAudio\
然后我們用命令行對這個 audio.wav 進行pcm格式的轉換然后得到 audio.pcm
命令是 : ffmpeg -y -i audio.wav -acodec pcm_s16le -f s16le -ac 1 -ar 16000 audio.pcm
然后打開目錄就可以看到pcm文件了
pcm文件已經得到了,趕緊進入正題吧
百度語音識別SDK的應用:
前提是你的audio.pcm 要與你當前的文件在同一個目錄,還是分段看一下代碼
讀取文件的內容,file_context 是 audio.pcm 文件打開的二進制流
asr函數需要四個參數,第四個參數可以忽略,自有默認值,參照一下這些參數是做什么的
第一個參數: speech 音頻文件流 建立包含語音內容的Buffer對象, 語音文件的格式,pcm 或者 wav 或者 amr。(雖說支持這么多格式,但是只有pcm的支持是最好的)
第二個參數: format 文件的格式,包括pcm(不壓縮)、wav、amr(雖說支持這么多格式,但是只有pcm的支持是最好的)
第三個參數: rate 音頻文件采樣率 如果使用剛剛的FFmpeg的命令轉換的,你的pcm文件就是16000
第四個參數: dev_pid 音頻文件語言id 默認1537(普通話 輸入法模型)
再來看下一段代碼,打印返回結果:
成功的dict中 result 就是我們要的識別文本
失敗的dict中 err_no 就是我們要的錯誤編碼,錯誤編碼代表什么呢?
如果err_no不是0的話,就參照一下錯誤碼表.
二、PyAudio 實現錄音 自動化交互實現問答
Python 很強大其原因就是因為它龐大的三方庫 , 資源是非常的豐富 , 當然也不會缺少關于音頻的庫
關于音頻, PyAudio 這個庫, 可以實現開啟麥克風錄音, 可以播放音頻文件等等,此刻我們不去了解其他的功能,只了解一下它如何實現錄音的
首先要先 pip 一個 PyAudio
pip install pyaudio
1.PyAudio 實現麥克風錄音
然后建立一個py文件,復制如下代碼
import pyaudio
import wave
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 16000
RECORD_SECONDS = 2
WAVE_OUTPUT_FILENAME = "Oldboy.wav"
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
print("開始錄音,請說話......")
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print("錄音結束,請閉嘴!")
stream.stop_stream()
stream.close()
p.terminate()
wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
嘗試一下,在目錄中出現了一個 Oldboy.wav 文件 , 聽一聽,還是很清晰的嘛
接下來,我們將這段錄音代碼,寫在一個函數里面,如果要錄音的話就調用
建立一個文件 pyrec.py 并將錄音代碼和函數寫在內
# pyrec.py 文件內容
import pyaudio
import wave
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 2
RATE = 16000
RECORD_SECONDS = 2
def rec(file_name):
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
print("開始錄音,請說話......")
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print("錄音結束,請閉嘴!")
stream.stop_stream()
stream.close()
p.terminate()
wf = wave.open(file_name, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
rec 函數就是我們調用的錄音函數,并且給他一個文件名,他就會自動將聲音寫入到文件中了
2.實現音頻格式自動轉換 并 調用語音識別
錄音的問題解決了,趕快和百度語音識別接在一起使用一下:
不管你的錄音有多么多么清晰,你發現百度給你返回的永遠是:
{'err_msg': 'speech quality error.', 'err_no': 3301, 'sn': '6397933501529645284'} # 音質不清晰
其實不是沒聽清,而是百度支持的音頻格式PCM搞的鬼
所以,我們要將錄制的wav音頻文件轉換為pcm文件
寫一個文件 wav2pcm.py 這個文件里面的函數是專門為我們轉換wav文件的
使用 os 模塊中的 os.system()方法 這個方法是執行系統命令用的, 在windows系統中的命令就是 cmd 里面寫的東西,dir , cd 這類的命令
# wav2pcm.py 文件內容
import os
def wav_to_pcm(wav_file):
# 假設 wav_file = "音頻文件.wav"
# wav_file.split(".") 得到["音頻文件","wav"] 拿出第一個結果"音頻文件" 與 ".pcm" 拼接 等到結果 "音頻文件.pcm"
pcm_file = "%s.pcm" %(wav_file.split(".")[0])
# 就是此前我們在cmd窗口中輸入命令,這里面就是在讓Python幫我們在cmd中執行命令
os.system("ffmpeg -y -i %s -acodec pcm_s16le -f s16le -ac 1 -ar 16000 %s"%(wav_file,pcm_file))
return pcm_file
這樣我們就有了把wav轉為pcm的函數了 , 再重新構建一次咱們的代碼
這次的返回結果還挺讓人滿意的嘛
{'corpus_no': '6569869134617218414', 'err_msg': 'success.', 'err_no': 0, 'result': ['老男孩教育'], 'sn': '8116162981529666859'}
拿到語音識別的字符串了,接下來用這段字符串 語音合成, 學習咱們說出來的話
3.語音合成 與 FFmpeg 播放mp3 文件
拿到字符串了,直接調用synthesis方法去合成吧
這段代碼銜接上一段代碼,成功獲得了 synth.mp3 音頻文件,并且確定了實在學習我們說的話
接下來就是讓我們的程序自動將 synth.mp3 音頻文件播放了 其實PyAudio 有播放的功能,但是操作有點復雜
所以我們還是選擇用簡單的方式解決復雜的問題,就是這么簡單粗暴,是否還記得FFmpeg 呢?
FFmpeg 這個系統工具中,有一個 ffplay 的工具用來打開并播放音頻文件的,使用方法大概是: ffplay 音頻文件.mp3
建立一個playmp3.py文件, 寫一個 play_mp3 的函數用來播放已經合成的語音
# playmp3.py 文件內容
import os
def play_mp3(file_name):
os.system("ffplay %s"%(file_name))
回到主文件,調用playmp3.py文件中的 play_mp3 函數
執行代碼,當你看到 : 開始錄音,請說話......
請大聲的說出: 學IT 找老男孩教育
然后你就會聽到,一個聲音重復你說的話
4.簡單問答
首先我們要把代碼重新梳理一下:
把語音合成 語音識別部分的代碼獨立成函數放到baidu_ai.py文件中
# baidu_ai.py 文件內容
from aip import AipSpeech
# 這里的三個參數,對應在百度語音創建的應用中的三個參數
APP_ID = "xxxxx"
API_KEY = "xxxxxxx"
SECRET_KEY = "xxxxxxxx"
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
def audio_to_text(pcm_file):
# 讀取文件 , 終于得到了PCM文件
with open(pcm_file, 'rb') as fp:
file_context = fp.read()
# 識別本地文件
res = client.asr(file_context, 'pcm', 16000, {
'dev_pid': 1536,
})
# 從字典里面獲取"result"的value 列表中第1個元素,就是識別出來的字符串"老男孩教育"
res_str = res.get("result")[0]
return res_str
def text_to_audio(res_str):
synth_file = "synth.mp3"
synth_context = client.synthesis(res_str, "zh", 1, {
"vol": 5,
"spd": 4,
"pit": 9,
"per": 4
})
with open(synth_file, "wb") as f:
f.write(synth_context)
return synth_file
然后把我們的主文件進行一下修改
import pyrec # 錄音函數文件
import wav2pcm # wav轉換pcm 函數文件
import baidu_ai # 語音合成函數,語音識別函數 文件
import playmp3 # 播放mp3 函數 文件
pyrec.rec("1.wav") # 錄音并生成wav文件,使用方式傳入文件名
pcm_file = wav2pcm.wav_to_pcm("1.wav") # 將wav文件 轉換成pcm文件 返回 pcm的文件名
res_str = baidu_ai.audio_to_text(pcm_file) # 將轉換后的pcm音頻文件識別成 文字 res_str
synth_file = baidu_ai.text_to_audio(res_str) # 將res_str 字符串 合成語音 返回文件名 synth_file
playmp3.play_mp3(synth_file) # 播放 synth_file
res_str 是字符串,如果字符串等于"你叫什么名字"的時候,我們就要給他一個回答:我的名字叫老男孩教育
新建一個FAQ.py的文件然后建立一個函數faq:
# FAQ.py 文件內容
def faq(Q):
if Q == "你叫什么名字": # 問題
return "我的名字是老男孩教育" # 答案
return "我不知道你在說什么" #問題沒有答案時返
在主文件中導入這個函數,并將語音識別后的字符串傳入函數中
現在來嘗試一下:"你叫什么名字","你今年幾歲了"
成功了,現在你可以對 FAQ.py 這個文件進行更多的問題匹配了
三、jieba gensim 最好別分家之最簡單的相似度實現
簡單的問答已經實現了,那么問題也跟著出現了,我不能確定問題一定是"你叫什么名字",也有可能是"你是誰","你叫啥"之類的,這就引出了人工智能中的另一項技術:
自然語言處理(NLP) : 大概意思就是 讓計算機明白一句話要表達的意思,NLP就相當于計算機在思考你說的話,讓計算機知道"你是誰","你叫啥","你叫什么名字"是一個意思
這就要做 : 語義相似度
接下來我們用Python來實現一個簡單的自然語言處理
現在又要用到Python強大的三方庫了
1、第一個是將中文字符串進行分詞的庫叫 jieba
pip install jieba
我們通常把這個庫叫做 結巴分詞 確實是結巴分詞,而且這個詞庫是 made in china , 基本用一下這個結巴分詞:
import jieba key_word = "你叫什么名字" # 定義一句話,基于這句話進行分詞 cut_word = jieba.cut(key_word) # 使用結巴分詞中的cut方法對"你叫什么名字" 進行分詞 print(cut_word) # <generator object Tokenizer.cut at 0x03676390> 不懂生成器的話,就忽略這里 cut_word_list = list(cut_word) # 如果不明白生成器的話,這里要記得把生成器對象做成列表 print(cut_word_list) # ['你', '叫', '什么', '名字'] text1 = "今天天氣很不錯" text2 = "太上皇打天下,到一半兒,掛了" text3 = "先帝創業未半而中道崩殂,今天下三分,益州疲弊,此誠危急存亡之秋也" # res = list(jieba.cut(text)) res = list(jieba.cut_for_search(text1)) # 用這個 res2 = list(jieba.cut_for_search(text2)) res3 = list(jieba.cut_for_search(text3)) # res = list(jieba.lcut_for_search(text)) print(res,res2,res3)
測試代碼就很明顯了,它很清晰的把咱們的中文字符串轉為列表存儲起來了
pip3 install pypinyin
from pypinyin import lazy_pinyin,TONE2,TONE,TONE3
a = "蓓蓓,貝貝"
res = lazy_pinyin(a,style=TONE2)
print("".join(res))
2、第二個是一個語言訓練庫叫 gensim
pip install gensim
這個訓練庫很厲害, 里面封裝很多機器學習的算法, 是目前人工智能的主流應用庫,這個不是很好理解, 需要一定的Python數據處理的功底
import jieba
from gensim import corpora
from gensim import models
from gensim import similarities
# from gensim.models import tfidfmodel,lsimodel
l1 = ["你的名字是什么", "你今年幾歲了", "你有多高你胸多大", "你胸多大"]
a = "你今年多大了"
all_doc_list = []
for doc in l1:
doc_list = [word for word in jieba.cut_for_search(doc)]
all_doc_list.append(doc_list)
print(all_doc_list)
#[['你', '的', '名字', '是', '什么'], ['你', '今年', '幾歲', '了'], ['你', '有', '多', '高', '你', '胸多大'], ['你', '胸多大']]
doc_test_list = [word for word in jieba.cut_for_search(a)]
#[你 今年 多 大 了]
# 制作語料庫
dictionary = corpora.Dictionary(all_doc_list) # 制作詞袋
# 14230 1675 1,9,8,11,1,10 [(1,2),(9,1),(8,1),(11,1)(10,1)]
# 1685
# 詞袋的理解
# 詞袋就是將很多很多的詞,進行排列形成一個 詞(key) 與一個 標志位(value) 的字典
# 例如: {'什么': 0, '你': 1, '名字': 2, '是': 3, '的': 4, '了': 5, '今年': 6, '幾歲': 7, '多': 8, '有': 9, '胸多大': 10, '高': 11}
# 至于它是做什么用的,帶著問題往下看
print("token2id", dictionary.token2id)
print("dictionary", dictionary, type(dictionary))
corpus = [dictionary.doc2bow(doc) for doc in all_doc_list]
# [[(1,1),(4,1),(2,1),(3,1),(0,1)],[(),(),()]] = dictionary.doc2bow(doc)
# 14230 1675
# 1685
# 語料庫:
# 這里是將all_doc_list 中的每一個列表中的詞語 與 dictionary 中的Key進行匹配
# 得到一個匹配后的結果,例如['你', '今年', '幾歲', '了']
# 就可以得到 [(1, 1), (5, 1), (6, 1), (7, 1)]
# 1代表的的是 你 1代表出現一次, 5代表的是 了 1代表出現了一次, 以此類推 6 = 今年 , 7 = 幾歲
print("corpus", corpus, type(corpus))
# 將需要尋找相似度的分詞列表 做成 語料庫 doc_test_vec
doc_test_vec = dictionary.doc2bow(doc_test_list) #[(1,1),(6,1)]
print("doc_test_vec", doc_test_vec, type(doc_test_vec))
# 3 x 1 5
# 3 x 10 + 3 x 5
# 3X5 + 3X5 + 3X5
# 將corpus語料庫(初識語料庫) 使用Lsi模型進行訓練
lsi = models.LsiModel(corpus)
# 向量
# [(5*5),(6*8),(9*3),(5*6)] (4*4)
# 這里的只是需要學習Lsi模型來了解的,這里不做闡述
print("lsi", lsi, type(lsi))
# 語料庫corpus的訓練結果
print("lsi[corpus]", lsi[corpus])
# 獲得語料庫doc_test_vec 在 語料庫corpus的訓練結果 中的 向量表示
print("lsi[doc_test_vec]", lsi[doc_test_vec])
# 文本相似度
# 稀疏矩陣相似度 將 主 語料庫corpus的訓練結果 作為初始值
index = similarities.SparseMatrixSimilarity(lsi[corpus], num_features=len(dictionary.keys()))
# 我是一個標準 正矩形 邊長+-1
# [(5*5),(6*8),(9*3),(5*6)] (4*4) = (5*5) = 1
print("index", index, type(index))
# 將 語料庫doc_test_vec 在 語料庫corpus的訓練結果 中的 向量表示 與 語料庫corpus的 向量表示 做矩陣相似度計算
sim = index[lsi[doc_test_vec]]
print("sim", sim, type(sim))
# 對下標和相似度結果進行一個排序,拿出相似度最高的結果
# cc = sorted(enumerate(sim), key=lambda item: item[1],reverse=True)
cc = sorted(enumerate(sim), key=lambda item: -item[1])
print(cc)
text = l1[cc[0][0]]
print(a,text)
View Code
四、others
# pip install baidu-aip
from aip import AipSpeech
#創建百度AI語音客戶端
""" 你的 APPID AK SK """
APP_ID = '16979868'
API_KEY = '1OyheYgoQY2LNnqnMfq9gDvv'
SECRET_KEY = 'DLuM0hMQqGozLbI4ose7fpCRTk14eXlH'
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
# ##############################語音合成
result = client.synthesis('你好','zh',1,{
'vol':5,
})
print(result)
#識別正確返回語音二進制,錯誤則返回dict 參照下面錯誤碼
if not isinstance(result,dict):
with open('audio.mp3','wb') as f:
f.write(result)
##############################語音識別
# 讀取文件
import os
def get_file_content(filePath):
os.system(f"ffmpeg -y -i {filePath} -acodec pcm_s16le -f s16le -ac 1 -ar 16000 {filePath}.pcm")
with open(f"{filePath}.pcm", 'rb') as fp:
return fp.read()
# 識別本地文件
res = client.asr(get_file_content('audio.mp3'), 'pcm', 16000, {
'dev_pid': 1537,
})
print(res)
"""
// 成功返回
{
"err_no": 0,
"err_msg": "success.",
"corpus_no": "15984125203285346378",
"sn": "481D633F-73BA-726F-49EF-8659ACCC2F3D",
"result": ["北京天氣"]
}
// 失敗返回
{
"err_no": 2000,
"err_msg": "data empty.",
"sn": null
}
"""
#### ffmpeg.org 轉換音頻視頻格式(添加環境變量) (格式工廠)
#### ffmpeg -y -i 16k.wav -acodec pcm_s16le -f s16le -ac 1 -ar 16000 16k.pcm
百度語音識別
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from aip import AipSpeech
#創建百度AI語音客戶端
""" 你的 APPID AK SK """
APP_ID = '16979868'
API_KEY = '1OyheYgoQY2LNnqnMfq9gDvv'
SECRET_KEY = 'DLuM0hMQqGozLbI4ose7fpCRTk14eXlH'
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
#自然語言處理()
from aip import AipNlp
nlp_client = AipNlp(APP_ID, API_KEY, SECRET_KEY)
""" 調用短文本相似度 """
res_nlp = nlp_client.simnet('你的名字是什么', '你丫誰呀')
print(res_nlp)
自然語言處理
# !/usr/bin/env python
# -*- coding: utf-8 -*-
# 圖靈機器人 www.tuling123.com/
import requests
dic = {
"reqType": 0,
"perception": {
"inputText": {
"text": "你叫什么名字"
},
},
"userInfo": {
"apiKey": "5ceb5670c0b743caa6510da14b7a0707",
"userId": "123456789"
}
}
def go_tuling(q):
dic['perception']['inputText']['text'] = q
res = requests.post("http://openapi.tuling123.com/openapi/api/v2", json=dic)
res_dic = res.json()
return res_dic.get("results")[0]["values"]["text"]
圖靈機器人
from aip import AipSpeech
#創建百度AI語音客戶端
""" 你的 APPID AK SK """
APP_ID = '16979868'
API_KEY = '1OyheYgoQY2LNnqnMfq9gDvv'
SECRET_KEY = 'DLuM0hMQqGozLbI4ose7fpCRTk14eXlH'
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
##############################語音識別
#開取語音識別
# 讀取文件
import os
def get_file_content(filePath):
os.system(f"ffmpeg -y -i {filePath} -acodec pcm_s16le -f s16le -ac 1 -ar 16000 {filePath}.pcm")
with open(f"{filePath}.pcm", 'rb') as fp:
return fp.read()
# 識別本地文件
res = client.asr(get_file_content('audio.mp3'), 'pcm', 16000, {
'dev_pid': 1537,
})
#自然語言處理()
from aip import AipNlp
nlp_client = AipNlp(APP_ID, API_KEY, SECRET_KEY)
""" 調用短文本相似度 """
# res_nlp = nlp_client.simnet('你的名字是什么', '你丫誰呀')
# print(res_nlp)
#58% 以上的相似度就算高的
#{'log_id': 957434345924889161, 'texts': {'text_2': '你丫誰呀', 'text_1': '你的名字是什么'}, 'score': 0.71901}
def my_nlp_func(text):
# if "你叫什么名字" in text: #你的名字是什么? 你丫誰呀? 您貴姓? what's your name?
# # NLP 自然語言處理的問題
# return "我叫孫悟空"
if nlp_client.simnet("你叫什么名字",text).get("score") >=0.58:
return "我叫孫悟空"
# return "我沒聽清楚,你能在說一遍么?"
###########
import reqs
return reqs.go_tuling(text)
###########
answer = my_nlp_func(res.get("result")[0])
# ##############################語音合成
result = client.synthesis(answer,'zh',1,{
'vol':5,
})
print(result)
#識別正確返回語音二進制,錯誤則返回dict 參照下面錯誤碼
if not isinstance(result,dict):
with open('answer.mp3','wb') as f:
f.write(result)
#自動播放音頻
# os.system("ffplay answer.mp3") #linux和mac下
os.system("answer.mp3") #window下
語音識別和語音合成
總結
- 上一篇: SQL:分析函数、排名函数、聚合函数配合
- 下一篇: 小程序异常监控及错误处理