前戲
一、 知識儲備
1.函數 : def args kwargs
def func(參數1,參數2): # def 用來定義函數及函數名,參數1和參數2就是定義時的形參,也就是將來調用函數時必須要傳入的參數 變量1 = 參數1+參數2 return 變量1
# *args 就是 將未定義且多余的 位置參數記錄在內,偷偷的告訴你,args是個元祖,里面記錄着你個函數傳遞的多余位置參數 # **kwargs 就是 將多余的關鍵字參數記錄在內,kwargs 其實是個dict哦,里面大概就是{"name":"python","age":1+1+1+1+1+1+18}
def args_func(a,b,*args): # args 里面保存着除了ab之外的所有多余參數 print(args) # 這回知道是元組了吧 for i in args: print(i) args_func(1,2,3,4,5,6) # 這里調用的時候1,2分別傳遞給a,b,那么3456就會保存在args里面哦
def kwargs_func(a, b, **kwargs): # kwargs 里面保存着除了ab之外其他關鍵字傳入參的參數 print(kwargs) # 這回知道是字典了吧 for k, v in kwargs: print(k, v) kwargs_func(1, 2, c=3, d=4, e=5) # 這里調用的時候,12分別傳遞給a,b 那么c=3,d=4,e=5 就會保存在**kwargs里面哦
def args_kwargs_func(*args, **kwargs): # 這里一定要注意*args 要在 **kwargs之前 print(args) print(kwargs) args_kwargs_func(1, 2, a=1, b=2) # 12存入args a=1,b=2 存入kwargs,這里要注意的是關鍵字傳參之后,不可以在位置傳參了
2.推導式
兩個栗子:
2.1 列表推導式:
li = [i for i in range(10)] # 簡單的列表推導式,就是在列表內寫一個for循環對吧 print(li) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] lis = [i for i in range(10) if i % 2 == 0] # 這是帶if 條件的列表推導式 print(lis) # [0, 2, 4, 6, 8
2.2 生成器推導式:
gener = (i for i in range(10)) # 簡單的生成器推導式,就是在元組內寫一個for循環對吧 print(gener) # <generator object <genexpr> at 0x04F9B3C0> geners = (i for i in range(10) if i % 2 == 0) # 這是帶if 條件的生成器推導式 print(geners) # <generator object <genexpr> at 0x04F9B3F0>
從上述來看,列表推導式和生成器推導式只是[] 與 () 的區別
但是實際上,生成器推導式的效率非常高,但可控性很差,比如不直觀,用一次就沒了
相對而言列表推導式的效率比較低,但是可控性強,可以反復利用,而且數據顯示很直觀
3.模塊
字符串之json模塊
import json # 我們做一個字典 dic = { "name": "Dragon", "age": 20, "hobby": ["摩托車", "騎車"], "other": { "say": "hello", "see": "beautiful girl", } } json_dic = json.dumps(dic) # json序列化 print(type(json_dic), json_dic) # <class 'str'> {"name": "Dragon", "age": 20, "hobby": ["\u6469\u6258\u8f66", "\u9a91\u8f66"], "other": {"say": "hello", "see": "beautiful girl"}} loads_dic = json.loads(json_dic) # json 反序列化 print(type(loads_dic), loads_dic) # <class 'dict'> {'name': 'Dragon', 'age': 20, 'hobby': ['摩托車', '騎車'], 'other': {'say': 'hello', 'see': 'beautiful girl'}}
os模塊,集成了很多操作系統的方法,比如創建文件夾,拼接路徑,刪除文件,創建文件等等
import os os.path.join("a","b") # 組合路徑 a/b os.system("ls") # 執行系統命令 os.sep() # 獲取當前操作系統的路徑分隔符 os.path.dirname(__file__) # 獲取當前文件的所在目錄
os補充:
import os os.getcwd() # 獲取當前工作目錄,即當前python腳本工作的目錄路徑 os.chdir("dirname") # 改變當前腳本工作目錄;相當於shell下cd os.curdir() # 返回當前目錄: ('.') os.pardir() # 獲取當前目錄的父目錄字符串名:('..') os.makedirs('dir1/dir2') # 可生成多層遞歸目錄 os.removedirs('dirname1') # 若目錄為空,則刪除,並遞歸到上一級目錄,如若也為空,則刪除,依此類推 os.mkdir('dirname') # 生成單級目錄;相當於shell中mkdir dirname os.rmdir('dirname') # 刪除單級空目錄,若目錄不為空則無法刪除,報錯;相當於shell中rmdir dirname os.listdir('dirname') # 列出指定目錄下的所有文件和子目錄,包括隱藏文件,並以列表方式打印 os.remove("file_name") # 刪除一個文件 os.rename("oldname", "new") # 重命名文件/目錄 os.stat('path/filename') # 獲取文件/目錄信息 os.sep() # 操作系統特定的路徑分隔符,win下為"\\",Linux下為"/" os.linesep() # 當前平台使用的行終止符,win下為"\t\n",Linux下為"\n" os.pathsep() # 用於分割文件路徑的字符串 os.name() # 字符串指示當前使用平台。win->'nt'; Linux->'posix' os.system("bash command") # 運行shell命令,直接顯示 os.environ() # 獲取系統環境變量 os.path.abspath(path) # 返回path規范化的絕對路徑 os.path.split(path) # 將path分割成目錄和文件名二元組返回 os.path.dirname(path) # 返回path的目錄。其實就是os.path.split(path)的第一個元素 os.path.basename(path) # 返回path最后的文件名。如何path以/或\結尾,那么就會返回空值。即os.path.split(path)的第二個元素 os.path.exists(path) # 如果path存在,返回True;如果path不存在,返回False os.path.isabs(path) # 如果path是絕對路徑,返回True os.path.isfile(path) # 如果path是一個存在的文件,返回True。否則返回False os.path.isdir(path) # 如果path是一個存在的目錄,則返回True。否則返回False os.path.join(path1[, path2[, ...]]) # 將多個路徑組合后返回,第一個絕對路徑之前的參數將被忽略 os.path.getatime(path) # 返回path所指向的文件或者目錄的最后存取時間 os.path.getmtime(path) # 返回path所指向的文件或者目錄的最后修改時間
4.文件操作
f = open("123.txt","rb") #打開文件句柄 print(f.read()) # 讀取文件內容 f.close() # 關閉文件句柄
打開文件時,需要指定文件路徑和以何等方式打開文件,打開后,即可獲取該文件句柄,日后通過此文件句柄對該文件操作。
打開文件的模式有:
- r ,只讀模式【默認】
- w,只寫模式【不可讀;不存在則創建;存在則清空內容;】
- x, 只寫模式【不可讀;不存在則創建,存在則報錯】
- a, 追加模式【可讀; 不存在則創建;存在則只追加內容;】
"+" 表示可以同時讀寫某個文件
- r+, 讀寫【可讀,可寫】
- w+,寫讀【可讀,可寫】
- x+ ,寫讀【可讀,可寫】
- a+, 寫讀【可讀,可寫】
"b"表示以字節的方式操作
- rb 或 r+b
- wb 或 w+b
- xb 或 w+b
- ab 或 a+b
注:以b方式打開時,讀取到的內容是字節類型,寫入時也需要提供字節類型
# 文件上下文操作 with open("123.txt","rb") as f: # 文件句柄f 自動打開關閉文件句柄 f.read() # 讀取文件內容(全部) with open("123.txt","rb") as f: f.read() #讀取文件內容(全部) f.readline() # 讀取文件中一行文件 f.readlines() # 讀取文件中所有行 ["1","2"] f.write("666") # 寫入文件內容 f.writelines("666") # 寫入一行文件 f.flush()# 刷新文件 f.seek(10) # 移動光標到10位置 f.truncate(6) # 從光標當前位置截取6位 f.tell() # 獲取當前光標位置
人工智能底層的擇取
預備環境: 1.FFmpeg: 鏈接:https://pan.baidu.com/s/1jonSAa_TG2XuaJEy3iTmHg 密碼:w6hk 2.baidu-aip: pip install baidu-aip
此篇是人工智能應用的重點,只用現成的技術不做底層算法,也是讓初級程序員快速進入人工智能行業的捷徑
目前失眠上主流的AI技術提供公司有很多,BAT和只能問答的圖靈機器人等,另外提一點:主做語音的科大訊飛是佼佼者但它是有償使用
這里我們采用百度的完全免費接口
開啟人工智能技術的大門 : http://ai.baidu.com/
首先進入控制台,注冊一個百度的賬號(百度賬號通用)
開通一下我們百度AI開放平台的授權
然后找到已開通服務中的百度語音
這里省去自行創建應用過程
進入管理應用,牢記下述3個值,后面實例接口時會用上
二、 百度的人工智能SDK:
1.安裝SDK與測試
首先咱們要 pip install baidu-aip 安裝一個百度人工智能開放平台的Python SDK實在是太方便了,這也是為什么我們選擇百度人工智能的最大原因
在工程目錄下,就可以看到s1.mp3這個文件了,可用播放器試聽效果
上面咱們測試了一個語音合成的例子,那么就從語音合成開始入手
2.語音合成

#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/08/25 18:28 # @Author : MJay_Lee # @File : ai.py # @Contact : limengjiejj@hotmail.com from aip import AipSpeech """ 你的 APPID AK SK """ APP_ID = '11721488' API_KEY = 'RSs9MrcwhhdndG6vLHN9Q9dC' SECRET_KEY = 'RpQwPMiPUYXYNOFb0bmFIHORNj4t6Nb0' client = AipSpeech(APP_ID, API_KEY, SECRET_KEY) res = client.synthesis( "智能語音的第一個示例", # text,合成的文本,使用UTF-8編碼,請注意文本長度必須小於1024字節 "zh", # lang,語言,中文:zh 英文:en 1, # ctp,客戶端信息這里就寫1 { # 這是一個dict類型的參數,里面的kv是關鍵,如下: "vol":5, # 合成音頻文件的准音量 "spd":4, # 語速,0~9,默認為5,中語速 "pit":8, # 語調音調,0~9,默認為5,中語調 "per":4, # 發音人選擇,0為女聲,1為1男聲,3為度逍遙,4為度丫丫,默認為普通女聲 } ) if not isinstance(res,dict): with open("audio.mp3","wb")as f: f.write(res) else: print(res) ''' # 錯誤返回示例: { 'err_detail': 'Params error.', 'err_msg': 'parameter error.', 'err_no': 501, 'err_subcode': 29, 'tts_logid': 3204603220 } '''
技術上,代碼上的任何疑慮都可以從官方文檔中得到答案
baidu-aip Python SDK 語音合成技術文檔 : https://ai.baidu.com/docs#/TTS-Online-Python-SDK/top
剛才我們做了一個語音合成的例子,借此可繼續展開說明
這里與百度進行一次加密校驗,認證你是合法用戶,合法的應用
AipSpeech 是百度語音的客戶端,認證成功之后,客戶端都將被開啟,這里的client就是已經開啟的百度語音的客戶端
res就是咱們音頻文件的byte流
如果失敗,res就會是個字典,如上圖的 #錯誤返回示例。
用百度語音客戶端中的synthesis方法,並提供相關參數
成功可以得到音頻文件,失敗則返回一段錯誤信息
重點看一下 synthesis 這個方法 , 從 https://ai.baidu.com/docs#/TTS-Online-Python-SDK/top 來獲得答案吧
從參數入手分析:
至此,人工只能中的語音合成技術點到為止了。
3.語音識別

#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/08/25 18:28 # @Author : MJay_Lee # @File : ai.py # @Contact : limengjiejj@hotmail.com from aip import AipSpeech """ 你的 APPID AK SK """ APP_ID = '11721488' API_KEY = 'RSs9MrcwhhdndG6vLHN9Q9dC' SECRET_KEY = 'RpQwPMiPUYXYNOFb0bmFIHORNj4t6Nb0' client = AipSpeech(APP_ID, API_KEY, SECRET_KEY) # 讀取文件 def get_file_content(filePath): with open(filePath, 'rb') as fp: return fp.read() # 識別本地文件 res = client.asr(get_file_content('audio.pcm'), 'pcm', 16000, { 'dev_pid': 1536, }) print(res) ''' # res內容 { 'corpus_no': '6594294686519761176', 'err_msg': 'success.', 'err_no': 0, 'result': ['陳傑陳傑你好'], 'sn': '995932809701535353876' } '''
聲音這個東西格式太多樣化了,如果要想讓百度的SDK識別咱們的音頻文件,就要想辦法轉變成百度SDK可以識別的格式PCM
已知可以實現自動化轉換格式並且屢試不爽的工具 : FFmpeg
FFmpeg 環境變量配置:
首先你要解壓縮,然后找到bin目錄,
我的目錄是 C:\my_AI\ai_voice\ffmpeg-20180619-a990184-win64-shared\bin
以window10為例,配置環境變量
嘗試一下是否配置成功
看到這個界面就算配置成功了
ffmpeg 這個工具可以將wav wma MP3 等音頻文件轉換為pcm無壓縮音頻文件,測試過程如下:
# 做一個測試,首先要打開windows的錄音機,錄制一段音頻(說普通話) # 現在假設錄制的音頻文件的名字為 audio.wav 放置在 c:\myaudio\ # 然后我們用命令行對這個 audio.wav 進行pcm格式的轉換然后得到 audio.pcm # 命令是 : ffmpeg -y -i audio.wav -acodec pcm_s16le -f s16le -ac 1 -ar 16000 audio.pcm
在錄音文件所在目錄下,執行上述命令,然后打開目錄,就可以看到pcm文件了
好了,換個環境
以mac為例,配置環境變量
自行安裝brew,然后導入ffmpeg
brew install ffmpeg
切換root用戶
su root
成功切換至root用戶后,添加ffmpeg至環境變量
vim /etc/profile # 進入profile文件,將ffmpeg絕對路徑添加至export中,如下: export "PATH=/usr/local/mysql/bin:/anaconda3/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/tools/unrar:/usr/local/Cellar/ffmpeg/4.0.2/bin/ffmpeg"
最后重啟服務即可
source /etc/profile
接下來步驟同windows一樣,找到目標文件,執行事先制定好的pcm文件命令即可得到我們需要的pcm文件
那么, pcm文件已經得到了,進入正題
百度語音識別SDK的應用:
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的話,就參照一下錯誤碼表
到此百度AI語音部分的調用就結束了。
補充:mac環境中,自動執行mp3文件,要改用指令:os.system("open xueshuohua.mp3")

#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/08/27 15:31 # @Author : MJay_Lee # @File : ai_xueshuohua.py # @Contact : limengjiejj@hotmail.com import os from aip import AipSpeech """ 你的 APPID AK SK """ APP_ID = '11721488' API_KEY = 'RSs9MrcwhhdndG6vLHN9Q9dC' SECRET_KEY = 'RpQwPMiPUYXYNOFb0bmFIHORNj4t6Nb0' client = AipSpeech(APP_ID, API_KEY, SECRET_KEY) # 自動化交互將自己說的音頻內容轉換為pcm文件 file_name = "audio" cmd_str = f"ffmpeg -y -i {file_name}.m4a -acodec pcm_s16le -f s16le -ac 1 -ar 16000 {file_name}.pcm" os.system(cmd_str) # 讀取文件 def get_file_content(filePath): with open(filePath, 'rb') as fp: return fp.read() # 識別本地文件 res = client.asr(get_file_content('audio.pcm'), 'pcm', 16000, { 'dev_pid': 1536, }) # 提取自己說的內容 text = res['result'][0] # 合成ai的音頻文件對象 speech = client.synthesis(text,'zh',1,{ 'spd': 4, 'vol': 8, 'pit': 8, 'per': 4 }) # 創建ai的音頻文件 with open("xueshuohua.mp3","wb") as f: f.write(speech) os.system("xueshuohua.mp3")
三、 Pyaudio實現錄音 自動化交互問答
Python 很強大其原因就是因為它龐大的三方庫 , 資源是非常的豐富 , 當然也不會缺少關於音頻的庫
關於音頻, PyAudio 這個庫, 可以實現開啟麥克風錄音, 可以播放音頻文件等等,此刻我們不去了解其他的功能,只了解一下它如何實現錄音的
首先
pip install pyaudio
1.Pyaudio實現麥克風錄音
(補充flask理論先)