! новое событие
Информационный поток
Задания вакансии материалы разработки сообщения форума

Использование Yandex Speachkit для распознавания речи в 1С.

  • Добавить свою публикацию
  • для этого требуется регистрация

     Статья описывает свой скромный опыт работы с Yandex Speachkit Cloud. Она не претендует на максимально развернутое сообщение об этой системе. Скорее, это даже немного художественная статья, переплетающаяся с технической.

     Однажды я задумал написать для себя проект: телеграм-бота, который помогает вести семейный бюджет. Вроде всего-ничего: арендовал vds на убунте 16.4, развернул postgresql 9.6 и, конечно же, сервер 1С 8.3.12...(не помню по памяти), накидал план-проект и, соответственно, приступил к работе. Во время работы вдруг пришла идея: а почему бы не сделать так: отправлять боту аудиосообщение с командой, скажем, "поступление 5 рублей", после этого речь должна будет преобразовываться в текст и обрабатывать команду? К моменту, когда пришла эта идея, основной модуль по обработке команд из текстовых сообщений был готов.

     Пришла идея и понеслось. Во-первых нужно было решить, какой использовать сервис, который будет преобразовывать речь в текст. Оказалось, что русскую речь преобразовывает только сервис Яндекса.

     Небольшое отступление. Прочитав документацию, я понял, что в этом нет ничего сложного. Достаточно написать один http запрос и вуаля... Однако на Инфостарте я нашел обработку, которая, конечно, чуть посложнее, но в принципе - то же самое. Стоит такая обработка 9000р. Нормально так.

     Итак, поехали. Буду писать код по частям и комментировать. Код будет содержать также запросы в телеграм.

     Для начала нужно получить файл звукового сообщения с сервера телеграм. Для этого нужно выполнить два GET запроса. У первого запроса метод "getFile", в котором указывается один параметр - "file_id". Значение этого параметра содержится в структуре сообщения (читайте документацию телеграм апи). При выполнении этого запроса сервер телеграм находит нужный нам звуковой файл и дает ему временную уникальную ссылку, которую выдает в ответе. Второй запрос - это получение, непосредственно, самих двоичных данных файла. После получения сохраняем файл.

 

 	Звук = СтруктураСообщения.voice;
	Запрос = Новый HTTPЗапрос(BotID + "/getFile?file_id=" + Звук.file_id);
	Ответ = Соединение.Получить(Запрос);
	СтрокаОтвет = Ответ.ПолучитьТелоКакСтроку();
	Чтение = Новый ЧтениеJSON;
	Чтение.УстановитьСтроку(СтрокаОтвет);
	Структура = ПрочитатьJSON(Чтение);
			
	Запрос = Новый HTTPЗапрос("/file/" + BotID + "/" + Структура.result.file_path);
	Ответ = Соединение.Получить(Запрос);
	ДД = Ответ.ПолучитьТелоКакДвоичныеДанные();
			
	Файл = ПолучитьИмяВременногоФайла("ogg");
	ДД.Записать(Файл);

 

     На этом останавляваться не будем. Кому интересно - читайте документацию.

     Вот, у нас есть звуковой файл. Такие голосовые сообщения хранятся в формате .ogg, что очень удобно ввиду их небольших размеров, а также того, что Яндекс также по-умолчанию принимает именно этот формат файла. Теперь нам необходимо авторизоваться в Яндекс облаке. Во-первых, нужно похимичить с созданием платежного аккаунта, созданием каталога, назначении ему прав. Обо всём написано здесь. Четвертый пункт в этой инструкции гласит, что нужно получить IAM-токен. Здесь самое интереное: IAM-токен действителен в течение 12 часов. Получается, что его нужно периодически обновлять. Здесь описано, как это сделать. Для обновления IAM-токена нужен постоянный пользовательский OAuth-токен, который можно получить на той же странице, перейдя по ссылке в пункте 2 на вкладке API. Всё, самое сложное позади;)

     Так как IAM-токен действителен в течение 12 часов, то сначала я сделал регламентное задание. Но практика показала, что он действует меньше. Поэтому я сделал, чтобы он обновлялся при получении каждого голосового сообщения. Ничего страшного, пусть пашет;) Итак, для обновления токена создается https соединение с доменом "iam.api.cloud.yandex.net" и стандартными портами и выполняется один простой POST-запрос "/iam/v1/tokens". Заголовок один, который гласит, что мы отправляем данные в формате json. В теле запроса указываем один параметр "yandexPassportOauthToken" и в значение этого параметра указываем наш OAuth-токен. В ответе на такой запрос получаем новенький IAM-токен.

 

Процедура ОбновитьIAMЯндекс()
	
	СоединениеЯндекс = Новый HTTPСоединение("iam.api.cloud.yandex.net", 443, , , , 20, Новый ЗащищенноеСоединениеOpenSSL(), Неопределено);
	
	Заголовки = Новый Соответствие;
	Заголовки.Вставить("Content-Type","application/json");
	Запрос = Новый HTTPЗапрос("/iam/v1/tokens",Заголовки);
	СтрокаТела = "{""yandexPassportOauthToken"": """ + Константы.OAUTHТокен.Получить() + """}";
	Запрос.УстановитьТелоИзСтроки(СтрокаТела,КодировкаТекста.UTF8);
	
	ФайлИтога = ПолучитьИмяВременногоФайла();
	СоединениеЯндекс.ОтправитьДляОбработки(Запрос, ФайлИтога);
	
	ТекДок = Новый ТекстовыйДокумент;
	ТекДок.Прочитать(ФайлИтога);
	
	Ответ = ТекДок.ПолучитьТекст();
	Чтение = Новый ЧтениеJSON;
	Чтение.УстановитьСтроку(Ответ);
	СтруктураОтвета = ПрочитатьJSON(Чтение);
	
	Константы.IAMТокенЯндекс.Установить(СтруктураОтвета.iamToken);
	
КонецПроцедуры

 

     Итак, ещё одна часть завершена. Теперь, наконец, самое интересное - отравить яндексу запрос на распознавание речи. Ах да, ещё нюанс... Помните, что нужно было создать каталог в Яндекс облаке? Нам нужен ID этого каталога. Это совсем не сложно - смотрите здесь.

     И финишная прямая. Создаем новое https соединение с доменом "stt.api.cloud.yandex.net"и стандартными портами. Создаем POST-запрос "/speech/v1/stt:recognize/". В заголовках указываем стандартный "Content-Type=application/json", А также наш IAM-токен. Имя заголовка "Authorization", значение - "Bearer " + наш токен. В параметрах запроса только один обязательный - "folderId", в значение которого вписываем ID нашего каталога. О других параметрах читайте в документации. В тело запроса вставляем наши двоичные данные, полученные с сервера телеграм.

 

СоединениеЯндекс = Новый HTTPСоединение("stt.api.cloud.yandex.net", 443, , , , 20, Новый ЗащищенноеСоединениеOpenSSL(), Неопределено);
Заголовки = Новый Соответствие();
Заголовки.Вставить("Authorization", "Bearer " + Константы.IAMТокенЯндекс.Получить());
Заголовки.Вставить("Content-Type", "application/json");
Запрос = Новый HTTPЗапрос("/speech/v1/stt:recognize/?topic=general&folderId=" + Константы.ИДПапкиЯндекс.Получить() + "&lang=ru-RU",Заголовки);
Запрос.УстановитьТелоИзДвоичныхДанных(ДД);
Ответ = СоединениеЯндекс.ОтправитьДляОбработки(Запрос);					
СтрокаОтвет = Ответ.ПолучитьТелоКакСтроку();
			
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(СтрокаОтвет);
СтруктураОтвета = ПрочитатьJSON(Чтение);
ТекстСообщения = СтруктураОтвета.result;

 

     Всё. В ответе на последний запрос будет результат - строка. После этого делаем с этой строкой всё, что душе угодно;)

     Итак, организовать распознавание речи в текст сделать не так уж сложно. Конечно, не во всяком бизнесе это пригодится. Но зато мне очень круто говорить своему боту, а он делает всё, что я ему скажу;)

     Полный листинг того, что получилось, прилагаю внизу. Если вам оказалась эта статья полезной и интересной, или же у вас есть объективные отзывы и комментарии, буду рад о них узнать. Если статья окажется полезной, то в дальнейшем напишу про прочие фишки, которые я использовал при создании бота, а, может, даже и про то, как этот бот создается. Всем спасибо за внимание!

 

Листинг:

Функция ПолучитьТекстИзГолосовогоСообщения(СтруктураСообщения)
	Если СтруктураСообщения.Свойство("voice") Тогда
		// получаем уникальный код звукового файла
		Звук = СтруктураСообщения.voice;
		Запрос = Новый HTTPЗапрос(BotID + "/getFile?file_id=" + Звук.file_id);
		Ответ = Соединение.Получить(Запрос);
		СтрокаОтвет = Ответ.ПолучитьТелоКакСтроку();
		Чтение = Новый ЧтениеJSON;
		Чтение.УстановитьСтроку(СтрокаОтвет);
		Структура = ПрочитатьJSON(Чтение);
		
		// получаем двоичные данные 
		Запрос = Новый HTTPЗапрос("/file/" + BotID + "/" + Структура.result.file_path);
		Ответ = Соединение.Получить(Запрос);
		ДД = Ответ.ПолучитьТелоКакДвоичныеДанные();	
		
		// обновляем IAM-токен
		ОбновитьIAMЯндекс();

		// получаем готовый результат
		СоединениеЯндекс = Новый HTTPСоединение("stt.api.cloud.yandex.net", 443, , , , 20, Новый ЗащищенноеСоединениеOpenSSL(), Неопределено);
		Заголовки = Новый Соответствие();
		Заголовки.Вставить("Authorization", "Bearer " + Константы.IAMТокенЯндекс.Получить());
		Заголовки.Вставить("Content-Type", "application/json");
		Запрос = Новый HTTPЗапрос("/speech/v1/stt:recognize/?topic=general&folderId=" + Константы.ИДПапкиЯндекс.Получить() + "&lang=ru-RU",Заголовки);
		Запрос.УстановитьТелоИзДвоичныхДанных(ДД);
		Ответ = СоединениеЯндекс.ОтправитьДляОбработки(Запрос);						
		СтрокаОтвет = Ответ.ПолучитьТелоКакСтроку();
			
		Чтение = Новый ЧтениеJSON;
		Чтение.УстановитьСтроку(СтрокаОтвет);
		СтруктураОтвета = ПрочитатьJSON(Чтение);			
		Возврат СтруктураОтвета.result;	
	Иначе
		Возврат Неопределено;	
	КонецЕсли;
КонецФункции

Процедура ОбновитьIAMЯндекс()
	
	СоединениеЯндекс = Новый HTTPСоединение("iam.api.cloud.yandex.net", 443, , , , 20, Новый ЗащищенноеСоединениеOpenSSL(), Неопределено);
	
	Заголовки = Новый Соответствие;
	Заголовки.Вставить("Content-Type","application/json");
	Запрос = Новый HTTPЗапрос("/iam/v1/tokens",Заголовки);
	СтрокаТела = "{""yandexPassportOauthToken"": """ + Константы.OAUTHТокен.Получить() + """}";
	Запрос.УстановитьТелоИзСтроки(СтрокаТела,КодировкаТекста.UTF8);
	
	ФайлИтога = ПолучитьИмяВременногоФайла();
	СоединениеЯндекс.ОтправитьДляОбработки(Запрос, ФайлИтога);
	
	ТекДок = Новый ТекстовыйДокумент;
	ТекДок.Прочитать(ФайлИтога);
	
	Ответ = ТекДок.ПолучитьТекст();
	Чтение = Новый ЧтениеJSON;
	Чтение.УстановитьСтроку(Ответ);
	СтруктураОтвета = ПрочитатьJSON(Чтение);
	
	Константы.IAMТокенЯндекс.Установить(СтруктураОтвета.iamToken);
	
КонецПроцедуры

 

 
0
≡ к списку статей