· 5 years ago · Aug 12, 2020, 10:18 AM
1import xml.etree.ElementTree as XmlElementTree
2import httplib2
3import uuid
4from config import ***
5
6
7***_HOST = '***'
8***_PATH = '/***_xml'
9CHUNK_SIZE = 1024 ** 2 # Размер чанка. 1 МБ.
10
11
12def speech_to_text(filename=None, bytes=None, request_id=uuid.uuid4().hex,
13 topic='notes', lang='ru-RU', key=***_API_KEY):
14 """Распознавание речи
15 filename: имя звукового файла
16 bytes: байты (звук)
17 request_id: наверное, ID запроса, но значение по умолчанию вычисляется только 1 раз...
18 lang: язык сообщения
19 key: ключ API
20 """
21
22
23 # Получаем байты звука из аргументов или читаем из файла
24 if filename:
25 with open(filename, 'br') as file:
26 bytes = file.read()
27 if not bytes:
28 # Если байтов не дали, ошибка
29 raise Exception('Neither file name nor bytes provided.')
30
31 # Импульсно-кодовая модуляция, bit: 16, rate: 16000
32 bytes = convert_to_pcm16b16000r(in_bytes=bytes)
33
34 # Собираем URL
35 url = ***_PATH + '?uuid=%s&key=%s&topic=%s&lang=%s' % (
36 request_id,
37 key,
38 topic,
39 lang
40 )
41
42 # Разбиваем байты на чанки
43 chunks = read_chunks(CHUNK_SIZE, bytes)
44
45 # Создаем запрос
46 connection = httplib2.HTTPConnectionWithTimeout(***_HOST)
47 connection.connect()
48 connection.putrequest('POST', url)
49 connection.putheader('Transfer-Encoding', 'chunked')
50 connection.putheader('Content-Type', 'audio/x-pcm;bit=16;rate=16000')
51 connection.endheaders()
52
53 # Отправляем чанки
54 for chunk in chunks:
55 connection.send(('%s\r\n' % hex(len(chunk))[2:]).encode())
56 connection.send(chunk)
57 connection.send('\r\n'.encode())
58 connection.send('0\r\n\r\n'.encode())
59
60 # Получаем ответ
61 response = connection.getresponse()
62 if response.code == 200:
63 # Если ответ получен успешно, парсим XML
64 response_text = response.read()
65 xml = XmlElementTree.fromstring(response_text)
66
67 if int(xml.attrib['success']) == 1:
68 # Поиск варианта с максимально высокой вероятностью правильного распознавания
69 max_confidence = -float("inf")
70 text = ''
71 for child in xml:
72 if float(child.attrib['confidence']) > max_confidence:
73 text = child.text
74 max_confidence = float(child.attrib['confidence'])
75
76 if max_confidence != -float("inf"): # Если нашли хоть какой-то вариант
77 return text
78 else:
79 # Нет вариантов
80 raise SpeechException('No text found.\n\nResponse:\n%s' % (response_text))
81 else:
82 # Тот ресурс, который мы просили распознать текст, отработал с ошибкой
83 raise SpeechException('No text found.\n\nResponse:\n%s' % (response_text))
84 else:
85 # Ошибка запроса
86 raise SpeechException('Unknown error.\nCode: %s\n\n%s' % (response.code, response.read()))
87
88сlass SpeechException(Exception):
89 # Кастомное исключение
90 pass
91