百度AI開放平台官網:http://ai.baidu.com/?track=cp:aipinzhuan|pf:pc|pp:AIpingtai|pu:title|ci:|kw:10005792
pip3 install baidu-aip
百度AI的使用:
1、首先創建應用:
2、使用方法可以查看文檔:
3、各功能的使用
3.1 語言合成:

from aip import AipSpeech """ 你的 APPID AK SK """ APP_ID = '15420336' API_KEY = 'VwSGcqqwsCl282LGKnFwHDIA' SECRET_KEY = 'h4oL6Y9yRuvmD0oSdQGQZchNcix4TF5P' client = AipSpeech(APP_ID, API_KEY, SECRET_KEY) result = client.synthesis('先帝創業未半而中道崩殂', 'zh', 1, { 'vol': 5, "spd": 3, "pit": 7, "per": 4 }) print(result) # 識別正確返回語音二進制 錯誤則返回dict 參照下面錯誤碼 if not isinstance(result, dict): with open('audio.mp3', 'wb') as f: f.write(result)
Python使用 語言合成 文檔:
3.1.1 簡介
Hi,您好,歡迎使用百度語音合成服務。
本文檔主要針對Python開發者,描述百度語音合成接口服務的相關技術內容。如果您對文檔內容有任何疑問,可以通過以下幾種方式聯系我們:
- 在百度雲控制台內提交工單,咨詢問題類型請選擇人工智能服務;
- 加入開發者QQ群:910926227
接口能力
接口名稱 | 接口能力簡要描述 |
---|---|
語音合成 | 將計算機自己產生的、或外部輸入的文字信息轉變為可以聽得懂的、流利的口語輸出的技術。 |
注意事項
目前本SDK的功能同REST API,需要聯網調用http接口 。REST API 僅支持最多512字(1024 字節)的音頻合成,合成的文件格式為mp3。沒有其他額外功能。 如果需要使用離線合成等其它功能,請使用Android或者iOS 合成 SDK
請嚴格按照文檔里描述的參數進行開發。請注意以下幾個問題:
- 合成文本長度必須小於1024字節,如果本文長度較長,可以采用多次請求的方式。切忌文本長度超過限制。
2.新創建語音合成應用不限制每日調用量,但有QPS限額。詳細限額數據可在控制台中查看。完成個人實名認證及企業認證可提高QPS限額。若需更大QPS可進一步商務合作咨詢。
- 必填字段中,嚴格按照文檔描述中內容填寫。
版本更新記錄
上線日期 | 版本號 | 更新內容 |
---|---|---|
2017.5.11 | 1.0.0 | 語音合成服務上線 |
3.1.2 快速入門
安裝語音合成 Python SDK
語音合成 Python SDK目錄結構
├── README.md
├── aip //SDK目錄
│ ├── __init__.py //導出類
│ ├── base.py //aip基類
│ ├── http.py //http請求
│ └── speech.py //語音合成
└── setup.py //setuptools安裝
支持Python版本:2.7.+ ,3.+
安裝使用Python SDK有如下方式:
- 如果已安裝pip,執行
pip install baidu-aip
即可。 - 如果已安裝setuptools,執行
python setup.py install
即可。
新建AipSpeech
AipSpeech是語音合成的Python SDK客戶端,為使用語音合成的開發人員提供了一系列的交互方法。
參考如下代碼新建一個AipSpeech:
from aip import AipSpeech
""" 你的 APPID AK SK """
APP_ID = '你的 App ID'
API_KEY = '你的 Api Key'
SECRET_KEY = '你的 Secret Key'
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
在上面代碼中,常量APP_ID
在百度雲控制台中創建,常量API_KEY
與SECRET_KEY
是在創建完畢應用后,系統分配給用戶的,均為字符串,用於標識用戶,為訪問做簽名驗證,可在AI服務控制台中的應用列表中查看。
配置AipSpeech
如果用戶需要配置AipSpeech的網絡請求參數(一般不需要配置),可以在構造AipSpeech之后調用接口設置參數,目前只支持以下參數:
接口 | 說明 |
---|---|
setConnectionTimeoutInMillis | 建立連接的超時時間(單位:毫秒 |
setSocketTimeoutInMillis | 通過打開的連接傳輸數據的超時時間(單位:毫秒) |
3.1.3 接口說明
語音合成
接口描述
基於該接口,開發者可以輕松的獲取語音合成能力
請求說明
- 合成文本長度必須小於1024字節,如果本文長度較長,可以采用多次請求的方式。文本長度不可超過限制
舉例,要把一段文字合成為語音文件:
result = client.synthesis('你好百度', 'zh', 1, {
'vol': 5,
})
# 識別正確返回語音二進制 錯誤則返回dict 參照下面錯誤碼
if not isinstance(result, dict):
with open('auido.mp3', 'wb') as f:
f.write(result)
參數 | 類型 | 描述 | 是否必須 |
---|---|---|---|
tex | String | 合成的文本,使用UTF-8編碼, 請注意文本長度必須小於1024字節 |
是 |
cuid | String | 用戶唯一標識,用來區分用戶, 填寫機器 MAC 地址或 IMEI 碼,長度為60以內 |
否 |
spd | String | 語速,取值0-9,默認為5中語速 | 否 |
pit | String | 音調,取值0-9,默認為5中語調 | 否 |
vol | String | 音量,取值0-15,默認為5中音量 | 否 |
per | String | 發音人選擇, 0為女聲,1為男聲, 3為情感合成-度逍遙,4為情感合成-度丫丫,默認為普通女 |
否 |
返回樣例:
// 成功返回二進制文件流
// 失敗返回
{
"err_no":500,
"err_msg":"notsupport.",
"sn":"abcdefgh",
"idx":1
}
3.1.4 錯誤信息
錯誤返回格式
若請求錯誤,服務器將返回的JSON文本包含以下參數:
- error_code:錯誤碼。
- error_msg:錯誤描述信息,幫助理解和解決發生的錯誤。
錯誤碼
錯誤碼 | 含義 |
---|---|
500 | 不支持的輸入 |
501 | 輸入參數不正確 |
502 | token驗證失敗 |
503 | 合成后端錯誤 |
3.2 語言識別

from aip import AipSpeech import os """ 你的 APPID AK SK """ APP_ID = '15420336' API_KEY = 'VwSGcqqwsCl282LGKnFwHDIA' SECRET_KEY = 'h4oL6Y9yRuvmD0oSdQGQZchNcix4TF5P' client = AipSpeech(APP_ID, API_KEY, SECRET_KEY) # 讀取文件 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('wyn.wma'), 'pcm', 16000, { 'dev_pid': 1536, }) print(res.get("result")[0])
Python使用 語言識別 文檔:
音頻處理工具
3.2.1 簡介
目前本SDK的功能同REST API,需要聯網調用http接口, 具體功能見REST API 文檔, REST API 僅支持整段語音識別的模式,即需要上傳完整語音文件進行識別,時長不超過60s,支持、自定義詞庫設置, 沒有其他額外功能。
接口能力
接口名稱 | 接口能力簡要描述 |
---|---|
語音識別 | 將人類的語音中的詞匯內容轉換為計算機可讀的輸入,例如按鍵、二進制編碼或者字符序列 |
支持的語音格式
原始 PCM 的錄音參數必須符合 16k 采樣率、16bit 位深、單聲道,支持的格式有:pcm(不壓縮)、wav(不壓縮,pcm編碼)、amr(壓縮格式)。
注意事項
如果需要使用實時識別、長語音、喚醒詞、語義解析等其它語音功能,請使用Android或者iOS SDK 或 Linux C++ SDK 等。
- 請嚴格按照文檔里描述的參數進行開發,特別請關注原始錄音參數以及語音壓縮格式的建議,否則會影響識別率,進而影響到產品的用戶體驗。
- 目前系統支持的語音時長上限為60s,請不要超過這個長度,否則會返回錯誤。
反饋
- 在百度雲控制台內提交工單,咨詢問題類型請選擇人工智能服務;
- QQ群快速溝通: AI開放平台官網首頁底部“QQ支持群”中,查找“百度語音”。
版本更新記錄
上線日期 | 版本號 | 更新內容 |
---|---|---|
2017.5.11 | 1.0.0 | 語音識別服務上線 |
3.2.2 快速入門
安裝語音識別 Python SDK
語音識別 Python SDK目錄結構
├── README.md
├── aip //SDK目錄
│ ├── __init__.py //導出類
│ ├── base.py //aip基類
│ ├── http.py //http請求
│ └── speech.py //語音識別
└── setup.py //setuptools安裝
支持Python版本:2.7.+ ,3.+
安裝使用Python SDK有如下方式:
- 如果已安裝pip,執行
pip install baidu-aip
即可。 - 如果已安裝setuptools,執行
python setup.py install
即可。
新建AipSpeech
AipSpeech是語音識別的Python SDK客戶端,為使用語音識別的開發人員提供了一系列的交互方法。
參考如下代碼新建一個AipSpeech:
from aip import AipSpeech
""" 你的 APPID AK SK """
APP_ID = '你的 App ID'
API_KEY = '你的 Api Key'
SECRET_KEY = '你的 Secret Key'
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
在上面代碼中,常量APP_ID
在百度雲控制台中創建,常量API_KEY
與SECRET_KEY
是在創建完畢應用后,系統分配給用戶的,均為字符串,用於標識用戶,為訪問做簽名驗證,可在AI服務控制台中的應用列表中查看。
配置AipSpeech
如果用戶需要配置AipSpeech的網絡請求參數(一般不需要配置),可以在構造AipSpeech之后調用接口設置參數,目前只支持以下參數:
接口 | 說明 |
---|---|
setConnectionTimeoutInMillis | 建立連接的超時時間(單位:毫秒 |
setSocketTimeoutInMillis | 通過打開的連接傳輸數據的超時時間(單位:毫秒) |
3.2.3 接口說明
語音識別
接口描述
向遠程服務上傳整段語音進行識別
請求說明
舉例,要對段保存有一段語音的語音文件進行識別:
# 讀取文件
def get_file_content(filePath):
with open(filePath, 'rb') as fp:
return fp.read()
# 識別本地文件
client.asr(get_file_content('audio.pcm'), 'pcm', 16000, {
'dev_pid': 1536,
})
參數 | 類型 | 描述 | 是否必須 |
---|---|---|---|
speech | Buffer | 建立包含語音內容的Buffer對象, 語音文件的格式,pcm 或者 wav 或者 amr。不區分大小寫 | 是 |
format | String | 語音文件的格式,pcm 或者 wav 或者 amr。不區分大小寫。推薦pcm文件 | 是 |
rate | int | 采樣率,16000,固定值 | 是 |
cuid | String | 用戶唯一標識,用來區分用戶,填寫機器 MAC 地址或 IMEI 碼,長度為60以內 | 否 |
dev_pid | Int | 不填寫lan參數生效,都不填寫,默認1537(普通話 輸入法模型),dev_pid參數見本節開頭的表格 | 否 |
lan(已廢棄) | String | 歷史兼容參數,請使用dev_pid。如果dev_pid填寫,該參數會被覆蓋。語種選擇,輸入法模型,默認中文(zh)。 中文=zh、粵語=ct、英文=en,不區分大小寫。 | 否 |
dev_pid 參數列表
dev_pid | 語言 | 模型 | 是否有標點 | 備注 |
---|---|---|---|---|
1536 | 普通話(支持簡單的英文識別) | 搜索模型 | 無標點 | 支持自定義詞庫 |
1537 | 普通話(純中文識別) | 輸入法模型 | 有標點 | 支持自定義詞庫 |
1737 | 英語 | 無標點 | 不支持自定義詞庫 | |
1637 | 粵語 | 有標點 | 不支持自定義詞庫 | |
1837 | 四川話 | 有標點 | 不支持自定義詞庫 | |
1936 | 普通話遠場 | 遠場模型 | 有標點 | 不支持 |
語音識別 返回數據參數詳情
參數 | 類型 | 是否一定輸出 | 描述 |
---|---|---|---|
err_no | int | 是 | 錯誤碼 |
err_msg | int | 是 | 錯誤碼描述 |
sn | int | 是 | 語音數據唯一標識,系統內部產生,用於 debug |
result | int | 是 | 識別結果數組,提供1-5 個候選結果,string 類型為識別的字符串, utf-8 編碼 |
返回樣例:
// 成功返回
{
"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
}
3.2.4 錯誤信息
錯誤返回格式
若請求錯誤,服務器將返回的JSON文本包含以下參數:
- error_code:錯誤碼。
- error_msg:錯誤描述信息,幫助理解和解決發生的錯誤。
錯誤碼
錯誤碼 | 用戶輸入/服務端 | 含義 | 一般解決方法 |
---|---|---|---|
3300 | 用戶輸入錯誤 | 輸入參數不正確 | 請仔細核對文檔及參照demo,核對輸入參數 |
3301 | 用戶輸入錯誤 | 音頻質量過差 | 請上傳清晰的音頻 |
3302 | 用戶輸入錯誤 | 鑒權失敗 | token字段校驗失敗。請使用正確的API_KEY 和 SECRET_KEY生成。或QPS、調用量超出限額。或音頻采樣率不正確(可嘗試更換為16k采樣率)。 |
3303 | 服務端問題 | 語音服務器后端問題 | 請將api返回結果反饋至論壇或者QQ群 |
3304 | 用戶請求超限 | 用戶的請求QPS超限 | 請降低識別api請求頻率 (qps以appId計算,移動端如果共用則累計) |
3305 | 用戶請求超限 | 用戶的日pv(日請求量)超限 | 請“申請提高配額”,如果暫未通過,請降低日請求量 |
3307 | 服務端問題 | 語音服務器后端識別出錯問題 | 目前請確保16000的采樣率音頻時長低於30s。如果仍有問題,請將api返回結果反饋至論壇或者QQ群 |
3308 | 用戶輸入錯誤 | 音頻過長 | 音頻時長不超過60s,請將音頻時長截取為60s以下 |
3309 | 用戶輸入錯誤 | 音頻數據問題 | 服務端無法將音頻轉為pcm格式,可能是長度問題,音頻格式問題等。 請將輸入的音頻時長截取為60s以下,並核對下音頻的編碼,是否是16K, 16bits,單聲道。 |
3310 | 用戶輸入錯誤 | 輸入的音頻文件過大 | 語音文件共有3種輸入方式: json 里的speech 參數(base64后); 直接post 二進制數據,及callback參數里url。 分別對應三種情況:json超過10M;直接post的語音文件超過10M;callback里回調url的音頻文件超過10M |
3311 | 用戶輸入錯誤 | 采樣率rate參數不在選項里 | 目前rate參數僅提供16000,填寫4000即會有此錯誤 |
3312 | 用戶輸入錯誤 | 音頻格式format參數不在選項里 | 目前格式僅僅支持pcm,wav或amr,如填寫mp3即會有此錯誤 |
錯誤碼常見問題及具體分析
3300 錯誤
語音識別api使用的是HTTP POST方法, BODY里直接放置json, Content-Type頭部為 application/json。 並非常見的瀏覽器表單請求(application/x-www-form-urlencoded或者multipart/x-www-form-urlencoded)。
必填字段:format rate channel cuid token cuid token cuid token cuid token,請勿漏填。此外 (speech, len) 及 (url, callback) 這兩組參數必須二選一,如果都填,默認處理第一組。 channel cuid token,請勿漏填。此外 (speech, len) 及 (url, callback) 這兩組參數必須二選一,如果都填,默認處理第一種。 channel cuid token,請勿漏填。此外 (speech, len) 及 (url, callback) 這兩組參數必須二選一,如果都填,默認處理第一種。
必填字段如format rate channel cuid token,請勿漏填。此外 (speech, len) 及 (url, callback) 這兩組參數必須二選一,如果都填,默認處理第一種,並確認 音頻時長截取為60s以下。
3309錯誤
wav和amr的音頻,服務端會自動轉為pcm,這個過程中導致轉碼出錯。請確認下format及rate參數與音頻一致,並確認音頻時長截取為60s以下。
3301 錯誤
識別結果實際為空。可能是音頻質量過差,不清晰,或者是空白音頻。 有時也可能是pcm填錯采樣率。如16K采樣率的pcm文件,填寫的rate參數為8000。
行業與場景限制 根據工信部《綜合整治騷擾電話專項行動方案》、《關於推進綜合整治騷擾電話專項行動的工作方案》,相關能力不得用於商業營銷類、惡意騷擾類和違法犯罪類騷擾電話類場景,也不支持在貸款、理財、信用卡、股票、基金、債券、保險、售房租房、醫療機構、保健食品、人力資源服務、旅游等場景的騷擾電話營銷行為。
基於 語言合成 和 語言識別 可以做一個 機器學我們說話 功能:

from aip import AipSpeech import time,os """ 你的 APPID AK SK """ APP_ID = '15420336' API_KEY = 'VwSGcqqwsCl282LGKnFwHDIA' SECRET_KEY = 'h4oL6Y9yRuvmD0oSdQGQZchNcix4TF5P' client = AipSpeech(APP_ID, API_KEY, SECRET_KEY) # 讀取文件 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() def audio2text(filepath): # 識別本地文件 res = client.asr(get_file_content(filepath), 'pcm', 16000, { 'dev_pid': 1536, }) print(res.get("result")[0]) return res.get("result")[0] def text2audio(text): filename = f"{time.time()}.mp3" result = client.synthesis(text, 'zh', 1, { 'vol': 5, "spd": 3, "pit": 7, "per": 4 }) # 識別正確返回語音二進制 錯誤則返回dict 參照下面錯誤碼 if not isinstance(result, dict): with open(filename, 'wb') as f: f.write(result) return filename text = audio2text("wyn.wma") filename = text2audio(text) os.system(filename)
3.3 自然語言處理技術
短文本相似度NLP

from aip import AipSpeech,AipNlp import time,os """ 你的 APPID AK SK """ APP_ID = '15420336' API_KEY = 'VwSGcqqwsCl282LGKnFwHDIA' SECRET_KEY = 'h4oL6Y9yRuvmD0oSdQGQZchNcix4TF5P' nlp = AipNlp(APP_ID, API_KEY, SECRET_KEY) #短文本相似度 client = AipSpeech(APP_ID, API_KEY, SECRET_KEY) # 讀取文件 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() def audio2text(filepath): # 識別本地文件 res = client.asr(get_file_content(filepath), 'pcm', 16000, { 'dev_pid': 1536, }) print(res.get("result")[0]) return res.get("result")[0] def text2audio(text): filename = f"{time.time()}.mp3" result = client.synthesis(text, 'zh', 1, { 'vol': 5, "spd": 3, "pit": 7, "per": 4 }) # 識別正確返回語音二進制 錯誤則返回dict 參照下面錯誤碼 if not isinstance(result, dict): with open(filename, 'wb') as f: f.write(result) return filename def to_tuling(text): import requests args = { "reqType": 0, "perception": { "inputText": { "text": text } }, "userInfo": { "apiKey": "9a9a026e2eb64ed6b006ad99d27f6b9e", "userId": "1111" } } url = "http://openapi.tuling123.com/openapi/api/v2" res = requests.post(url, json=args) text = res.json().get("results")[0].get("values").get("text") return text # res = nlp.simnet("你叫什么名字","你的名字是什么") # print(res) text = audio2text("bjtq.wma") # 短文本相似度 if nlp.simnet("你叫什么名字",text).get("score") >= 0.68 : text = "我的名字叫銀角大王8" else: text = to_tuling(text) filename = text2audio(text) os.system(filename)
圖靈機器人官網:http://www.tuling123.com/
基於 語言合成 和 語言識別 以及 自然語言的短文本相似度 還有 圖靈機器人 做一個 機器智能回答問題 的功能:
簡易版:

from aip import AipSpeech,AipNlp import time,os """ 你的 APPID AK SK """ APP_ID = '15420336' API_KEY = 'VwSGcqqwsCl282LGKnFwHDIA' SECRET_KEY = 'h4oL6Y9yRuvmD0oSdQGQZchNcix4TF5P' nlp = AipNlp(APP_ID, API_KEY, SECRET_KEY) client = AipSpeech(APP_ID, API_KEY, SECRET_KEY) # 讀取文件 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() def audio2text(filepath): # 識別本地文件 res = client.asr(get_file_content(filepath), 'pcm', 16000, { 'dev_pid': 1536, }) print(res.get("result")[0]) return res.get("result")[0] def text2audio(text): filename = f"{time.time()}.mp3" result = client.synthesis(text, 'zh', 1, { 'vol': 5, "spd": 3, "pit": 7, "per": 4 }) # 識別正確返回語音二進制 錯誤則返回dict 參照下面錯誤碼 if not isinstance(result, dict): with open(filename, 'wb') as f: f.write(result) return filename def to_tuling(text): import requests args = { "reqType": 0, "perception": { "inputText": { "text": text } }, "userInfo": { "apiKey": "9a9a026e2eb64ed6b006ad99d27f6b9e", "userId": "1111" } } url = "http://openapi.tuling123.com/openapi/api/v2" res = requests.post(url, json=args) text = res.json().get("results")[0].get("values").get("text") return text # res = nlp.simnet("你叫什么名字","你的名字是什么") # print(res) text = audio2text("bjtq.wma") if nlp.simnet("你叫什么名字",text).get("score") >= 0.68 : text = "我的名字叫銀角大王8" else: text = to_tuling(text) filename = text2audio(text) os.system(filename)
完善版:

from flask import Flask,render_template,request,jsonify,send_file from uuid import uuid4 import baidu_ai app = Flask(__name__) @app.route("/") def index(): return render_template("index.html") @app.route("/ai",methods=["POST"]) def ai(): # 1.保存錄音文件 audio = request.files.get("record") filename = f"{uuid4()}.wav" audio.save(filename) #2.將錄音文件轉換為PCM發送給百度進行語音識別 q_text = baidu_ai.audio2text(filename) #3.將識別的問題交給圖靈或自主處理獲取答案 a_text = baidu_ai.to_tuling(q_text) #4.將答案發送給百度語音合成,合成音頻文件 a_file = baidu_ai.text2audio(a_text) #5.將音頻文件發送給前端播放 return jsonify({"filename":a_file}) @app.route("/get_audio/<filename>") def get_audio(filename): return send_file(filename) if __name__ == '__main__': app.run("0.0.0.0",9527,debug=True)

from aip import AipSpeech,AipNlp import time,os """ 你的 APPID AK SK """ APP_ID = '15420336' API_KEY = 'VwSGcqqwsCl282LGKnFwHDIA' SECRET_KEY = 'h4oL6Y9yRuvmD0oSdQGQZchNcix4TF5P' nlp = AipNlp(APP_ID, API_KEY, SECRET_KEY) client = AipSpeech(APP_ID, API_KEY, SECRET_KEY) # 讀取文件 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() def audio2text(filepath): # 識別本地文件 res = client.asr(get_file_content(filepath), 'pcm', 16000, { 'dev_pid': 1536, }) print(res.get("result")[0]) return res.get("result")[0] def text2audio(text): filename = f"{time.time()}.mp3" result = client.synthesis(text, 'zh', 1, { 'vol': 5, "spd": 3, "pit": 7, "per": 4 }) # 識別正確返回語音二進制 錯誤則返回dict 參照下面錯誤碼 if not isinstance(result, dict): with open(filename, 'wb') as f: f.write(result) return filename def to_tuling(text): import requests args = { "reqType": 0, "perception": { "inputText": { "text": text } }, "userInfo": { "apiKey": "9a9a026e2eb64ed6b006ad99d27f6b9e", "userId": "1111" } } url = "http://openapi.tuling123.com/openapi/api/v2" res = requests.post(url, json=args) text = res.json().get("results")[0].get("values").get("text") print("圖靈答案",text) return text

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <audio controls autoplay id="player"></audio> <p> <button onclick="start_reco()" style="background-color: yellow">錄制語音指令</button> </p> <p> <button onclick="stop_reco_audio()" style="background-color: blue">發送語音指令</button> </p> </body> <!--<script type="application/javascript" src="/static/Recorder.js"></script>--> <script type="application/javascript" src="https://cdn.bootcss.com/recorderjs/0.1.0/recorder.js"></script> <script type="text/javascript" src="/static/jQuery3.1.1.js"></script> <script type="text/javascript"> var reco = null; var audio_context = new AudioContext(); navigator.getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); navigator.getUserMedia({audio: true}, create_stream, function (err) { console.log(err) }); function create_stream(user_media) { var stream_input = audio_context.createMediaStreamSource(user_media); reco = new Recorder(stream_input); } function start_reco() { reco.record(); } function stop_reco_audio() { reco.stop(); send_audio(); reco.clear(); } function send_audio() { reco.exportWAV(function (wav_file) { var formdata = new FormData(); formdata.append("record", wav_file); console.log(formdata); $.ajax({ url: "http://192.168.13.42:9527/ai", type: 'post', processData: false, contentType: false, data: formdata, dataType: 'json', success: function (data) { document.getElementById("player").src ="http://192.168.13.42:9527/get_audio/" + data.filename } }); }) } </script> </html>

bootsdn download

(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Recorder = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ "use strict"; module.exports = require("./Recorder").Recorder; },{"./recorder":2}],2:[function(require,module,exports){ 'use strict'; var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor); } }return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.Recorder = undefined; var _inlineWorker = require('inline-worker'); var _inlineWorker2 = _interopRequireDefault(_inlineWorker); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Recorder = exports.Recorder = (function () { function Recorder(source, cfg) { var _this = this; _classCallCheck(this, Recorder); this.config = { bufferLen: 4096, numChannels: 2, mimeType: 'audio_pcm/wav' }; this.recording = false; this.callbacks = { getBuffer: [], exportWAV: [] }; Object.assign(this.config, cfg); this.context = source.context; this.node = (this.context.createScriptProcessor || this.context.createJavaScriptNode).call(this.context, this.config.bufferLen, this.config.numChannels, this.config.numChannels); this.node.onaudioprocess = function (e) { if (!_this.recording) return; var buffer = []; for (var channel = 0; channel < _this.config.numChannels; channel++) { buffer.push(e.inputBuffer.getChannelData(channel)); } _this.worker.postMessage({ command: 'record', buffer: buffer }); }; source.connect(this.node); this.node.connect(this.context.destination); //this should not be necessary var self = {}; this.worker = new _inlineWorker2.default(function () { var recLength = 0, recBuffers = [], sampleRate = undefined, numChannels = undefined; self.onmessage = function (e) { switch (e.data.command) { case 'init': init(e.data.config); break; case 'record': record(e.data.buffer); break; case 'exportWAV': exportWAV(e.data.type); break; case 'getBuffer': getBuffer(); break; case 'clear': clear(); break; } }; function init(config) { sampleRate = config.sampleRate; numChannels = config.numChannels; initBuffers(); } function record(inputBuffer) { for (var channel = 0; channel < numChannels; channel++) { recBuffers[channel].push(inputBuffer[channel]); } recLength += inputBuffer[0].length; } function exportWAV(type) { var buffers = []; for (var channel = 0; channel < numChannels; channel++) { buffers.push(mergeBuffers(recBuffers[channel], recLength)); } var interleaved = undefined; if (numChannels === 2) { interleaved = interleave(buffers[0], buffers[1]); } else { interleaved = buffers[0]; } var dataview = encodeWAV(interleaved); var audioBlob = new Blob([dataview], { type: type }); self.postMessage({ command: 'exportWAV', data: audioBlob }); } function getBuffer() { var buffers = []; for (var channel = 0; channel < numChannels; channel++) { buffers.push(mergeBuffers(recBuffers[channel], recLength)); } self.postMessage({ command: 'getBuffer', data: buffers }); } function clear() { recLength = 0; recBuffers = []; initBuffers(); } function initBuffers() { for (var channel = 0; channel < numChannels; channel++) { recBuffers[channel] = []; } } function mergeBuffers(recBuffers, recLength) { var result = new Float32Array(recLength); var offset = 0; for (var i = 0; i < recBuffers.length; i++) { result.set(recBuffers[i], offset); offset += recBuffers[i].length; } return result; } function interleave(inputL, inputR) { var length = inputL.length + inputR.length; var result = new Float32Array(length); var index = 0, inputIndex = 0; while (index < length) { result[index++] = inputL[inputIndex]; result[index++] = inputR[inputIndex]; inputIndex++; } return result; } function floatTo16BitPCM(output, offset, input) { for (var i = 0; i < input.length; i++, offset += 2) { var s = Math.max(-1, Math.min(1, input[i])); output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true); } } function writeString(view, offset, string) { for (var i = 0; i < string.length; i++) { view.setUint8(offset + i, string.charCodeAt(i)); } } function encodeWAV(samples) { var buffer = new ArrayBuffer(44 + samples.length * 2); var view = new DataView(buffer); /* RIFF identifier */ writeString(view, 0, 'RIFF'); /* RIFF chunk length */ view.setUint32(4, 36 + samples.length * 2, true); /* RIFF type */ writeString(view, 8, 'WAVE'); /* format chunk identifier */ writeString(view, 12, 'fmt '); /* format chunk length */ view.setUint32(16, 16, true); /* sample format (raw) */ view.setUint16(20, 1, true); /* channel count */ view.setUint16(22, numChannels, true); /* sample rate */ view.setUint32(24, sampleRate, true); /* byte rate (sample rate * block align) */ view.setUint32(28, sampleRate * 4, true); /* block align (channel count * bytes per sample) */ view.setUint16(32, numChannels * 2, true); /* bits per sample */ view.setUint16(34, 16, true); /* data chunk identifier */ writeString(view, 36, 'data'); /* data chunk length */ view.setUint32(40, samples.length * 2, true); floatTo16BitPCM(view, 44, samples); return view; } }, self); this.worker.postMessage({ command: 'init', config: { sampleRate: this.context.sampleRate, numChannels: this.config.numChannels } }); this.worker.onmessage = function (e) { var cb = _this.callbacks[e.data.command].pop(); if (typeof cb == 'function') { cb(e.data.data); } }; } _createClass(Recorder, [{ key: 'record', value: function record() { this.recording = true; } }, { key: 'stop', value: function stop() { this.recording = false; } }, { key: 'clear', value: function clear() { this.worker.postMessage({ command: 'clear' }); } }, { key: 'getBuffer', value: function getBuffer(cb) { cb = cb || this.config.callback; if (!cb) throw new Error('Callback not set'); this.callbacks.getBuffer.push(cb); this.worker.postMessage({ command: 'getBuffer' }); } }, { key: 'exportWAV', value: function exportWAV(cb, mimeType) { mimeType = mimeType || this.config.mimeType; cb = cb || this.config.callback; if (!cb) throw new Error('Callback not set'); this.callbacks.exportWAV.push(cb); this.worker.postMessage({ command: 'exportWAV', type: mimeType }); } }], [{ key: 'forceDownload', value: function forceDownload(blob, filename) { var url = (window.URL || window.webkitURL).createObjectURL(blob); var link = window.document.createElement('a'); link.href = url; link.download = filename || 'output.wav'; var click = document.createEvent("Event"); click.initEvent("click", true, true); link.dispatchEvent(click); } }]); return Recorder; })(); exports.default = Recorder; },{"inline-worker":3}],3:[function(require,module,exports){ "use strict"; module.exports = require("./inline-worker"); },{"./inline-worker":4}],4:[function(require,module,exports){ (function (global){ "use strict"; var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var WORKER_ENABLED = !!(global === global.window && global.URL && global.Blob && global.Worker); var InlineWorker = (function () { function InlineWorker(func, self) { var _this = this; _classCallCheck(this, InlineWorker); if (WORKER_ENABLED) { var functionBody = func.toString().trim().match(/^function\s*\w*\s*\([\w\s,]*\)\s*{([\w\W]*?)}$/)[1]; var url = global.URL.createObjectURL(new global.Blob([functionBody], { type: "text/javascript" })); return new global.Worker(url); } this.self = self; this.self.postMessage = function (data) { setTimeout(function () { _this.onmessage({ data: data }); }, 0); }; setTimeout(function () { func.call(self); }, 0); } _createClass(InlineWorker, { postMessage: { value: function postMessage(data) { var _this = this; setTimeout(function () { _this.self.onmessage({ data: data }); }, 0); } } }); return InlineWorker; })(); module.exports = InlineWorker; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{}]},{},[1])(1) });