В этом руководстве показано, как использовать программу Python и API Twilio для набора телефонных звонков.
Старомодные добрые телефонные звонки остаются одним из лучших способов общения несмотря на множество новых приложений для смартфонов, появившихся в прошлом несколько лет. Всего несколько строк кода Python плюс интерфейс программирования веб-приложений мы можем совершать и принимать телефонные звонки из любого приложения.
В нашем примере вызовы будут произносить фрагмент текста и помещать всех входящих вызовов в записанную конференц-связь. Вы можете изменить инструкции, используя Twilio-глаголы TwiML , когда вы выполнять различные действия в телефонных звонках вашего собственного приложения.
Наши инструменты
У вас должен быть установлен Python 2 или 3 для построить это приложение. В этом посте мы также будем использовать:
- pip и
- virtualenv для обработки
- зависимости приложений
- Бесплатная учетная запись Twilio для использования своих
- веб-API телефонных звонков
- Twilio’s
- вспомогательная библиотека Python ,
- версия 5.7.0, которая
- доступно на PyPI
Вы можете найти весь открытый исходный код для этого руководства в python-twilio-example-apps Репозиторий GitHub под Каталог no-framework/phone-calls . Используйте и скопируйте код для своих собственных приложений. Все в этом репозиторий и в этом сообщении в блоге имеют открытый исходный код под лицензией MIT.
КАК ПОЗВОНИТЬ С КОМПЬЮТЕРА НА ТЕЛЕФОН? ЗВОНКИ ОНЛАЙН БЕСПЛАТНО!
Установить зависимости приложений
Наше приложение будет использовать Twilio вспомогательная библиотека Python для создания запроса HTTP POST к API Twilio. Вспомогательная библиотека Twilio можно установить из PyPI в виртуальный окружающая обстановка. Откройте свой терминал и используйте команду virtualenv для создания новый virtualenv:
virtualenv phoneapp
Вызовите сценарий activate в каталоге virtualenv bin/ , чтобы this virtualenv активный исполняемый файл Python. Обратите внимание, что вам нужно будет выполните этот шаг в каждом окне терминала, которое вы хотите, чтобы virtualenv быть активным.
source phoneapp/bin/activate
Командная строка изменится после активации virtualenv на что-то вроде (phoneapp) $ .
Затем используйте команду pip , чтобы установить Пакет Twilio Python в virtualenv.
pip install twilio==5.7.0
Необходимая зависимость будет готова для проекта, как только установка скрипта завершена. Теперь мы можем писать и выполнять код Python для набирать телефонные номера.
Наш скрипт Python
Создайте новый файл с именем phone_calls.py и скопируйте или введите следующий строки кода.
from twilio.rest import TwilioRestClient # Twilio phone number goes here. Grab one at https://twilio.com/try-twilio # and use the E.164 format, for example: «+12025551234» TWILIO_PHONE_NUMBER = «» # list of one or more phone numbers to dial, in «+19732644210» format DIAL_NUMBERS = [«»,] # URL location of TwiML instructions for how to handle the phone call TWIML_INSTRUCTIONS_URL = «http://static.fullstackpython.com/phone-calls-python.xml» # replace the placeholder values with your Account SID and Auth Token # found on the Twilio Console: https://www.twilio.com/console client = TwilioRestClient(«ACxxxxxxxxxx», «yyyyyyyyyy») def dial_numbers(numbers_list): «»»Dials one or more phone numbers from a Twilio phone number.»»» for number in numbers_list: print(«Dialing » + number) # set the method to «GET» from default POST because Amazon S3 only # serves GET requests on files.
Typically POST would be used for apps client.calls.create(to=number, from_=TWILIO_PHONE_NUMBER, url=TWIML_INSTRUCTIONS_URL, method=»GET») if __name__ == «__main__»: dial_numbers(DIAL_NUMBERS)
Как создать виртуальный номер для звонков и смс?
Есть несколько строк, которые вам нужно изменить в этом приложении, прежде чем оно будет работать. Сначала введите один или несколько телефонных номеров, по которым вы хотите позвонить, в Список DIAL_NUMBERS. Каждый должен быть строкой, разделенной запятой. За например, DIAL_NUMBERS = [«+12025551234», «+14155559876», «+19735551234»] .
Затем TWILIO_PHONE_NUMBER , SID учетной записи и токен аутентификации, найдено в client = TwilioRestClient («ACxxxxxxxxxx», «yyyyyyyyyy») линия, необходимо установить. Мы можем получить эти значения из Twilio Console .
В вашем веб-браузере перейдите на на веб-сайте Twilio и зарегистрируйтесь для получения бесплатной учетной записи или войдите в свою существующую учетную запись Twilio.
Скопируйте SID учетной записи и токен аутентификации из консоли Twilio и вставьте их. в код вашего приложения:
Пробная учетная запись Twilio позволяет набирать и принимать телефонные звонки на ваш собственный подтвержденный номер телефона. Для обработки звонков с любого телефона номер, то вам нужно обновить свою учетную запись (нажмите кнопку обновления на верхняя панель навигации).
После того, как вы войдете в свою учетную запись Twilio, перейдите в экран управления телефонными номерами . На этом экране вы можете купите один или несколько телефонных номеров или щелкните существующий номер телефона в своей учетной записи, чтобы настроить его.
После нажатия на номер вы попадете в конфигурацию номера телефона экран. Вставьте URL-адрес с инструкциями TwiML и измените раскрывающийся список с «HTTP POST» на «HTTP GET». В этом посте мы будем использовать http://static.fullstackpython.com/phone-calls-python.xml , но этот URL может быть больше, чем просто статический XML-файл.
Сила Twilio действительно проявляется, когда этот URL обрабатывается вашим веб-сайтом. приложение, чтобы оно могло динамически отвечать инструкциями TwiML на основе номер входящего звонящего или другие свойства, хранящиеся в вашей базе данных.
Под веб-перехватчиком Voice вставьте http://static.fullstackpython.com/phone-calls-python.xml и измените раскрывающийся список справа от «HTTP POST» до «HTTP GET». Нажмите “Сохранить” кнопку в нижней части экрана.
Теперь попробуйте позвонить на свой номер телефона. Вы должны услышать фрагмент текста прочитанный голосом Алисы, и вы будете переведены на конференц-связь. Если никто больше не набирает номер, значит, должна играть удерживаемая музыка.
Телефонные звонки
Android – телефонные звонки
Android предоставляет встроенные приложения для телефонных звонков, в некоторых случаях нам может понадобиться сделать телефонный звонок через наше приложение. Это можно легко сделать, используя неявные намерения с соответствующими действиями. Также мы можем использовать классы PhoneStateListener и TelephonyManager, чтобы отслеживать изменения в некоторых состояниях телефонии на устройстве.
В этой главе перечислены все простые шаги по созданию приложения, которое можно использовать для совершения телефонного звонка. Вы можете использовать Android Intent для совершения телефонного звонка, вызывая встроенную функцию телефонного звонка Android. В следующем разделе описаны различные части нашего объекта Intent, необходимые для совершения вызова.
Intent Object – Действие, чтобы сделать телефонный звонок
Вы будете использовать действие ACTION_CALL для запуска встроенной функции телефонного звонка, доступной на устройстве Android. Ниже приведен простой синтаксис для создания намерения с действием ACTION_CALL
Intent phoneIntent = new Intent(Intent.ACTION_CALL);
Вы можете использовать действие ACTION_DIAL вместо ACTION_CALL, в этом случае у вас будет возможность изменить кодированный телефонный номер перед совершением вызова вместо прямого вызова.
Намеренный объект – данные / тип, чтобы сделать телефонный звонок
Чтобы позвонить по указанному номеру 91-000-000-0000, необходимо указать tel: в качестве URI с помощью метода setData () следующим образом:
phoneIntent.setData(Uri.parse(«tel:91-000-000-0000»));
Интересным моментом является то, что для совершения телефонного звонка не нужно указывать какие-либо дополнительные данные или тип данных.
пример
В следующем примере показано, как на практике использовать Android Intent для звонка на указанный номер мобильного телефона.
Чтобы поэкспериментировать с этим примером, вам понадобится настоящее мобильное устройство с новейшей ОС Android, в противном случае вам придется бороться с эмулятором, который может не работать.
| 1 | Вы будете использовать IDE Android Studio для создания приложения Android и назовите его « Мое приложение» в пакете com.example.saira_000.myapplication . |
| 2 | Измените файл src / MainActivity.java и добавьте необходимый код для выполнения вызова. |
| 3 | Измените XML-файл макета. Res / layout / activity_main.xml добавьте любой компонент GUI, если это необходимо. Я добавляю простую кнопку для вызова номера 91-000-000-0000 |
| 4 | Нет необходимости определять строковые константы по умолчанию. Android-студия заботится о константах по умолчанию. |
| 5 | Измените AndroidManifest.xml, как показано ниже |
| 6 | Запустите приложение, чтобы запустить эмулятор Android, и проверьте результат изменений, внесенных в приложение. |
Ниже приводится содержимое измененного основного файла активности src / MainActivity.java .
Ниже будет содержимое файла res / values / strings.xml для определения двух новых констант:
xml version=»1.0″ encoding=»utf-8″?> name=»app_name»>My Application
Ниже приводится содержимое по умолчанию для AndroidManifest.xml –

Давайте попробуем запустить ваше приложение My Application . Я предполагаю, что вы подключили свое фактическое мобильное устройство Android к компьютеру. Чтобы запустить приложение из студии Android, откройте один из файлов деятельности вашего проекта и нажмите «Выполнить». значок на панели инструментов. Выберите мобильное устройство в качестве опции, а затем проверьте свое мобильное устройство, которое отобразит следующий экран –

Теперь используйте кнопку Call , чтобы сделать телефонный звонок, как показано ниже –
Источник: coderlessons.com
Дозвонились! Как собрать свою Web-звонилку за час

Друзья, сегодня я хочу поговорить с вами про звонки. Для кого-то это совсем новая тема. Для других — чистой воды фан на уровне «а не зафигачить ли мне свой скайп?». Для третьих — внезапно возникшая жизненная необходимость. Последний вариант — наш вариант.
В этой статье я покажу вам маленький, но очень жизнеспособный пример реализации, который позволит вам буквально на коленке из нескольких десятков строк javascript сделать собственную WEB-звонилку и позвонить другу прямо из браузера.
Про технологии и протоколы

На дворе 2019 год, и к нашей радости уже есть готовый инструмент для реализации Real-Time Communication (RTC) для веба, а именно WebRTC. Еще несколько лет назад он был в активной разработке. API до сих пор дорабатывается, но технология де-факто стала стандартом и поддерживается в большинстве популярных браузеров. В этой статье на самой технологии мы останавливаться не будем, можно подробнее почитать на сайте разработчиков или поискать статьи на хабре. Например, вот тут.
Но прежде, чем мы начнём, хочу прояснить пару моментов.
- Во первых, WebRTC работает поверх пачки протоколов, и даже для p2p взаимодействия вам понадобится какой-то сервер, через который ваши клиенты смогут друг друга найти и подружиться. Наш же пример будет использовать SIP протокол, о котором можно почитать подробнее, скажем, тут.
- Вам понадобится сервер с поддержкой всего вышеперечисленного добра — вроде FreeSwitch или Asterisk.
Эти штуки оставляем за рамками статьи. Будем считать, что вам повезло так же, как нам, и в распоряжении уже имеется настроенная VoIP телефония.
Ну что, самая длинная часть статьи позади, давайте кодить!
Верстаем страничку

Для начала нам понадобится страничка, с которой мы будем звонить, поля для ввода логина, пароля, номера телефона и пара кнопок. В простейшем варианте выглядеть будет примерно так:
Login Password Login LogOut Call Hang Up
Аудиоэлементы будут «отправлять» и «принимать» звук, ну и для красоты через sounds проигрывать звуки дозвона.
UI готов, к UX не придерешься, давайте заставим его работать.
Прикручиваем JSSIP

Воспользуемся библиотекой, в которой уже реализовано всё, что требуется, — JSSIP. Можно посмотреть документацию: там всё довольно подробно описано и есть даже готовый пример реализации. То есть нам практически ничего не нужно делать — лишь всё максимально упростить и разобраться, что к чему.
После ввода логина/пароля (должны быть зарегистрированы на вашем сервере телефонии) нужно залогиниться на сервере. Делаем так:
Попутно можно подписаться на события connecting и connected и сделать там что-то полезное. Но перейдём сразу к событию регистрации:
his._ua.on(‘registered’, () => < console.log(«UA registered»); this.loginButton.addClass(‘d-none’); this.logOutButton.removeClass(‘d-none’); this.loginText.prop(‘disabled’, true); this.passwordText.prop(‘disabled’, true); $(«#callPanel»).removeClass(‘d-none’); >);
Тут нам просто нужно поменять статусы кнопочек: показать нужное, скрыть ненужное. И если вдруг что-то пошло не так с логином, плюнем ошибку в лог:
this._ua.on(‘registrationFailed’, (data) => < console.error(«UA registrationFailed», data.cause); >);
Этого достаточно для логина. Осталось завести шарманку с помощью
this._ua.start();
Если сервер указан правильно и ваш логин/пароль им приняты — появится поле для ввода телефона и кнопка Call.
Для разлогина нужно вызвать this._ua.stop(), всё просто.
Делаем звонок
Теперь — самое главное: нужно позвонить на введённый номер.
this.session = this._ua.call(number, < pcConfig: < hackStripTcp: true, // Важно для хрома, чтоб он не тупил при звонке rtcpMuxPolicy: ‘negotiate’, // Важно для хрома, чтоб работал multiplexing. Эту штуку обязательно нужно включить на астере. iceServers: [] >, mediaConstraints: < audio: true, // Поддерживаем только аудио video: false >, rtcOfferConstraints: < offerToReceiveAudio: 1, // Принимаем только аудио offerToReceiveVideo: 0 >>);
Обратите внимание: мы явно включаем мультиплексирование, эту настройку нужно включить и на вашем сервере. В случае астериска это rtcp_mux=yes в настройках sip.conf.
Дальнейшее взаимодействие строится на колбэках, в которых мы должны обеспечить направление аудио-видео потока в соответствующий элемент страницы и послать нужные сообщения в правильном порядке на сервер.
// В процессе дозвона this.session.on(‘progress’, () => < console.log(«UA session progress»); playSound(«ringback.ogg», true); >); // Астер нас соединил с абонентом this.session.on(‘connecting’, () => < console.log(«UA session connecting»); playSound(«ringback.ogg», true); // Тут мы подключаемся к микрофону и цепляем к нему поток, который пойдёт в астер let peerconnection = this.session.connection; let localStream = peerconnection.getLocalStreams()[0]; // Handle local stream if (localStream) < // Clone local stream this._localClonedStream = localStream.clone(); console.log(‘UA set local stream’); let localAudioControl = document.getElementById(«localAudio»); localAudioControl.srcObject = this._localClonedStream; >// Как только астер отдаст нам поток абонента, мы его засунем к себе в наушники peerconnection.addEventListener(‘addstream’, (event) => < console.log(«UA session addstream»); let remoteAudioControl = document.getElementById(«remoteAudio»); remoteAudioControl.srcObject = event.stream; >); >); // Дозвон завершился неудачно, например, абонент сбросил звонок this.session.on(‘failed’, (data) => < console.log(«UA session failed»); stopSound(«ringback.ogg»); playSound(«rejected.mp3», false); this.callButton.removeClass(‘d-none’); this.hangUpButton.addClass(‘d-none’); >); // Поговорили, разбежались this.session.on(‘ended’, () => < console.log(«UA session ended»); playSound(«rejected.mp3», false); JsSIP.Utils.closeMediaStream(this._localClonedStream); this.callButton.removeClass(‘d-none’); this.hangUpButton.addClass(‘d-none’); >); // Звонок принят, можно начинать говорить this.session.on(‘accepted’, () => < console.log(«UA session accepted»); stopSound(«ringback.ogg»); playSound(«answered.mp3», false); >);
В общем, всё довольно логично. Пока дозваниваемся [‘progress’] — играем звуки дозвона. В нашем примере мы играем свой звук, но как справедливо заметил pvsur, его можно так же получить с вызываемой стороны и услышать ответ автоинформатора вида «оставьте сообщение после звукового сигнала», если он будет.
Как только дозвонились [‘accepted’] — играем звук answered. Как только абонент снимет трубку, мы получим его звуковой поток и засунем его в элемент remoteAudio [‘connecting’ и ‘addstream’].
В конце звонка делаем closeMediaStream. Можно расслабиться.
Немного про эксплуатацию
При тестировании были обнаружены две вещи.
- В хроме в начале дозвона была задержка на несколько секунд, что сильно раздражало. По логам выяснили, что он ходил на ice сервера, что совершенно не требовалось, так как сервер у нас свой. Поэтому в конфиге для JSSIP мы их просто убрали, и сразу похорошело. Смотри pcConfig.iceServers и pcConfig.hackStripTcp.
- На нашем астериске настроен WSS протокол с шифрованием для SIP. Этого требует браузер при использовании на сайте HTTPS. Но астериск использует WS, основываясь на параметрах контакта, в которых библиотека JSSIP содержит захардкоженный дескриптор WS. Разработчики библиотеки при этом указывают на стандарты, в которых действительно нет никаких требований по этому поводу. А коллеги из астера упорно не хотят ничего исправлять. В общем, тупик. Ну а мы в это время находим в исходниках строку this._configuration.contact_uri = new URI(. ), меняем transport: ‘ws’ на transport: ‘wss’ и продолжаем радоваться жизни.
В целом пример готов, можно брать и звонить. Не нужно ставить никаких софтфонов или разрабатывать свои. Не нужно париться с деплоем этого софта на клиентские тачки. Просто открываем браузер и звоним.
Еще библиотека позволяет набирать дополнительные номера в тоновом режиме. То есть вы вполне можете позвонить, например, в колл-центр банка и добраться до нужного пункта по голосовому меню. Для этого достаточно выполнить такую команду:
this._call.sendDTMF(‘доп. номер’)
Про факапы

Было несколько моментов, которые реально заставили понервничать.
Я оставил эту часть за рамками статьи, но помимо исходящих вызовов нам требовалось и входящие принимать. И какое-то время пришлось приседать со входящим звонком, который приходил и тут же обрывался. Всё решилось уже упомянутой выше настройкой rtcpMuxPolicy и включением мультиплексирования на астериске, но тупили мы довольно долго.
И еще есть проблемы с дозвоном самому себе — когда вызов и прием звонка делаются на одной машине. Уже точно не помню, но соединение успешно устанавливалось, ошибок не было и звука тоже:) Время поджимало, так что мы на этот спецэффект забили. Но имейте в виду, что тестить входящие звонки лучше на отдельной тачке.
Напоследок хочется отметить, что работу связки JSSIP + Asterisk мы протестировали на своём колл-центре, всё работает отлично, по крайней мере в хроме, что нас полностью устраивает. Главное — разрешить браузеру доступ к медиа-устройствам и зарегистрировать пользователей на сервере звонилки.
Готовый пример можно посмотреть на гитхабе.
Источник: habr.com