Самообслуживание клиентов с помощью google ASR

Началось все с запроса клиента который хотел шагать в ногу со временем и частично заменить живых операционистов на бездушного робота — сделать прием показаний счетчиков через телефон. С вводом через DTMF вроде все понятно и никакой изюминки в этом нет. Хотелось ввод голосом.

Под cut’ом небольшой мануал про прикручивание google ASR к одному из коробочных вариантов asterisk’a.

После некоторого мониторинга интернета было найдено несколько готовых решений на технологиях ЦРТ. Может и хорошо но ценник стартовал от 150 кило рублей, поэтому идем мимо (привет жаба).

Голый asterisk брать не стали, потому как хочется какой никакой гуй, FreePBX тоже пошел лесом ибо оно превращается в один большой custom-context, взяли коробку XVB — VirtualPBX потому как: cdr, TTS, gsm модемы, автоинформатор ( наш второй этап ) из коробки, ASR и база данных через http API. Берем бесплатную ( от платных отличается только ограничением на 10 одновременных звонков), версию — для наших 2 линий ТфОП и 2 3G свистков за глаза. В принципе к тому же switchvox’у прикручивание примерно такое же.

Поехали:

Качаем с сайта или зеркала ( стабильная но с чуть старым астериском тут ) большой tar.bz2 архив с готовым для работы имиджем для VMWare Player. Или если есть старая версия ставим апдейты.

Распаковываем и запускаем в VMWare плеере либо конвертируем в ESXi или делаем дамп на реальное железо. Ничего сложного. Первый запуск немного долгий ибо распаковываются звуковые файлы и проверяются апдейты.

Лирическое отступление:
Система задумывалась для создания хостинга виртуальных АТС, но так как используется нами единолично то и админы и пользователи мы сами. В общем такая не маленькая `пушка` для борьбы с `воробьями`. Но есть и дополнительные плюшки, например возможность создать несколько QA из коробки.

Заходим в интерфейс администратора, делаем пользователя, добавляем DID, меняем ему язык на Русский-Женщина ( это google TTS ) — эта виртуальная АТС и будет нашей системой самообслуживания. Более подробно про настройку писать наверное не стоит, тут уже писали.

Затем топаем в консоль и пишем cgi скрипт который будет к гуглу ходить. Берем пример и немного правим чтоб понимал CGI параметры, получаем что то типа:

#!/usr/bin/perl ######################################################################## use strict;  use CGI qw(:standard); use LWP::UserAgent; use JSON::XS;  my $lang = param('lang'); my $file = param('file'); my $var_name = param('var') || 'ASR_RESULT';  print "Content-type: text/plain; charset=utf-8\n\n";  my $url;  if ( lc($lang) eq 'ru' ) {     $url = "http://www.google.com/speech-api/v1/recognize?xjerr=1&client=chromium&lang=ru-RU"; } else {     $url = "http://www.google.com/speech-api/v1/recognize?xjerr=1&client=chromium&lang=en-US"; }  my $new_file = "/tmp/google-asr-$$.wav";  open(TMP,">$new_file"); my $buffer;  while ( !eof($file) ) {     read( $file, $buffer, 16384 );     print TMP $buffer; }  system "ffmpeg -y -i $new_file $new_file.flac 2>/dev/null";  if ( $? ) {     print "$var_name=\n";     die "Can't convert file $new_file to $new_file.flac: $?\n"; } else {     $new_file .= '.flac'; }  my $file_info = `file $new_file`;  if ( $file_info =~ /FLAC audio.*\s([\d.]+)\s*kHz/ ) {     $file_info = $1 * 1000; } else {     unlink $new_file;     print "$var_name=\n";     die "Incorrect FLAC file: $file_info\n"; }  unless ( open( FILE, "<$new_file" ) ) {     print "$var_name=\n";     die "Can't open input file[$file]: $!\n"; } undef $/; my $audio = <FILE>; $/ = "\n"; close(FILE);  unlink $new_file;  my $ua = LWP::UserAgent->new( debug => 1 );  my $response = $ua->post($url, Content_Type => "audio/x-flac; rate=$file_info", Content => $audio);  if ( $response->is_success ) {     my $h_ref;      eval {         my $json = JSON::XS->new();         $h_ref = $json->decode($response->content());     };     if ( ref $h_ref eq 'HASH' and exists $h_ref->{'hypotheses'} ) {         my $data = $h_ref->{'hypotheses'}->[0]->{'utterance'};         my $map = {             'нoль'          => 0,             'oдин'          => 1,             'двa'           => 2,             'три'           => 3,             'четыре'        => 4,             'пять'          => 5,             'шесть'         => 6,             'семь'          => 7,             'вoсемь'        => 8,             'девять'        => 9,             'десять'        => 10,               'да'            => 'да',              'дальше'        => 'да',              'верно'         => 'да',              'нет'           => 'нет',             'назад'         => 'нет',               'газ'           => 'газ',               'гас'           => 'газ',               'вода'          => 'вода',               'воду'          => 'воду',               'свет'          => 'свет',               'электричество' => 'свет',               'электро'       => 'свет',          };          my $result = '';          foreach my $ch ( split(/\s+/,$data) ) {             $result .= length($map->{$ch}) ? $map->{$ch} : $ch;         }          print "$var_name=$result\n";         exit;     } }  print "$var_name=\n"; 

Кроме чтения CGI параметров еще добавили `конвертацию в числа` из строк вида ‘один’,’два’ и тд и несколько ‘альясов’ на названия типов счетчиков и подтверждение ( да == да||дальше||верно ), потому как на некоторых линиях ‘дальше’ распознается лучше чем просто ‘да’.

На входе скрипт принимает файл в wav формате и имя переменной куда записать значение (это передается в XVB и используется в диалплане), делаем еще 2 скрипта:

  • Второй ( account_check.cgi ) проверяет корректность ввода лицевого счета,
  • Третий ( commit.cgi ) записывает данные в базу.

Я не буду приводить их здесь потому, что там все будет зависеть от Вашей БД. Третий скрипт принимает номер лицевого счета / тип показаний / и показания и записывает их в БД и возвращает разницу. Мы проговариваем ее пользователю.
Сохраняем эти скрипты на той же машине ( или на другой ) в /var/www/cgi-bin/.

Далее происходит скучная настройка диал-плана из практически одинаковых кусков:

  • запрос данных и передача в наш cgi-скрипт который возвращает из wav текстовую строку ( WebVariables )
  • проверка введенных пользователем данных ( GotoIF )
  • повтор введенных данных ( RoboText )
  • подтверждение данных голосом ( WebVariables )

То есть для каждого показателя мы делаем:

  • запрос данных ( запись звукового файла ).
  • передача файла на веб сервер который декодирует введенные данные в текст и возвращает ответ в переменной.
  • читаем пользователю то что он ввели и просим подтвердить ввода.
  • записываем результат.

Как видно действия сильно нудные поэтому мы не стали делать все это руками а сгенерировали XML конфиг скриптом
(XVB поддерживает загрузку/выгрузку конфигурации из XML файла). Маленький кусок того что получилось:

<opt> <IVR name="0"  	EXT_NUMBER="0"  	NAME="Приветствие."  	GREET_REPEAT_CNT="1"  	GREETING="Вас приветствует портал приема показаний счетчиков."  	GREET_REPEAT_DELAY="0.00"  	NEXTEXTENSION="V5_2*0"  	TYPE="1"  	WAITEXTENSION="0"> </IVR> <IVR name="error"  	EXT_NUMBER="error"  	NAME="WEB ошибка"  	GREETING="Произошла ошибка. Попробуйте позвонить позднее."  	GREET_REPEAT_CNT="1"  	GREET_REPEAT_DELAY="0.00"  	NEXTEXTENSION="hangup"  	TYPE="1"  	WAITEXTENSION="0"> </IVR> <IVR name="V5_2*0"  	EXT_NUMBER="V5_2*0"    	NAME="счетчик вода - холодная --------------"  	GREET_REPEAT_CNT="0"  	GREET_REPEAT_DELAY="0.00"  	NEXTEXTENSION="V5_2*1"  	TYPE="1"  	WAITEXTENSION="0"> </IVR> <IVR name="V5_2*1"    	EXT_NUMBER="V5_2*1"    	NAME="счетчик вода - холодная / ввод цифр"  	GOTO_IF_FAIL="error"  	GREETING="Назовите показания счетчика холодной воды"   	GREET_REPEAT_DELAY="0.00"  	GREET_REPEAT_CNT="1"  	MAX_MSG_DURATION="10"  	MAX_SILENCE="2"  	NEED_VOICE="1"  	NEXTEXTENSION="V5_2*2"  	TYPE="20"  	WAITEXTENSION="0"  	WEBVAR_URL="http://localhost/cgi-bin/gv.pl?lang=ru&file=% VAR:FILE_DATA %&var=ASR_RESULTV5_2"> </IVR> <IVR name="V5_2*2"    	EXT_NUMBER="V5_2*2"    	NAME="счетчик вода - холодная / проверка ввода"  	GREET_REPEAT_CNT="0"  	GREET_REPEAT_DELAY="0.00"  	NEXTEXTENSION="V5_2*3"  	TYPE="21"  	WAITEXTENSION="0"> 	<_VB_DATA COND="==" FUNC="strlen" PRIORITY="5" REDIRECT_TO="V5_2*2*1" VAR_NAME="ASR_RESULTV5_2" VAR_VALUE="0"/> </IVR> <IVR name="V5_2*2*1"  	EXT_NUMBER="V5_2*2*1"  	NAME="счетчик вода - холодная / ошибка ввода"  	GREETING="Мы не распознали ваш ввод, пожалуйста повторите еще раз."  	GREET_REPEAT_CNT="1"  	GREET_REPEAT_DELAY="0.00"  	NEXTEXTENSION="V5_2*1"  	TYPE="1"  	WAITEXTENSION="0"> </IVR> <IVR name="V5_2*3"    	EXT_NUMBER="V5_2*3"    	NAME="счетчик вода - холодная / чтение ввода"  	GREETING="Вы ввели"  	GREET_REPEAT_CNT="1"  	GREET_REPEAT_DELAY="0.00"  	NEXTEXTENSION="V5_2*4"  	SAY_PATTERN="char"  	SAY_PATTERN_ID="0"  	TEXT_STR="% VAR:ASR_RESULTV5_2 %"  	TYPE="25"  	WAITEXTENSION="0"> </IVR> <IVR name="V5_2*4"    	EXT_NUMBER="V5_2*4"    	NAME="счетчик вода - холодная / подтверждение"  	GOTO_IF_FAIL="error"  	GREETING="Подтвердите, сказав Да иилии Нет."  	GREET_REPEAT_DELAY="0.00"  	GREET_REPEAT_CNT="1"  	MAX_MSG_DURATION="3"  	MAX_SILENCE="2"  	NEED_PARAMS="0"  	NEED_VOICE="1"  	NEXTEXTENSION="V5_2*4*1"  	TYPE="20"  	WAITEXTENSION="0"  	WEBVAR_URL="http://localhost/cgi-bin/gv.pl?lang=ru&file=% VAR:FILE_DATA %"> </IVR> <IVR name="V5_2*4*1"  	EXT_NUMBER="V5_2*4*1"  	NAME="счетчик вода - холодная / проверка подтверждения"  	GREET_REPEAT_CNT="0"  	GREET_REPEAT_DELAY="0.00"  	NEXTEXTENSION="V5_2*3"  	TYPE="21"  	WAITEXTENSION="0"> 	<_VB_DATA COND="==" FUNC="value" PRIORITY="5" REDIRECT_TO="V5_2*0" VAR_NAME="ASR_RESULT" VAR_VALUE="да"/> 	<_VB_DATA COND="==" FUNC="value" PRIORITY="5" REDIRECT_TO="V5_2*1" VAR_NAME="ASR_RESULT" VAR_VALUE="нет"/> </IVR> <IVR name="V5_3*9"    	EXT_NUMBER="V5_3*9"    	NAME="счетчик вода - горячая / Сохранение"  	GREET_REPEAT_CNT="0"  	GREET_REPEAT_DELAY="0.00"  	NEXTEXTENSION="V5_3*9*1"  	TYPE="6"  	WAITEXTENSION="0"  	QUIET_MODE="1"  	GOTO_IF_FAIL="error"  	TTS_URL="http://127.0.0.1/cgi-bin/commit.pl?level=V5_3&account=% VAR:ASR_RESULTV1 %&value1=% VAR:ASR_RESULTV5_1 %&value2=% VAR:ASR_RESULTV5_2 %&value3=% VAR:ASR_RESULTV5_3 %"> </IVR> <IVR name="V5_3*9*1"  	EXT_NUMBER="V5_3*9*1"  	NAME="-----------------------"  	GREET_REPEAT_CNT="1"  	GREETING="Ваши показания сохранены. Спасибо. Если хотите выберите другой тип счетчика сейчас."  	GREET_REPEAT_DELAY="0.00"  	NEXTEXTENSION="0"  	TYPE="1"  	WAITEXTENSION="0"> </IVR> </opt>  

Можно сохранить выше приведенный конфиг в xxx.xml и залить в профиле пользователя через пункт восстановления конфигурации.

В вебе, в итоге у нас получилось, что то похожее на:

Собственно простейший рабочий прототип для сбора показаний голосом и через DTMF ( возможность организации самообслуживания вводом DTMF в
VirtualPBX есть из коробки поэтому я не стал здесь это подробно описывать ) готов. Сейчас шлифуем свои скрипты и пишем нормальные звуковые приветствия.

Если кому интересно как оно распознает ( а распознает оно по разному ) то:

  • Через скайп: skype: tsg812
  • Через VoIP: tel:+1 253-243-1337
  • Через dongle: tel: +7 987 391 6412

Донгл и скайп пока в фоваритах по качеству, к ТфОп пока не прикручивали.

P.S. Посмотрим сколько народу предпочтет голос DTMF’у, для меня DTMF вроде проще ( привычнее ) и быстрее если есть возможность ввести через DTMF.

ссылка на оригинал статьи http://habrahabr.ru/post/188382/

В космос через смартфон

Оснащенный тремя антеннами советский телевизор «Б-2» пролетает над Хабаровском (на самом деле нет)

Мечтали управлять спутником на орбите через приложение в телефоне?

Инвестиционные фонды очень консервативны и не любят вкладывать средства в новые технологии. Предложите им интересный проект из области образования, медицины, транспорта, развлечений или бытовой техники, а потом поясните, что это нечто новое, не апробированный продукт. Инвестор убежит, размахивая в ужасе руками. Однако за гранью привычного взгляда на мир всегда находится пространство уникальных возможностей. Инвестиционный фонд Grishin Robotics, созданный сооснователем и генеральным директором Mail.Ru Group Дмитрием Гришиным, внезапно вышел за рамки шаблонных моделей и профинансировал компанию NanoSatisfi, предоставляющую доступ к перепрограммированию орбитальных наноспутников в онлайн-режиме.

Не так давно производство и запуск спутников стоило миллионы долларов. Только действительно крупные компании могли позволить себе начать инвестировать в область спутниковых технологий. Снижение издержек, появление надежных и производительных смартфонов, привело к тому, что стоимость коммерческого спутника упала до нескольких тысяч долларов. Сейчас наноспутник – килограммовый смартфон в формате CubeSat.

Согласно прогнозам, количество запусков наноспутников в 2020 году почти удвоится по сравнению с 2013 годом. Фактически перед нами поезд новой индустрии, вот-вот готовый стартовать с вокзала. Компания NanoSatisfi стремится запрыгнуть на подножку, а в перспективе – возглавить состав стремящегося в будущее рынка. Компания приготовила к запуску два наноспутника, а на 2014 год планирует организовать к ним доступ для более чем 25 тысяч человек.

NanoSatisfi разрабатывает веб-сервис, через который можно будет получить прямой доступ к спутникам, а открытое API позволит независимым разработчикам принять участие в разработки приложений. От недобросовестного хака предусмотрена следующая защита: сначала код прогонят через дубликат спутника в офисе компании.

На борту есть камера высокого разрешения, спектрометр, магнетометр, счётчик Гейгера и ещё пара десятков приборов – всё это позволит собирать данные, полезные, к примеру, авиалиниям или добытчикам полезных ископаемых. Да и просто любопытство можно будет удовлетворить почти каждому: доступ к спутнику будет открыт за 250 $ в неделю.

Помимо орбитальных экспериментов, любой желающий сможет получить фотографии Земли. Для этого достаточно будет выбрать через приложение тот участок планеты, над которым пролетает спутник, и в нужный момент аппарат сделает снимок, после чего перешлет вам вид планеты на электронную почту (вам тоже интересно, какой у спутника будет адрес?).

Проект собирал деньги через Kickstarter, но финансирования не хватило. Теперь Grishin Robotics предоставили 300 000 $. Логика: наноспутники – это продолжение тренда общемирового расширения рынка персональной робототехники. Сам владелец, Дмитрий Гришин, планирует инвестировать в разработку персональной робототехники $25 млн. В космосе робот или у вас в офисе – не важно, ведь он повторяет путь развития компьютеров в целом. Радикальное снижение стоимости сделает технологию невероятно доступной уже в ближайшие годы.

ссылка на оригинал статьи http://habrahabr.ru/post/188542/

Есть ли у вас SSD на рабочем компьютере?

В продолжение топика Обоснование необходимости приобретения SSD для разработчиков я решил добавить просто опрос. К сожалению, мне не удалось добавить опрос в оригинальный топик (может быть ограничение песочницы). Комментарии просьба оставлять в том топике. Целевая аудитория — разработчики, дизайнеры, моделисты, для кого дисковая подсистема важна.

Есть ли у вас SSD на рабочем компьютере?

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Проголосовало 6 человек. Воздержалось 3 человека.

ссылка на оригинал статьи http://habrahabr.ru/post/188538/

С Новым Марсианским Годом!

Сегодня, 31 июля 2013 года, 31й марсианский год сменяется новым 32м годом. Поскольку марсианский год (668 земных суток) почти в два раза дольше земного, это довольно таки особое событие. Хороший повод, чтобы устроить праздник!

Марсианское летоисчисление берет свое начало 11го апреля 1955 года (К сожалению, не смог нагуглить почему за точку отсчета была принята именно эта дата. Если кто-нибудь знает, буду благодарен за информацию). С тех пор, момент, когда Марс совершает полный оборот вокруг Солнца, сместился для нас с апреля на июль. Он будет продолжать смещаться и дальше, поскольку марсианский год равен не полным двум годам. Чтобы дать вам представление, вашему покорному слуге сейчас 24 года, что по марсианскому летоисчислению немногим больше 13ти лет.

В отличие от Земли, на Марсе Новый Год наступает, когда в Северном Полушарии весна, а в Южном осень. В Южном Полушарии дни становятся все короче по мере приближения зимы.

С Новым Годом, друзья!

ссылка на оригинал статьи http://habrahabr.ru/post/188526/

Особенности игрового рынка в Китае — часть 1

Китай невероятно похож на Россию — пришли мы к выводу с Алленом Фу, руководителем подразделения Unity Technologies в Китае, после долгой беседы. Оказывается за 18 месяцев работы китайского офиса Юнити, Аллен встретился с теми же самыми культурными, историческими, национальными особенностями ведения бизнеса, с которыми команда Юнити встречается в России.

«Россия в сердце китайцев является частью общей истории. Я думаю наши страны должны намного больше общаться», — размышляет Ксин Жанг, отвечающий за техническую поддержку пользователей Юнити в Китае. Он очень удивлен, почему Юнити до сих пор не открыла офис в России и не предоставляет техническую поддержку пользователей на русском языке…

Впрочем, приоритеты в играх у России и Китая отличаются очень сильно.

«Новый удивительный мир, который не складывается с моим западным ходом мысли», — удивлялся я снова и снова, рассматривая популярные игры, обсуждая тренды, увлечения молодежи, современных и классических героев. «Нет, нет, нет, китайцам это не интересно», — получал я ответ, показывая популярные западные игры на iOS и Android.

CSR Racing — китайцев не интересуют дорогие автомобили. И вообще, гонки — это плохо и никому не интересно. The Room — там надо много думать, и вообще ты едешь в метро и тебя трясет, поэтому все с акселерометром — плохо. Античные герои, культурные ценности Европы, западные модные тренды, телешоу — все плохо. Hidden object — тоже плохо! Китайские HOB’ы — это когда на фоне с однородной заливкой разбросаны не пересекающиеся предметы, и есть указание вроде «это может летать», твоя задача — догадаться, что это привидение, самолет… (в русской версии ту же были бы еж и птица киви).

А вот в этой игре надо покупать оружие и убивать рыбок, которые не очень то от тебя убегают. Смысл игры убить больше рыбок, для этого надо покупать лучшее оружие за настоящие юани. Мне Curiosity Мулинье напомнило…

За эти пять дней с нашим издательским направлением в Шанхае образ успешной игры у меня нарисовался примерно следующий:

  • Раннер
  • Паззл
  • Файтинг
  • Карточная игра
  • Аркадный платформер
  • Простая механика с минимальным барьером входа
  • Про милых животных
  • Про китайскую культуру
  • Бесплатная игра с очень жестокой монетизацией
  • Высокий контраст, яркие цвета, минимум деталей
  • Должно выглядеть хорошо на 800х480 при 65К цветов

Unity Games China работает напрямую с местными провайдерами контента (Google Play тут отсутствует) — отсюда знание и понимание рынка. Мы отдаем apk с игрой (в Китае верят только в Андроид) партнеру (оператору связи или платформодержателю), а он возвращает пожелания по локализации _и_ адаптации игры.

Сам процесс выпуска игры на Китайский рынок через нашего паблишера Unity Games China я опишу в следующей части.

Впечатления про ChinaJoy и Шанхай я оставил в своем блоге (на инглише…).

ссылка на оригинал статьи http://habrahabr.ru/company/unity3d/blog/188472/