Python調用百度接口(情感傾向分析)和訊飛接口(語音識別、關鍵詞提取)處理音頻文件


本示例的過程是:

1. 音頻轉文本

2. 利用文本獲取情感傾向分析結果

3. 利用文本獲取關鍵詞提取

 

首先是訊飛的語音識別模塊。在這里可以找到非實時語音轉寫的相關文檔以及 Python 示例。我略作了改動,讓它可以對不同人說話作區分,並且作了一些封裝。

語音識別功能

weblfasr_python3_demo.py 文件:

  1 #!/usr/bin/env python
  2 # -*- coding: utf-8 -*-
  3 """
  4 訊飛非實時轉寫調用demo(語音識別)
  5 """
  6 import base64
  7 import hashlib
  8 import hmac
  9 import json
 10 import os
 11 import time
 12 
 13 import requests
 14 
 15 lfasr_host = 'http://raasr.xfyun.cn/api'
 16 
 17 # 請求的接口名
 18 api_prepare = '/prepare'
 19 api_upload = '/upload'
 20 api_merge = '/merge'
 21 api_get_progress = '/getProgress'
 22 api_get_result = '/getResult'
 23 # 文件分片大下52k
 24 file_piece_sice = 10485760
 25 
 26 # ——————————————————轉寫可配置參數————————————————
 27 # 參數可在官網界面(https://doc.xfyun.cn/rest_api/%E8%AF%AD%E9%9F%B3%E8%BD%AC%E5%86%99.html)查看,根據需求可自行在gene_params方法里添加修改
 28 # 轉寫類型
 29 lfasr_type = 0
 30 # 是否開啟分詞
 31 has_participle = 'false'
 32 has_seperate = 'true'
 33 # 多候選詞個數
 34 max_alternatives = 0
 35 # 子用戶標識
 36 suid = ''
 37 
 38 
 39 class SliceIdGenerator:
 40     """slice id生成器"""
 41 
 42     def __init__(self):
 43         self.__ch = 'aaaaaaaaa`'
 44 
 45     def getNextSliceId(self):
 46         ch = self.__ch
 47         j = len(ch) - 1
 48         while j >= 0:
 49             cj = ch[j]
 50             if cj != 'z':
 51                 ch = ch[:j] + chr(ord(cj) + 1) + ch[j + 1:]
 52                 break
 53             else:
 54                 ch = ch[:j] + 'a' + ch[j + 1:]
 55                 j = j - 1
 56         self.__ch = ch
 57         return self.__ch
 58 
 59 
 60 class RequestApi(object):
 61     def __init__(self, appid, secret_key, upload_file_path):
 62         self.appid = appid
 63         self.secret_key = secret_key
 64         self.upload_file_path = upload_file_path
 65 
 66     # 根據不同的apiname生成不同的參數,本示例中未使用全部參數您可在官網(https://doc.xfyun.cn/rest_api/%E8%AF%AD%E9%9F%B3%E8%BD%AC%E5%86%99.html)查看后選擇適合業務場景的進行更換
 67     def gene_params(self, apiname, taskid=None, slice_id=None):
 68         appid = self.appid
 69         secret_key = self.secret_key
 70         upload_file_path = self.upload_file_path
 71         ts = str(int(time.time()))
 72         m2 = hashlib.md5()
 73         m2.update((appid + ts).encode('utf-8'))
 74         md5 = m2.hexdigest()
 75         md5 = bytes(md5, encoding='utf-8')
 76         # 以secret_key為key, 上面的md5為msg, 使用hashlib.sha1加密結果為signa
 77         signa = hmac.new(secret_key.encode('utf-8'), md5, hashlib.sha1).digest()
 78         signa = base64.b64encode(signa)
 79         signa = str(signa, 'utf-8')
 80         file_len = os.path.getsize(upload_file_path)
 81         file_name = os.path.basename(upload_file_path)
 82         param_dict = {}
 83 
 84         if apiname == api_prepare:
 85             # slice_num是指分片數量,如果您使用的音頻都是較短音頻也可以不分片,直接將slice_num指定為1即可
 86             slice_num = int(file_len / file_piece_sice) + (0 if (file_len % file_piece_sice == 0) else 1)
 87             param_dict['app_id'] = appid
 88             param_dict['signa'] = signa
 89             param_dict['ts'] = ts
 90             param_dict['file_len'] = str(file_len)
 91             param_dict['file_name'] = file_name
 92             param_dict['slice_num'] = str(slice_num)
 93         elif apiname == api_upload:
 94             param_dict['app_id'] = appid
 95             param_dict['signa'] = signa
 96             param_dict['ts'] = ts
 97             param_dict['task_id'] = taskid
 98             param_dict['slice_id'] = slice_id
 99         elif apiname == api_merge:
100             param_dict['app_id'] = appid
101             param_dict['signa'] = signa
102             param_dict['ts'] = ts
103             param_dict['task_id'] = taskid
104             param_dict['file_name'] = file_name
105         elif apiname == api_get_progress or apiname == api_get_result:
106             param_dict['app_id'] = appid
107             param_dict['signa'] = signa
108             param_dict['ts'] = ts
109             param_dict['task_id'] = taskid
110         param_dict['has_seperate'] = has_seperate
111         return param_dict
112 
113     # 請求和結果解析,結果中各個字段的含義可參考:https://doc.xfyun.cn/rest_api/%E8%AF%AD%E9%9F%B3%E8%BD%AC%E5%86%99.html
114     def gene_request(self, apiname, data, files=None, headers=None):
115         response = requests.post(lfasr_host + apiname, data=data, files=files, headers=headers)
116         result = json.loads(response.text)
117         if result["ok"] == 0:
118             # print("{} success:".format(apiname) + str(result))
119             print('treating...')
120             return result
121         else:
122             # print("{} error:".format(apiname) + str(result))
123             exit(0)
124             return result
125 
126     # 預處理
127     def prepare_request(self):
128         return self.gene_request(apiname=api_prepare,
129                                  data=self.gene_params(api_prepare))
130 
131     # 上傳
132     def upload_request(self, taskid, upload_file_path):
133         file_object = open(upload_file_path, 'rb')
134         try:
135             index = 1
136             sig = SliceIdGenerator()
137             while True:
138                 content = file_object.read(file_piece_sice)
139                 if not content or len(content) == 0:
140                     break
141                 files = {
142                     "filename": self.gene_params(api_upload).get("slice_id"),
143                     "content": content
144                 }
145                 response = self.gene_request(api_upload,
146                                              data=self.gene_params(api_upload, taskid=taskid,
147                                                                    slice_id=sig.getNextSliceId()),
148                                              files=files)
149                 if response.get('ok') != 0:
150                     # 上傳分片失敗
151                     print('upload slice fail, response: ' + str(response))
152                     return False
153                 # print('upload slice ' + str(index) + ' success')
154                 print('treating...')
155                 index += 1
156         finally:
157             'file index:' + str(file_object.tell())
158             file_object.close()
159         return True
160 
161     # 合並
162     def merge_request(self, taskid):
163         return self.gene_request(api_merge, data=self.gene_params(api_merge, taskid=taskid))
164 
165     # 獲取進度
166     def get_progress_request(self, taskid):
167         return self.gene_request(api_get_progress, data=self.gene_params(api_get_progress, taskid=taskid))
168 
169     # 獲取結果
170     def get_result_request(self, taskid):
171         return self.gene_request(api_get_result, data=self.gene_params(api_get_result, taskid=taskid))
172 
173     def all_api_request(self):
174         # 1. 預處理
175         pre_result = self.prepare_request()
176         taskid = pre_result["data"]
177         # 2 . 分片上傳
178         self.upload_request(taskid=taskid, upload_file_path=self.upload_file_path)
179         # 3 . 文件合並
180         self.merge_request(taskid=taskid)
181         # 4 . 獲取任務進度
182         while True:
183             # 每隔20秒獲取一次任務進度
184             progress = self.get_progress_request(taskid)
185             progress_dic = progress
186             if progress_dic['err_no'] != 0 and progress_dic['err_no'] != 26605:
187                 # print('task error: ' + progress_dic['failed'])
188                 return
189             else:
190                 data = progress_dic['data']
191                 task_status = json.loads(data)
192                 if task_status['status'] == 9:
193                     # print('task ' + taskid + ' finished')
194                     break
195                 print('The task ' + taskid + ' is in processing, task status: ' + str(data))
196                 print('processing...')
197             # 每次獲取進度間隔20S
198             time.sleep(20)
199         # 5 . 獲取結果
200         return self.get_result_request(taskid=taskid)
201 
202 
203 def get_text_result(upload_file_path):
204     """
205     封裝該接口,獲取接口返回的內容
206     :param upload_file_path:
207     :return: 識別出來的文本數據
208     """
209     api = RequestApi(appid="xxx", secret_key="xxx", upload_file_path=upload_file_path)
210     return api.all_api_request()
211 
212 
213 # 注意:如果出現requests模塊報錯:"NoneType" object has no attribute 'read', 請嘗試將requests模塊更新到2.20.0或以上版本(本demo測試版本為2.20.0)
214 # 輸入訊飛開放平台的appid,secret_key和待轉寫的文件路徑
215 if __name__ == '__main__':
216     result = get_text_result('input/xxx.m4a')
217     print(result)
218     print(type(result))

appid 和 secret_key 需要你自己申請之后,配置上去。

配置好之后填寫需要輸入的音頻,就可以運行該腳本作測試。

python weblfasr_python3_demo.py 
treating...
treating...
treating...
treating...
treating...
The task e3e3284aee4a4e3b86a4fd506960e0f2 is in processing, task status: {"status":2,"desc":"音頻並完成"}
processing...
treating...
The task e3e3284aee4a4e3b86a4fd506960e0f2 is in processing, task status: {"status":3,"desc":"音頻寫中"}
processing...
treating...
treating...
{'data': '[{"bg":"480","ed":"1810","onebest":"我好高興!","speaker":"2"},{"bg":"1820","ed":"4440ebest":"啊明天就放假了!","speaker":"1"}]', 'err_no': 0, 'failed': None, 'ok': 0}
<class 'dict'>

情感傾向分析功能

這里是百度情感傾向分析的文檔,可以選擇 Python SDK 或者 API 接口,我選擇的是 API 接口。並且我對它進行了一定程度的封裝。

baidu_sentiment.py 文件有如下代碼:

 1 #!/usr/bin/env python
 2 # -*- coding: utf-8 -*-
 3 """
 4 百度情感傾向分析:
 5 get_sentiment_result 用於 demo 進行調用
 6 # 參數    說明    描述
 7 # log_id    uint64    請求唯一標識碼
 8 # sentiment    int    表示情感極性分類結果,0:負向,1:中性,2:正向
 9 # confidence    float    表示分類的置信度,取值范圍[0,1]
10 # positive_prob    float    表示屬於積極類別的概率 ,取值范圍[0,1]
11 # negative_prob    float    表示屬於消極類別的概率,取值范圍[0,1]
12 """
13 import json
14 import requests
15 
16 
17 def get_sentiment_result(text):
18     """
19     利用情感傾向分析API來獲取返回數據
20     :param text: 輸入文本
21     :return response: 返回的響應
22     """
23     if text == '':
24         return ''
25     # 請求接口
26     url = 'https://aip.baidubce.com/oauth/2.0/token'
27     # 需要先獲取一個 token
28     client_id = 'xxx'
29     client_secret = 'xxx'
30     params = {
31         'grant_type': 'client_credentials',
32         'client_id': client_id,
33         'client_secret': client_secret
34     }
35     headers = {'Content-Type': 'application/json; charset=UTF-8'}
36     response = requests.post(url=url, params=params, headers=headers).json()
37     access_token = response['access_token']
38 
39     # 通用版情緒識別接口
40     url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/sentiment_classify'
41     # 定制版情緒識別接口
42     # url = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/sentiment_classify_custom'
43     # 使用 token 調用情感傾向分析接口
44     params = {
45         'access_token': access_token
46     }
47     payload = json.dumps({
48         'text': text
49     })
50     headers = {'Content-Type': 'application/json; charset=UTF-8'}
51     response = requests.post(url=url, params=params, data=payload, headers=headers).json()
52     return response
53 
54 
55 if __name__ == '__main__':
56     print(get_sentiment_result('白日放歌須縱酒,青春作伴好還鄉。'))
57     print(get_sentiment_result('思悠悠,恨悠悠,恨到歸時方始休。'))

同樣,你需要在百度創建應用,配置好你的 client_id 和 client_secret。你也可以運行該腳本進行測試。

python baidu_sentiment.py 
{'log_id': 2676765769120607830, 'text': '白日放歌須縱酒,青春作伴好還鄉。', 'items': [{'positive_prob': 0.537741, 'confidence': 0.245186, 'negative_prob': 0.462259, 'sentiment': 1}]}
{'log_id': 4078175744151108694, 'text': '思悠悠,恨悠悠,恨到歸時方始休。', 'items': [{'positive_prob': 0.345277, 'confidence': 0.232717, 'negative_prob': 0.654723, 'sentiment': 0}]}

關鍵詞提取功能

這里可以找到訊飛的關鍵詞提取的接口文檔和示例代碼。同樣我也略作了改動,進行了封裝。

WebLtp_python3_demo.py 文件代碼:

 1 #!/usr/bin/python
 2 # -*- coding: UTF-8 -*-
 3 """
 4 訊飛關鍵詞提取接口
 5 """
 6 import time
 7 import urllib.request
 8 import urllib.parse
 9 import json
10 import hashlib
11 import base64
12 
13 # 接口地址
14 url = "http://ltpapi.xfyun.cn/v1/ke"
15 # 開放平台應用ID
16 x_appid = "xxx"
17 # 開放平台應用接口秘鑰
18 api_key = "xxx"
19 # 語言文本
20 TEXT = "漢皇重色思傾國,御宇多年求不得。楊家有女初長成,養在深閨人未識。天生麗質難自棄,一朝選在君王側。"
21 
22 
23 def get_keyword_result(text):
24     """
25     這是訊飛官方文檔給出的示例
26     :param text: 輸入文本
27     :return response: 返回對象
28     """
29     if text == '':
30         return ''
31     body = urllib.parse.urlencode({'text': text}).encode('utf-8')
32     param = {"type": "dependent"}
33     x_param = base64.b64encode(json.dumps(param).replace(' ', '').encode('utf-8'))
34     x_time = str(int(time.time()))
35     x_checksum = hashlib.md5(api_key.encode('utf-8') +
36                              str(x_time).encode('utf-8') +
37                              x_param).hexdigest()
38     x_header = {'X-Appid': x_appid,
39                 'X-CurTime': x_time,
40                 'X-Param': x_param,
41                 'X-CheckSum': x_checksum}
42     req = urllib.request.Request(url, body, x_header)
43     result = urllib.request.urlopen(req)
44     result = result.read()
45     return result.decode('utf-8')
46 
47 
48 if __name__ == '__main__':
49     keyword_result = get_keyword_result(TEXT)
50     print(keyword_result)
51     print(type(keyword_result))

配置好你的 x_appid 和 api_key。

注意:關鍵詞提取還需要你在訊飛應用的后台設置白名單。

點擊管理,配置好自己的公網 IP。試着運行一下腳本,會有如下輸出:

python WebLtp_python3_demo.py 
{"code":"0","data":{"ke":[{"score":"0.646","word":"漢皇"},{"score":"0.634","word":"御宇"},{"score":"0.633","word":"重色"},{"score":"0.632","word":"王側"},{"score":"0.628","word":"思傾國"},{"score":"0.601","word":"自棄"},{"score":"0.600","word":"楊家"},{"score":"0.588","word":"深閨人未識"},{"score":"0.588","word":"求不得"},{"score":"0.586","word":"天生麗質"}]},"desc":"success","sid":"ltp000aed03@dx589210907749000100"}
<class 'str'>

把所有功能組合起來

用一個 Demo 把所有功能組合起來,並把結果存儲到文件中。

demo.py 如下:

  1 #!/usr/bin/env python
  2 # -*- coding: utf-8 -*-
  3 """
  4 這是主要的demo
  5 流程是:
  6 音頻->訊飛語音識別API->文本
  7 文本再作兩種處理:
  8     文本->百度情緒識別API->情緒識別的響應
  9     文本->訊飛關鍵詞提取API->關鍵詞提取的響應
 10 """
 11 import sys
 12 import json
 13 from weblfasr_python3_demo import get_text_result
 14 from baidu_sentiment import get_sentiment_result
 15 from WebLtp_python3_demo import get_keyword_result
 16 
 17 # 硬編碼選定需要離線分析的音頻
 18 # 以下是一些測試--------------------------
 19 # SOURCE_PATH = 'input/test.mp3'
 20 # SOURCE_PATH = 'input/test.pcm'
 21 # SOURCE_PATH = 'input/test.m4a'
 22 # SOURCE_PATH = 'input/test.wav'
 23 # 以上是一些測試--------------------------
 24 # 或者,通過命令行參數選定需要離線分析的音頻
 25 # 如:python demo.py test.wav
 26 SOURCE_PATH = 'input/' + sys.argv[1]
 27 # STEP 1: 調用訊飛語音識別 API
 28 # 獲取訊飛識別出來的響應
 29 TEXT_RESULT = get_text_result(SOURCE_PATH)
 30 
 31 
 32 def save_file(data, destin):
 33     """
 34     數據持久化函數
 35     :param data: 數據
 36     :param destin: 目標路徑
 37     :return: None
 38     """
 39     data = str(data)
 40     if data:
 41         with open(destin, "w", encoding='utf-8') as f:
 42             f.write(data)
 43 
 44 
 45 def whole_method():
 46     """
 47     將音頻文本不作區分地提取(兩個人的對話不做區分)
 48     :return: None
 49     """
 50     # 解析語音識別出來的數據
 51     data_list = json.loads(TEXT_RESULT['data'])
 52     # text 用於拼接
 53     text_result = ''
 54     for data in data_list:
 55         text_result += data['onebest']
 56     print('text_result:', text_result)
 57     print('text_result completed')
 58     # 把文本寫入到文件中
 59     save_file(text_result, 'output/text_result.txt')
 60     # STEP 2: 情感傾向分析
 61     # 輸入文本,使用情緒識別函數獲取響應
 62     sentiment_result = get_sentiment_result(text_result)
 63     # 保存數據
 64     save_file(sentiment_result, 'output/sentiment_result.txt')
 65     print('sentiment_result completed')
 66     # STEP 3: 關鍵詞提取
 67     # 輸入文本,調用訊飛提取關鍵詞的接口,對文本做關鍵詞提取
 68     keyword_result = get_keyword_result(text_result)
 69     # 保存數據
 70     save_file(keyword_result, 'output/keyword_result.txt')
 71     print('keyword_result completed')
 72 
 73 
 74 def seperate_method():
 75     """
 76     將音頻文本作區分地提取(區分兩個人的對話)
 77     :return: None
 78     """
 79     data_list = json.loads(TEXT_RESULT['data'])
 80     text_result1 = ''
 81     text_result2 = ''
 82     # 假設有兩個人,把文本分別做整合
 83     for data in data_list:
 84         # print(data)
 85         if data['speaker'] == '1':
 86             text_result1 += data['onebest']
 87         else:
 88             text_result2 += data['onebest']
 89     print('text_result1', text_result1)
 90     print('text_result2', text_result2)
 91     print('text_result1 text_result2 completed')
 92     save_file(text_result1, 'output/text_result1.txt')
 93     save_file(text_result2, 'output/text_result2.txt')
 94     # STEP 2: 情感傾向分析
 95     # 輸入文本,使用情緒識別函數獲取響應
 96     # A 的對話
 97     sentiment_result1 = get_sentiment_result(text_result1)
 98     save_file(sentiment_result1, 'output/sentiment_result1.txt')
 99     print('result_get_result1 completed')
100     # B 的對話
101     sentiment_result2 = get_sentiment_result(text_result2)
102     save_file(sentiment_result2, 'output/sentiment_result2.txt')
103     print('result_get_result2 completed')
104     # STEP 3: 關鍵詞提取
105     # 調用訊飛接口做文本的關鍵字提取
106     # A 的對話
107     keyword_result1 = get_keyword_result(text_result1)
108     save_file(keyword_result1, 'output/keyword_result1.txt')
109     print('keyword_result1 completed')
110     # B 的對話
111     keyword_result2 = get_keyword_result(text_result2)
112     save_file(keyword_result2, 'output/keyword_result2.txt')
113     print('keyword_result2 completed')
114 
115 
116 if __name__ == '__main__':
117     if TEXT_RESULT:
118         whole_method()
119         seperate_method()

輸出大致如下:

python demo.py test.mp3
treating...
treating...
treating...
treating...
treating...
The task 8552d13470ed4839b11e0f3693f296f9 is in processing, task status: {"status":2,"desc":"音頻合並完成"}
processing...
treating...
...
The task 8552d13470ed4839b11e0f3693f296f9 is in processing, task status: {"status":3,"desc":"音頻轉寫中"}
processing...
treating...
treating...
text_result: 喂喂你好,是xxx的機主是吧?誰?呀我是xxx的工作人員,您在今天中午12點多在我們xxx提交了xxx是吧?那怎么?...那沒有關系,我說您是否辦理xxx?什么有什么有關系,啊有什么有關系啊。
text_result completed
sentiment_result completed
keyword_result completed
text_result1 喂喂你好,是xxx的機主是吧?呀我是xxx的工作人員,您在今天中午12點多在我們xxx提交了xxx是吧?...那沒有關系,我說您是否辦理xxx?
text_result2 誰?那怎么?...什么有什么有關系,啊有什么有關系啊。
text_result1 text_result2 completed
result_get_result1 completed
result_get_result2 completed
keyword_result1 completed
keyword_result2 completed

原文作者:雨先生
原文鏈接:https://www.cnblogs.com/noluye/p/11225024.html 
許可協議:知識共享署名-非商業性使用 4.0 國際許可協議


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM