Міграція сервісу віртуальних компаньйонок на WebRTC

Це історія одного проекту відеострімінгу.

image

Цікавий клієнт
Я сидів перед монітором вже цілу годину, а може і два. Все почалося з посилання на чийсь твіттер, яку колега люб'язно закинув мені в скайп. Потім випадково відкрив новинний сайт, потім Facebook, за цей час встигла з'явитися ще пара новин… загалом, спина вже затерпла і пора було піти розім'ятися. В офісі було прохолодно, тихо працювали кондиціонери. Виходити на вуличну спеку зовсім не хотілося і, разогнувшись, я дошкандибав до найближчого кавового автомата. Десь на ресепшені продзвенів дзвоник.

Через пару хвилин я побачив Ольгу, що супроводжує джентльмена азіатської зовнішності. На вигляд йому було близько п'ятдесяти. На злегка зморшкуватою голові сиділа сіра капелюх з короткими полями. Вони явно йшли до мене. Порівнявшись з кавовим автоматом, який вже дзюрчав у стаканчик моїм капучіно, джентельмен виголосив ламаною російською: Здраствуйте, я відносний проекту WebRTC. Моя звуть Суконако, і простягнув руку. Що привело сюди цього японця, подумав я, відповівши на потиск, і запросив гостя до свого кабінету. Далі нам довелося перейти на англійську мову, який нам обом був більш зрозумілий.

Збираємо вимоги
Я: Отже, чим можу бути корисний?

З: Ми працюємо з 2000 року в стриминге і Flex для великої кількості користувачів. Ми використовуємо Adobe Flash Media Server (FMS) і зараз хотіли б використовувати WebRTC.

Я: Можна детальніше про те, чого ви хотіли б досягти використанням WebRTC-сервера?

З: Нам потрібно звичайний медіасервер, який може приймати відеопотоки від одного користувача і передавати їх іншим користувачам. Ми хочемо відеочат.

Я: Без проблем, ми можемо зробити рішення на базі одного з WebRTC-серверів.

З: Adobe FMS нас повністю влаштовує. Ми хотіли б розширити коло наших користувачів на WebRTC, не прибираючи FMS. Він працює добре.

В руках Суконако з'явився планшет, він посунув його мені і ткнув пальцем в наступну схему:

image

C: Flex App – це доктор, Flex Apps – це пацієнти, доктор використовує веб-камеру і консультує відразу декількох пацієнтів. Один з пацієнтів може запитати у лікаря приватну консультацію, і тоді доктор залишається один на один для приватної консультації з пацієнтом. У цей момент інші пацієнти не можуть спілкуватися з доктором і не бачать його.

image

Дивно, подумав я. Про що доктор може одночасно консультувати пацієнтів. Один бідкається про те, що болить вухо, другий нарікає на гланди, потім той, що з гландами натискає на кнопку і переходить в режим приватної консультації. Однак принцип зрозумілий. Зосередимося на технічній стороні питання.

image

Я: тобто в результаті встановлюється двосторонній відеозв'язок доктора і пацієнта?

З: Не зовсім. Пацієнт завжди бачить доктора, але доктор не може бачити пацієнта. За замовчуванням відео пацієнта вимкнено.

Я: Значить відео одностороннє – від лікаря до пацієнта?

З: У більшості випадків-так. Але іноді пацієнти бажають показати своє відео лікаря. Це трапляється нечасто.

Я: Все зрозуміло. Значить потрібно щоб і лікар і пацієнт могли використовувати WebRTC-браузер, наприклад Firefox або Google Chrome, а також IE, який буде працювати через FMS. Вірно?

З: Майже так. Всі лікарі використовують розроблене нами стрімінг-додаток на Flex. Пацієнти ж повинні використовувати наш додаток або WebRTC.

Я: тобто в ідеалі, ваш додаток має виглядати так?

І накидав схему.

image

З: Так, вірно. Це повинно працювати саме так. З одного боку нативне Flex-додаток, а з іншого WebRTC-браузер. Нас цікавлять насамперед браузери на Android-смартфонах і iOS-пристроях. Вам напевно відомо, що Flash так чи інакше присутня на всіх десктопних браузерами: IE, Chrome, Firefox, Safari, але його немає на Android і iOS. Ми хотіли б зробити наш сервіс доступним на мобільних браузерах і зберегти те, що працює добре на десктопах, тобто FMS.

Я: На Android-браузерах WebRTC буде працювати, а на iOS з цим проблема – WebRTC в iOS-браузерах не працює із-за обмежень платформи. Тобто ми не зможемо доставити WebRTC відеопотік на iOS і не можемо стримить відео з вебкамери iOS-браузера.

C: Стривайте, мені відомо що Safari не підтримує WebRTC, але його підтримка є Google Chrome.

Я: Так, але не у випадку iOS. Там Chrome натикається на технічні обмеження платформи і не має таких можливостей роботи з WebRTC-відео, як на десктопі. Тобто iOS браузер в даному випадку не підходить. Чому б вам не вивантажити власний додаток в Apple App Store? Тоді користувачам iOS потрібно буде лише встановити додаток і використовувати чистий WebRTC, той, що використовується в Google Chrome?

З: На жаль, ми не можемо вивантажити додаток в App Store з внутрішніх причин. Крім цього, ми хотіли б дати нашим користувачам (пацієнтам) можливість не встановлювати додаткових додатків на вашому iPhone або iPad, а працювати прямо з браузера. Які у нас є варіанти?

У цей момент я подумав, про «внутрішні причини», які не дозволяють опублікувати додаток в App Store. Можливо область медичних консультацій регулюється законодавством, і це дійсно не так просто, викотити в App Store додаток такого роду.

Варіантів насправді було не багато і кращим із них було нативне додаток з підтримкою WebRTC. iOS Safari, як відомо підтримує HLS (Apple HTTP Live Streaming), але цей варіант був відкинутий, тому що в спілкуванні лікаря з пацієнтом передбачався певний реалтайм і живе спілкування, для якого HLS абсолютно не підходить при затримці близько 20 секунд.

Залишався останній варіант: вебсокеты. Websockets зараз підтримується майже у всіх браузерах – це фактично TCP-канал, по якому можна доставити відео з затримкою порівнянної з RTMP, т. е 3 секунди, а не 20. З доставкою зрозуміло. Ще б відтворити цей потік <video/> HTML5 елементі і було б все чудово.

Я: Варіант, схоже, лише один – вебсокеты. Причому в цьому випадку пацієнти не зможуть надіслати своє відео на сервер. Можлива лише одностороння доставка від лікаря до пацієнта. Можна спробувати HLS, але там затримка більше 20 секунд і ймовірно вам не підійде.

З: Добре. Чи Правильно я зрозумів, що ми зможемо грати живі потоки з FMS прямо на iOS браузері Safari? Нехай без WebRTC, але з невеликою затримкою, порівнянної з RTMP?

Я: Так, абсолютно вірно. Але нам потрібно деякий час це перевірити. Давайте домовимося, скажімо на понеділок, і я покажу вам демо.

З: Мені б хотілося побачити можливість інтеграції FMS одночасно з WebRTC і з Websockets, щоб бути впевненим, що це буде працювати на iOS та Android. Можливо так зробити?

Я: Так, думаю все вийде.

З: Дякую за консультацію. У понеділок зайду в 10, якщо не заперечуєте і обговоримо всі питання, вже маючи демо.

Я: Так, звичайно, до цього часу все буде готово.

Шукаємо рішення
Як видно з розмови, вимоги трохи змінилися і тепер належало прикрутити до Adobe AMS два способи доставки: WebRTC для браузерів на Android і Websockets для браузера Safari під iOS. Залишилося знайти відсутній елемент, який дозволить побудувати це демо і зв'язати всі беруть участь в ньому технології та протоколи.

image

Провівши японського гостя, я першим ділом поїхав дивитися специфікацію Adobe AMS. Знайшов у ній багато цікавого, крім слів WebRTC і Websocket.

Далі, не довго думаючи, забив в Гугл три потрібних кейворда: rtmp, webrtc і websockets. Гугл виплюнув кілька релевантних сайтів. Придатними, як виявилося, були всього два: пропрієтарний проект Flashphoner і опис опенсорсного прототипу з сайту Phoboslab

image

Перший кандидат
Почати вирішив з Phoboslab, де була у всіх фарбах описана проблема відтворення стріму в iOS Safari і пропонувалося рішення, дуже схоже на опенсорсное.

Рішення будується на ffmpeg, node.js та клієнтський javascript для декодування і відтворення відеопотоку. Всі компоненти були дійсно опенсорсные і схема виглядала багатообіцяючою.

Я підняв віртуальний сервер DO, зібрав ffmpeg і встановив node.js. Все це зайняло близько двох годин.

image

Відео в iOS Safari дійсно грало, і грало не погано. Мій iPhone5 злегка грівся, але JavaScript стабільно лопатил відеотрафік з Websocket і показував його на web-сторінці.

Фактично відбувалося декодування стріму на JavaScript і подальша побудова в елементі сторінки браузера iOS Safari. Залишалися відкритими такі питання:

— Як забрати стрім з FMS
— Як додати до стриму звук
— Що щодо WebRTC

І тут мене чекало деяке розчарування. Виявилося, що JavaScript-плеєр грає (малює) тільки відео. Для аудіо довелося б пускати додатковий потік, після чого їх потрібно синхронізувати. Але дане рішення цього не передбачала. Таким чином, дане рішення не підходило для передачі відео від лікаря з-за відсутності звуку.

Другий кандидат
Наступним піддослідним було Web Call Server з обіцяної підтримкою RTMP, WebRTC, Websocket протоколів. Залишилося перевірити, чи застосовна підтримка даних протоколів в моєму конкретному випадку і як це працює.

Першим ділом вирішив перевірити конвертацію RTMP відеопотоку в Websocket, за аналогією з попереднім тестом. Адже якщо це вдасться зробити, то далі можна перенаправити RTMP потік з FMS на Web Call Server і тим самим вирішити одну із задач.

image

Я озброївся iPhone-ом і відкрив одну з демо-сторінок, де пропонувалося спробувати зробити це з демо-сервера. За запевненням техпідтримки, Web Call Server можна швидко встановити на свою Linux-систему, але це зайняло б деякий час, а демо давало можливість відразу зрозуміти працює це чи ні.

Демо-інтерфейс представляв собою звичайне Flash-додаток з непоказним дизайном і простим функціоналом, під назвою Flash Streaming.

image

З цього Flash додатки можна підключитися до сервера по протоколу RTMP і опублікувати стрім з веб-камери. Опублікувати (Publish) – значить захопити відео з веб-камери браузера за допомогою Flash Player і відправити дані на сервер в реальному часі по протоколу RTMP.

Судячи по статусах 'Connected' і 'Publishing', з'єднання було успішно встановлено та стрім з веб-камери вирушав на сервер. Щоб не світити в стриме своїм фейсом, я використовував віртуальну камеру і серію з п'ятого (?) сезону Game of Thrones.

Далі залишилося побачити і почути це відео на iPhone в браузері Safari. Для цього рекомендувалося використовувати окремий плеєр під назвою WS Player Minimal.

image

На плеєрі вдалося отримати пристойну картинку і звук без спотворень або рассинхрона.

Мабуть, я досяг певного прогресу у своєму ресерче:

  • Вдалося протестувати доставку стріму RTMP-Websocket
  • Стрим був зі звуком і відео і коректно відображався на браузері Safari
Залишилося перевірити грає стрім в WebRTC і можна було переходити до інтеграції з Adobe FMS. Для перевірки цього ж стріму c WebRTC, я відкрив демо Streamer Player And Minimal в браузері Chrome і виконав аналогічну нехитру процедуру, вставивши ім'я потоку, і натиснувши на відтворення.

image

Какаова ж була моя радість, Кхалісі!

Тепер в моєму арсеналі була доставка RTMP потоку на Chrome, а значить на Android за WebRTC, і на iOS Safari вебсокетам. І в тому і в іншому випадку картинка була цілком плавною, зі звуком і теоретично годилася для розгортання консалтингового сервісу.

Наступним питанням була робота з FMS. Зрозуміло, що RTMP протокол повинен бути єдиним для всіх реалізацій, але належало з'ясувати: а) чи Може FMS перенаправити RTMP стрім на Flashphoner і б) прийме Flashphoner цей стрім, як брав його з Flash в тестах вище.

Інтеграція з Adobe Media Server
З FMS довелося повозитися. Його установка і тести зайняли у мене пару годин. Перше, що я зробив, це протестував FMS з допомогою FMLE і переконався що FMS я встановив і налаштував правильно, і RTMP відеопотоки ходять на ньому без будь-яких перешкод.

image

Наступним кроком була налаштування перенаправлення RTMP потоку на Flashphoner. Тут довелося трохи напружити мозок, озброїтися документацією Adobe Action Script і заимплементить такий скрипт: main.asc.

var wcsServer = "wcs5-eu.flashphoner.com";
var netConnections = new Object();
var streams = new Object();

application.onConnect = function (client){
trace("onConnect "+client.id);
var nc = new NetConnection();
var obj = new Object();
obj.login = "Alice";
obj.appKey = "flashChatApp";
nc.connect("rtmp://"+wcsServer+":1935",obj);
nc.onStatus = function(info){
trace("onStatus info.code: "+info.code);
if (info.code=="NetConnection.Connect.Success"){
trace("connection opened "+wcsServer);
}
}
netConnections[client.id]=nc;
return true;
}

application.onDisconnect = function (client){
trace("onDisconnect "+client.id);
var nc = netConnections[client.id];
if (nc){
nc.close();
trace("disconnected "+client.id);
}
}

application.onPublish = function(client, myStream){
trace("onPublish "+myStream.name);
var nc = netConnections[client.id];
ns = new NetStream(nc);
ns.onStatus = function(info){
if (info.code == "NetStream.Publish.Start"){
trace("It is now publishing "+myStream.name);
}
}
ns.attach(myStream);
ns.publish(myStream.name);
streams[myStream.name]=ns;
trace("publish stream "+myStream.name+" to: "+wcsServer);
}

application.onUnpublish = function(client, myStream){
trace("onUnpublish "+myStream.name);
var ns = streams[myStream.name];
if (ns){
ns.publish(false);
trace("unpublished "+ns.name);
}
}


Скрипт досить простий і займається тим, що делегує входять на FMS коннекти та відеопотоки Flashphoner-сервера. Наприклад, при отриманні конекту від програми в методі onConnect, створюється коннект до Flashphoner-серверу за RTMP.

При отриманні відеопотоку onPublish, цей же відеопотік публікується на Flashphoner.

При дисконнектах і зупинці стримов, відповідні виклики делегуються для звільнення ресурсів. Так у мене вийшов міст, по якому буде прокидываться трафік між FMS і Flashphoner для подальшої роздачі WebRTC і Websockets.

image

Для тестування цієї композиції я взяв вже знайомий Flash-інтерфейс Flash Streaming. Єдина різниця була в тому, що потрібно було вказати RTMP адреса FMS-сервера і далі покластися на скрипт main.asc, який делегує цей відеопотік Flashphoner. В моєму випадку цією адресою був rtmp://my-fms:1935

image

При тестуванні довелося неабияк подебажить серверний скрипт main.asc від незнання Action Script і серверного програмування під FMS, але це все залишилося в минулому, і вище в лістингу доступна робоча на той момент версія цього скрипта. FMS не підвів і передав RTMP стрім по призначенню, що і дозволило успішно програти його в Chrome та Safari.

image

Установка Web Call Server
У підсумку демо було готове. Залишалося поставити Web Call Server на своїй системі щоб уникнути збоїв в момент презентації. Мало чого вони там можуть накрутити до понеділка.

На сайті розробника знайшлася інструкція по установці, що складається з п'яти пунктів. П'ятий пункт з установкою SSL-сертифікатів я опустив, оскільки поки не планував використовувати WebRTC-стрімінг з камери і мікрофону.

  1. Download Web Call Server 5
  2. Install using the 'install.sh' script
  3. Launch using 'service webcallserver start'
  4. Open the web-interface http://host:9091 and activate your license
Установка пройшла нормально. Я завбачливо відключив на тестовому сервері Firewall (service iptables stop) щоб виключити проблеми з непроходженням трафіку.

Через хвилину після запуса сервера вийшло відкрити веб-інтерфейс з адмінкою http://host:9091, щоб активувати тестову ліцензію і отримати у себе на Ubuntu демо-сервер, схожий на цей:

image

Додатковий прогін тестів дозволив переконатися, що схема працює і в моєму оточенні. З почуттям виконаної справи, я завершив робочий день і поставив напоминалку – ще раз перевірити тести у понеділок о 9:00 перед приходом Суконако.

Як проходила міграція і чим закінчилася справа, можу написати у другій частині, якщо буде цікаво.

Посилання на використовувані інструменти:

  1. FMS (Flash Media Server) він же AMS (Adobe Media Server) – RTMP медіа сервер.
  2. DODigital Ocean – хостинг віртуальних серверів.
  3. WCS (Flashphoner Web Call Server – WebRTC, Websocket медіа сервер.
  4. FMLE (Adobe Flash Media Live Encoder – клієнт для перевірки RTMP-з'єднання з сервером.
  5. Phoboslab — опенсорсний прототип Websocket стрімінг на Safari в iOS.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.