• Главная
  • Карта сайта
Не найдено

Capturing Audio & Video in HTML5 - HTML5 Rocks

  1. Capturing Audio & Video in HTML5 This article discusses APIs that are not yet fully standardized...
  2. Історія появи getUserMedia ()
  3. Етап 1: захоплення мультимедійних файлів в HTML
  4. Етап 2: елемент пристрою
  5. Етап 3: WebRTC
  6. Початок роботи
  7. включення
  8. визначення можливостей
  9. Отримання доступу до пристрою введення
  10. Безпека
  11. Забезпечення зворотної сумісності
  12. Демонстрація основних можливостей
  13. знімки екрану
  14. застосування ефектів
  15. текстури WebGL
  16. Використання getUserMedia з API веб-аудіо
  17. висновки
  18. додаткові ресурси
  19. Вступ
  20. Історія появи getUserMedia ()
  21. Етап 1: захоплення мультимедійних файлів в HTML
  22. Етап 2: елемент пристрою
  23. Етап 3: WebRTC
  24. Початок роботи
  25. включення
  26. визначення можливостей
  27. Отримання доступу до пристрою введення
  28. Безпека
  29. Забезпечення зворотної сумісності
  30. Демонстрація основних можливостей
  31. знімки екрану
  32. застосування ефектів
  33. текстури WebGL
  34. Використання getUserMedia з API веб-аудіо
  35. висновки
  36. додаткові ресурси
  37. Вступ
  38. Історія появи getUserMedia ()
  39. Етап 1: захоплення мультимедійних файлів в HTML
  40. Етап 2: елемент пристрою
  41. Етап 3: WebRTC
  42. Початок роботи
  43. включення
  44. визначення можливостей
  45. Отримання доступу до пристрою введення
  46. Безпека
  47. Забезпечення зворотної сумісності
  48. Демонстрація основних можливостей
  49. знімки екрану
  50. застосування ефектів
  51. текстури WebGL
  52. Використання getUserMedia з API веб-аудіо
  53. висновки

Capturing Audio & Video in HTML5

This article discusses APIs that are not yet fully standardized and still in flux. Be cautious when using experimental APIs in your own projects.

Вступ

Захоплення потокового відео і аудіо є пріоритетним напрямком в розробці веб-додатків на протязі багатьох років. Протягом довгого часу для виконання цих завдань ми покладалися на плагіни ( Flash і Silverlight ). Come on!

На допомогу прийшов HTML5. Можливо, цей момент не очевидний, але поширення HTML5 підняло питання доступу до апаратних ресурсів. Прекрасними прикладами цього є функції Geolocation (GPS), Orientation API (Акселерометр), WebGL (Графічні процесори) і API веб-аудіо (Звукове обладнання). Ці розробки дуже функціональні. Вони створені на основі API JavaScript високого рівня і спираються на апаратні можливості вихідного пристрою.

Ця стаття присвячена новому API під назвою navigator.getUserMedia () , Який надає веб-додатків доступ до відеокамери та мікрофону.

Історія появи getUserMedia ()

Історія появи API getUserMedia () досить цікава.

За останні кілька років з'явилося кілька різних API захоплення мультимедійних файлів. Багато хто усвідомив необхідність доступу до апаратних ресурсів з веб-додатків, і це привело до створення різних специфікацій. Ситуація остаточно заплуталася, і тоді консорціум W3C вирішив сформувати робочу групу. Її єдиним завданням стало навести порядок у цій сфері. Для цього робоча група по створенню правил для API пристроїв (DAP) повинна була об'єднати і стандартизувати існуючі пропозиції.

Зараз можна підвести підсумки того, що було зроблено в 2011 р

Етап 1: захоплення мультимедійних файлів в HTML

Специфікація захоплення мультимедійних файлів в HTML стала першим стандартом захоплення мультимедійної інформації в веб-додатках, створеним групою DAP. Його робота заснована на перевизначенні функції <input type = "file"> і додаванні нових значень для параметра accept.

Щоб дати користувачам можливість сфотографувати себе на веб-камеру, можна додати рядок capture = camera.

<Input type = "file" accept = "image / *; capture = camera">

Точно так само відбувається запис відео і звуку.

<Input type = "file" accept = "video / *; capture = camcorder"> <input type = "file" accept = "audio / *; capture = microphone">

Це досить зручно. Зокрема, мені подобається, що в цьому методі використовується файловий ввід. З точки зору семантики це має велике значення. Єдиний недолік цього API - неможливість додавання ефектів в реальному часі (наприклад, не можна виводити дані з веб-камери на елемент <canvas> і застосовувати фільтри WebGL). За допомогою захоплення мультимедійних файлів в HTML можна тільки записувати файли мультимедіа або робити знімки.

підтримка

  • Браузер Android 3.0 - один з перших прикладів реалізації цього API. Щоб побачити його в дії, подивіться це відео .
  • Chrome для Android (0.16)

Я не рекомендую використовувати цей API, якщо тільки ви не працюєте з одним з перерахованих вище браузерів. Розробники поступово переходять до getUserMedia (), і в перспективі навряд чи хто-небудь захоче займатися реалізацією захоплення мультимедійних файлів за допомогою HTML.

Етап 2: елемент пристрою

Багато хто вважав, що в API захоплення мультимедійних файлів в HTML занадто багато обмежень, тому з'явилася нова специфікація, що підтримує будь-які пристрої, включаючи ті, що з'являться в майбутньому. Не дивно, що ця розробка зажадала введення нового елемента <Device> , Який став кроком на шляху до створення API getUserMedia ().

Одним з перших браузерів, в якому була реалізована підтримка захоплення відео за допомогою елемента <device>, стала Opera. Незабаром після цього ( точніше, в той же день ), Співтовариство WhatWG вирішило відмовитися від тега <device> на користь більш успішного API JavaScript під назвою navigator.getUserMedia (). Через тиждень в нову збірку Opera була додана підтримка оновленої специфікації getUserMedia (). В кінці цього року компанія Майкрософт приєдналася до розробки, випустивши експериментальний пакет для IE9 з підтримкою цієї специфікації.

Ось так міг виглядати тег <device>:

<Device type = "media" onchange = "update (this.data)"> </ device> <video autoplay> </ video> <script> function update (stream) {document.querySelector ( 'video'). Src = stream.url; } </ Script>

підтримка

На жаль, тег <device> не був реалізований ні в одному браузері. Таким чином, його можна не брати до уваги, хоча у тега <device> все ж було дві переваги. По-перше, він мав семантичний характер, а по-друге, дозволяв не обмежуватися аудіо- та відеопристроїв.

Переходимо до наступної технології.

Етап 3: WebRTC

Елемент <device> в кінцевому рахунку повністю зник.

В останні кілька місяців спроби створення API для захоплення даних мультимедіа почали приносити відчутні результати - багато в чому завдяки проекту WebRTC (Передача даних в Інтернеті в реальному часі). Розробку цієї специфікації курирує спеціальна робоча група W3C WebRTC . В даний час над реалізацією її підтримки в браузерах працюють такі відомі компанії, як Google, Opera, Mozilla, а також ряд інших .

WebRTC має пряме відношення до getUserMedia () - першому API в цьому наборі. Ця технологія забезпечує доступ до потоковим даними з мікрофона і відеокамери.

підтримка

WebRTC можна включити в браузері Chrome 18.0.1008 і його більш пізніх версіях на сторінці about: flags.

Початок роботи

Завдяки navigator.getUserMedia () нарешті з'явилася можливість перехоплювати дані з веб-камер і мікрофонів безпосередньо, тобто без допомоги плагінів. Доступ до камери тепер здійснюється за запитом, і для цього нічого не потрібно встановлювати. Ця можливість вбудована в браузер, і це досить цікаво.

включення

API getUserMedia () з'явився зовсім недавно, тому він реалізований тільки в збірках для розробників Google і Opera. У Chrome 18+ його можна включити на сторінці about: flags.

У Chrome 18+ його можна включити на сторінці about: flags

Включення getUserMedia () на сторінці about: flags браузера Chrome.

Для Opera ви можете завантажити одну з експериментальних збірок для Android або звичайних комп'ютерів .

визначення можливостей

Ця перевірка дозволяє переконатися в підтримці браузером функції navigator.getUserMedia.

function hasGetUserMedia () {// Note: Opera builds are unprefixed. return !! (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); } If (hasGetUserMedia ()) {// Good to go! } Else {alert ( 'getUserMedia () is not supported in your browser'); }

Отримання доступу до пристрою введення

Для доступу до веб-камері або мікрофону необхідно запросити дозвіл. Перший параметр методу getUserMedia () визначає тип даних, до яких вони вимагають доступ. Наприклад, якщо щоб звернутися до веб-камері, необхідно задати для нього значення video. Щоб використовувати одночасно камеру і мікрофон, потрібно вказати video, audio.

<Video autoplay> </ video> <script> var onFailSoHard = function (e) {console.log ( 'Reeeejected!', E); }; // Not showing vendor prefixes. navigator.getUserMedia ( 'video, audio', function (localMediaStream) {var video = document.querySelector ( 'video'); video.src = window.URL.createObjectURL (localMediaStream); // Note: onloadedmetadata does not fire in Chrome when using it with getUserMedia. // See crbug.com/110938. video.onloadedmetadata = function (e) {// Ready to go. Do some stuff.};}, onFailSoHard); </ Script>

Отже, що ж відбувається далі? Функція захоплення даних мультимедіа - прекрасний приклад спільної роботи різних API в HTML5. Вона використовується разом з іншими елементами HTML5: <audio> і <video>. Зверніть увагу: ми не додаємо атрибут src або елементи <source> в тег <video>. Замість того щоб вказувати URL файлу мультимедіа, ми передаємо URL елемента Blob з об'єкта LocalMediaStream, який представляє веб-камеру.

Ми також додаємо для тега <video> атрибут автоматичного програвання autoplay, щоб відео не зупинилася на першому ж кадрі. Додати елементи управління також нескладно.

Увага! У Chrome є неполадка: якщо передати в якості значення параметра тільки audio, код не працює ( crbug.com/112367 ). Та ж проблема з тегом <audio> виявлена ​​і в Opera.

В Opera і Chrome реалізовані різні версії цієї специфікації , Що дещо ускладнює її практичне використання на даному етапі.

Chrome

Нижче наведено фрагмент коду для Chrome 18+ (необхідно спочатку включити цю функцію на сторінці about: flags).

navigator.webkitGetUserMedia ( 'audio, video', function (localMediaStream) {var video = document.querySelector ( 'video'); video.src = window.webkitURL.createObjectURL (localMediaStream);}, onFailSoHard);

Opera:

Складання Opera для розробників засновані на оновленій версії специфікації. Нижче наведено фрагмент коду для Opera.

navigator.getUserMedia ({audio: true, video: true}, function (localMediaStream) {video.src = localMediaStream;}, onFailSoHard);

Існує кілька ключових відмінностей.

  • У getUserMedia () не використовуються префікси.
  • Об'єкт передається як перший аргумент, а не список рядків.
  • Значення video.src присвоюється безпосередньо об'єкту LocalMediaStream, а не URL даного Blob. Наскільки мені відомо, в Opera в кінцевому підсумку буде використовуватися URL об'єкта Blob.

Крос-браузерна підтримка

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

var video = document.querySelector ( 'video'); if (navigator.getUserMedia) {navigator.getUserMedia ({audio: true, video: true}, function (stream) {video.src = stream;}, onFailSoHard); } Else if (navigator.webkitGetUserMedia) {navigator.webkitGetUserMedia ( 'audio, video', function (stream) {video.src = window.webkitURL.createObjectURL (stream);}, onFailSoHard); } Else {video.src = 'somevideo.webm'; // fallback. }

Обов'язково ознайомтеся зі статтею Майка Тейлора (Mike Taylor) і Майка Робінсона (Mike Robinson) gUM Shield . Вона допоможе усунути протиріччя в варіантах коду для різних браузерів.

Безпека

У майбутньому в браузерах при виклику методу getUserMedia (), можливо, буде з'являтися інформаційна панель, що дозволяє користувачеві надавати або заборонити доступ до камери або мікрофона. На жаль, в специфікації приділено мало уваги питанням безпеки. Поки що така панель з дозволами не реалізована.

Забезпечення зворотної сумісності

Для тих, хто не може скористатися методом getUserMedia () (наприклад, якщо цей API не підтримує або з якоїсь причини стався збій запиту), єдине рішення - використовувати існуючі відеофайли.

// Not showing vendor prefixes or code that works cross-browser: function fallback (e) {video.src = 'fallbackvideo.webm'; } Function success (stream) {video.src = window.URL.createObjectURL (stream); } If (! Navigator.getUserMedia) {fallback (); } Else {navigator.getUserMedia ({video: true}, success, fallback); }

Демонстрація основних можливостей

Захоплення відео Зупинити

знімки екрану

В API <canvas> є метод ctx.drawImage (video, 0, 0), який дозволяє легко виводити кадри <video> на елемент <canvas>. Звичайно, тепер, коли з'явилася можливість введення відео за допомогою API getUserMedia (), можна легко створити додаток типу "фотокіоск" для роботи з потоковим відео.

<Video autoplay> </ video> <img src = ""> <canvas style = "display: none;"> </ canvas> var video = document.querySelector ( 'video'); var canvas = document.querySelector ( 'canvas'); var ctx = canvas.getContext ( '2d'); var localMediaStream = null; function snapshot () {if (localMediaStream) {ctx.drawImage (video, 0, 0); // "image / webp" works in Chrome 18. In other browsers, this will fall back to image / png. document.querySelector ( 'img'). src = canvas.toDataURL ( 'image / webp'); }} Video.addEventListener ( 'click', snapshot, false); // Not showing vendor prefixes or code that works cross-browser. navigator.getUserMedia ({video: true}, function (stream) {video.src = window.URL.createObjectURL (stream); localMediaStream = stream;}, onFailSoHard); <Video autoplay> </ video> <img src = > <canvas style = display: none;> </ canvas> var video = document

захоплення Зупинити

застосування ефектів

фільтри CSS

Фільтри CSS в даний час підтримуються в "нічних" збірках WebKit і Chrome 18+.

За допомогою фільтрів CSS до елементу <video> при захопленні можна застосувати деякі ефекти.

<Style> video {width: 307px; height: 250px; background: rgba (255,255,255,0.5); border: 1px solid #ccc; } .Grayscale { + Filter: grayscale (1); } .Sepia { + Filter: sepia (1); } .Blur { + Filter: blur (3px); } ... </ style> <video autoplay> </ video> <script> var idx = 0; var filters = [ 'grayscale', 'sepia', 'blur', 'brightness', 'contrast', 'hue-rotate', 'hue-rotate2', 'hue-rotate3', 'saturate', 'invert', '']; function changeFilter (e) {var el = e.target; el.className = ''; var effect = filters [idx ++% filters.length]; // loop through filters. if (effect) {el.classList.add (effect); }} Document.querySelector ( 'video'). AddEventListener ( 'click', changeFilter, false); </ Script>

Натисніть відео, щоб ознайомитися з фільтрами CSS

Захоплення відео Зупинити

текстури WebGL

Один із чудових прикладів використання функцій захоплення відео - висновок одержуваних в режимі реального часу даних в якості текстури WebGL. Я абсолютно не розбираюся в WebGL, тому пропоную вам ознайомитися з керівництвом і демонстраційним прикладом Джерома Етьєна (Jerome Etienne). У ньому йдеться про те, як за допомогою методу getUserMedia () і скрипта Three.js виводити потокове відео в WebGL.

Використання getUserMedia з API веб-аудіо

У цьому розділі описані можливі удосконалення і поліпшення цього API.

У мене є мрія: вбудувати AutoTune в браузер, використовуючи тільки відкриті веб-технології. Вона майже здійсненна. Вже є API getUserMedia () для введення звуку з мікрофона. Досить додати ефекти реального часу за допомогою API веб-аудіо , І все буде готово. Бракує лише інтеграції цих двох рішень ( crbug.com/112404 ), Хоча попередню пропозицію вже розробляється.

Передача сигналу мікрофона в API веб-аудіо, можливо, буде коли-небудь відбуватися так, як показано нижче.

var context = new window.webkitAudioContext (); navigator.webkitGetUserMedia ({audio: true}, function (stream) {var microphone = context.createMediaStreamSource (stream); var filter = context.createBiquadFilter (); // microphone -> filter -> destination. microphone.connect (filter) ; filter.connect (context.destination);}, onFailSoHard);

Щоб побачити, як API getUserMedia () зв'язується з API веб-аудіо, зайдіть на сайт crbug.com/112404 .

висновки

В цілому віддалений доступ до пристроїв через Інтернет завжди був досить складним завданням. багато пробували розв'язати цю проблему, але мало кому вдавалося це зробити. Більшість рішень ніколи не виходило за рамки пропрієтарного програмного забезпечення, тому вони не набули широкого поширення.

Справжня проблема полягає в тому, що модель безпеки для веб-додатків сильно відрізняється від традиційної. Особисто мені не хотілося б, щоб доступ до моєї камері був у першого-ліпшого сайту. Вирішити це питання досить складно.

Об'єднані платформи, наприклад PhoneGap , Допомогли розширити межі можливого, але це лише початок, і таке рішення є тимчасовим. Щоб веб-додатки могли успішно конкурувати з традиційними рішеннями, їм необхідний доступ до апаратного забезпечення комп'ютерів.

API getUserMedia () є першою спробою доступу до нового типу пристроїв. Сподіваюся, що в найближчому майбутньому з'являться і інші рішення.

додаткові ресурси

демонстраційні приклади

Capturing Audio & Video in HTML5

This article discusses APIs that are not yet fully standardized and still in flux. Be cautious when using experimental APIs in your own projects.

Вступ

Захоплення потокового відео і аудіо є пріоритетним напрямком в розробці веб-додатків на протязі багатьох років. Протягом довгого часу для виконання цих завдань ми покладалися на плагіни ( Flash і Silverlight ). Come on!

На допомогу прийшов HTML5. Можливо, цей момент не очевидний, але поширення HTML5 підняло питання доступу до апаратних ресурсів. Прекрасними прикладами цього є функції Geolocation (GPS), Orientation API (Акселерометр), WebGL (Графічні процесори) і API веб-аудіо (Звукове обладнання). Ці розробки дуже функціональні. Вони створені на основі API JavaScript високого рівня і спираються на апаратні можливості вихідного пристрою.

Ця стаття присвячена новому API під назвою navigator.getUserMedia () , Який надає веб-додатків доступ до відеокамери та мікрофону.

Історія появи getUserMedia ()

Історія появи API getUserMedia () досить цікава.

За останні кілька років з'явилося кілька різних API захоплення мультимедійних файлів. Багато хто усвідомив необхідність доступу до апаратних ресурсів з веб-додатків, і це привело до створення різних специфікацій. Ситуація остаточно заплуталася, і тоді консорціум W3C вирішив сформувати робочу групу. Її єдиним завданням стало навести порядок у цій сфері. Для цього робоча група по створенню правил для API пристроїв (DAP) повинна була об'єднати і стандартизувати існуючі пропозиції.

Зараз можна підвести підсумки того, що було зроблено в 2011 р

Етап 1: захоплення мультимедійних файлів в HTML

Специфікація захоплення мультимедійних файлів в HTML стала першим стандартом захоплення мультимедійної інформації в веб-додатках, створеним групою DAP. Його робота заснована на перевизначенні функції <input type = "file"> і додаванні нових значень для параметра accept.

Щоб дати користувачам можливість сфотографувати себе на веб-камеру, можна додати рядок capture = camera.

<Input type = "file" accept = "image / *; capture = camera">

Точно так само відбувається запис відео і звуку.

<Input type = "file" accept = "video / *; capture = camcorder"> <input type = "file" accept = "audio / *; capture = microphone">

Це досить зручно. Зокрема, мені подобається, що в цьому методі використовується файловий ввід. З точки зору семантики це має велике значення. Єдиний недолік цього API - неможливість додавання ефектів в реальному часі (наприклад, не можна виводити дані з веб-камери на елемент <canvas> і застосовувати фільтри WebGL). За допомогою захоплення мультимедійних файлів в HTML можна тільки записувати файли мультимедіа або робити знімки.

підтримка

  • Браузер Android 3.0 - один з перших прикладів реалізації цього API. Щоб побачити його в дії, подивіться це відео .
  • Chrome для Android (0.16)

Я не рекомендую використовувати цей API, якщо тільки ви не працюєте з одним з перерахованих вище браузерів. Розробники поступово переходять до getUserMedia (), і в перспективі навряд чи хто-небудь захоче займатися реалізацією захоплення мультимедійних файлів за допомогою HTML.

Етап 2: елемент пристрою

Багато хто вважав, що в API захоплення мультимедійних файлів в HTML занадто багато обмежень, тому з'явилася нова специфікація, що підтримує будь-які пристрої, включаючи ті, що з'являться в майбутньому. Не дивно, що ця розробка зажадала введення нового елемента <Device> , Який став кроком на шляху до створення API getUserMedia ().

Одним з перших браузерів, в якому була реалізована підтримка захоплення відео за допомогою елемента <device>, стала Opera. Скоро після цього ( точніше, в той же день ), Співтовариство WhatWG вирішило відмовитися від тега <device> на користь більш успішного API JavaScript під назвою navigator.getUserMedia (). Через тиждень в нову збірку Opera була додана підтримка оновленої специфікації getUserMedia (). В кінці цього року компанія Майкрософт приєдналася до розробки, випустивши експериментальний пакет для IE9 з підтримкою цієї специфікації.

Ось так міг виглядати тег <device>:

<Device type = "media" onchange = "update (this.data)"> </ device> <video autoplay> </ video> <script> function update (stream) {document.querySelector ( 'video'). Src = stream.url; } </ Script>

підтримка

На жаль, тег <device> не був реалізований ні в одному браузері. Таким чином, його можна не брати до уваги, хоча у тега <device> все ж було дві переваги. По-перше, він мав семантичний характер, а по-друге, дозволяв не обмежуватися аудіо- та відеопристроїв.

Переходимо до наступної технології.

Етап 3: WebRTC

Елемент <device> в кінцевому рахунку повністю зник.

В останні кілька місяців спроби створення API для захоплення даних мультимедіа почали приносити відчутні результати - багато в чому завдяки проекту WebRTC (Передача даних в Інтернеті в реальному часі). Розробку цієї специфікації курирує спеціальна робоча група W3C WebRTC . В даний час над реалізацією її підтримки в браузерах працюють такі відомі компанії, як Google, Opera, Mozilla, а також ряд інших .

WebRTC має пряме відношення до getUserMedia () - першому API в цьому наборі. Ця технологія забезпечує доступ до потоковим даними з мікрофона і відеокамери.

підтримка

WebRTC можна включити в браузері Chrome 18.0.1008 і його більш пізніх версіях на сторінці about: flags.

Початок роботи

Завдяки navigator.getUserMedia () нарешті з'явилася можливість перехоплювати дані з веб-камер і мікрофонів безпосередньо, тобто без допомоги плагінів. Доступ до камери тепер здійснюється за запитом, і для цього нічого не потрібно встановлювати. Ця можливість вбудована в браузер, і це досить цікаво.

включення

API getUserMedia () з'явився зовсім недавно, тому він реалізований тільки в збірках для розробників Google і Opera. У Chrome 18+ його можна включити на сторінці about: flags.

У Chrome 18+ його можна включити на сторінці about: flags

Включення getUserMedia () на сторінці about: flags браузера Chrome.

Для Opera ви можете завантажити одну з експериментальних збірок для Android або звичайних комп'ютерів .

визначення можливостей

Ця перевірка дозволяє переконатися в підтримці браузером функції navigator.getUserMedia.

function hasGetUserMedia () {// Note: Opera builds are unprefixed. return !! (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); } If (hasGetUserMedia ()) {// Good to go! } Else {alert ( 'getUserMedia () is not supported in your browser'); }

Отримання доступу до пристрою введення

Для доступу до веб-камері або мікрофону необхідно запросити дозвіл. Перший параметр методу getUserMedia () визначає тип даних, до яких вони вимагають доступ. Наприклад, якщо щоб звернутися до веб-камері, необхідно задати для нього значення video. Щоб використовувати одночасно камеру і мікрофон, потрібно вказати video, audio.

<Video autoplay> </ video> <script> var onFailSoHard = function (e) {console.log ( 'Reeeejected!', E); }; // Not showing vendor prefixes. navigator.getUserMedia ( 'video, audio', function (localMediaStream) {var video = document.querySelector ( 'video'); video.src = window.URL.createObjectURL (localMediaStream); // Note: onloadedmetadata does not fire in Chrome when using it with getUserMedia. // See crbug.com/110938. video.onloadedmetadata = function (e) {// Ready to go. Do some stuff.};}, onFailSoHard); </ Script>

Отже, що ж відбувається далі? Функція захоплення даних мультимедіа - прекрасний приклад спільної роботи різних API в HTML5. Вона використовується разом з іншими елементами HTML5: <audio> і <video>. Зверніть увагу: ми не додаємо атрибут src або елементи <source> в тег <video>. Замість того щоб вказувати URL файлу мультимедіа, ми передаємо URL елемента Blob з об'єкта LocalMediaStream, який представляє веб-камеру.

Ми також додаємо для тега <video> атрибут автоматичного програвання autoplay, щоб відео не зупинилася на першому ж кадрі. Додати елементи управління також нескладно.

Увага! У Chrome є неполадка: якщо передати в якості значення параметра тільки audio, код не працює ( crbug.com/112367 ). Та ж проблема з тегом <audio> виявлена ​​і в Opera.

В Opera і Chrome реалізовані різні версії цієї специфікації , Що дещо ускладнює її практичне використання на даному етапі.

Chrome

Нижче наведено фрагмент коду для Chrome 18+ (необхідно спочатку включити цю функцію на сторінці about: flags).

navigator.webkitGetUserMedia ( 'audio, video', function (localMediaStream) {var video = document.querySelector ( 'video'); video.src = window.webkitURL.createObjectURL (localMediaStream);}, onFailSoHard);

Opera:

Складання Opera для розробників засновані на оновленій версії специфікації. Нижче наведено фрагмент коду для Opera.

navigator.getUserMedia ({audio: true, video: true}, function (localMediaStream) {video.src = localMediaStream;}, onFailSoHard);

Існує кілька ключових відмінностей.

  • У getUserMedia () не використовуються префікси.
  • Об'єкт передається як перший аргумент, а не список рядків.
  • Значення video.src присвоюється безпосередньо об'єкту LocalMediaStream, а не URL даного Blob. Наскільки мені відомо, в Opera в кінцевому підсумку буде використовуватися URL об'єкта Blob.

Крос-браузерна підтримка

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

var video = document.querySelector ( 'video'); if (navigator.getUserMedia) {navigator.getUserMedia ({audio: true, video: true}, function (stream) {video.src = stream;}, onFailSoHard); } Else if (navigator.webkitGetUserMedia) {navigator.webkitGetUserMedia ( 'audio, video', function (stream) {video.src = window.webkitURL.createObjectURL (stream);}, onFailSoHard); } Else {video.src = 'somevideo.webm'; // fallback. }

Обов'язково ознайомтеся зі статтею Майка Тейлора (Mike Taylor) і Майка Робінсона (Mike Robinson) gUM Shield . Вона допоможе усунути протиріччя в варіантах коду для різних браузерів.

Безпека

У майбутньому в браузерах при виклику методу getUserMedia (), можливо, буде з'являтися інформаційна панель, що дозволяє користувачеві надавати або заборонити доступ до камери або мікрофона. На жаль, в специфікації приділено мало уваги питанням безпеки. Поки що така панель з дозволами не реалізована.

Забезпечення зворотної сумісності

Для тих, хто не може скористатися методом getUserMedia () (наприклад, якщо цей API не підтримує або з якоїсь причини стався збій запиту), єдине рішення - використовувати існуючі відеофайли.

// Not showing vendor prefixes or code that works cross-browser: function fallback (e) {video.src = 'fallbackvideo.webm'; } Function success (stream) {video.src = window.URL.createObjectURL (stream); } If (! Navigator.getUserMedia) {fallback (); } Else {navigator.getUserMedia ({video: true}, success, fallback); }

Демонстрація основних можливостей

Захоплення відео Зупинити

знімки екрану

В API <canvas> є метод ctx.drawImage (video, 0, 0), який дозволяє легко виводити кадри <video> на елемент <canvas>. Звичайно, тепер, коли з'явилася можливість введення відео за допомогою API getUserMedia (), можна легко створити додаток типу "фотокіоск" для роботи з потоковим відео.

<Video autoplay> </ video> <img src = ""> <canvas style = "display: none;"> </ canvas> var video = document.querySelector ( 'video'); var canvas = document.querySelector ( 'canvas'); var ctx = canvas.getContext ( '2d'); var localMediaStream = null; function snapshot () {if (localMediaStream) {ctx.drawImage (video, 0, 0); // "image / webp" works in Chrome 18. In other browsers, this will fall back to image / png. document.querySelector ( 'img'). src = canvas.toDataURL ( 'image / webp'); }} Video.addEventListener ( 'click', snapshot, false); // Not showing vendor prefixes or code that works cross-browser. navigator.getUserMedia ({video: true}, function (stream) {video.src = window.URL.createObjectURL (stream); localMediaStream = stream;}, onFailSoHard); <Video autoplay> </ video> <img src = > <canvas style = display: none;> </ canvas> var video = document

захоплення Зупинити

застосування ефектів

фільтри CSS

Фільтри CSS в даний час підтримуються в "нічних" збірках WebKit і Chrome 18+.

За допомогою фільтрів CSS до елементу <video> при захопленні можна застосувати деякі ефекти.

<Style> video {width: 307px; height: 250px; background: rgba (255,255,255,0.5); border: 1px solid #ccc; } .Grayscale { + Filter: grayscale (1); } .Sepia { + Filter: sepia (1); } .Blur { + Filter: blur (3px); } ... </ style> <video autoplay> </ video> <script> var idx = 0; var filters = [ 'grayscale', 'sepia', 'blur', 'brightness', 'contrast', 'hue-rotate', 'hue-rotate2', 'hue-rotate3', 'saturate', 'invert', '']; function changeFilter (e) {var el = e.target; el.className = ''; var effect = filters [idx ++% filters.length]; // loop through filters. if (effect) {el.classList.add (effect); }} Document.querySelector ( 'video'). AddEventListener ( 'click', changeFilter, false); </ Script>

Натисніть відео, щоб ознайомитися з фільтрами CSS

Захоплення відео Зупинити

текстури WebGL

Один із чудових прикладів використання функцій захоплення відео - висновок одержуваних в режимі реального часу даних в якості текстури WebGL. Я абсолютно не розбираюся в WebGL, тому пропоную вам ознайомитися з керівництвом і демонстраційним прикладом Джерома Етьєна (Jerome Etienne). У ньому йдеться про те, як за допомогою методу getUserMedia () і скрипта Three.js виводити потокове відео в WebGL.

Використання getUserMedia з API веб-аудіо

У цьому розділі описані можливі удосконалення і поліпшення цього API.

У мене є мрія: вбудувати AutoTune в браузер, використовуючи тільки відкриті веб-технології. Вона майже здійсненна. Вже є API getUserMedia () для введення звуку з мікрофона. Досить додати ефекти реального часу за допомогою API веб-аудіо , І все буде готово. Бракує лише інтеграції цих двох рішень ( crbug.com/112404 ), Хоча попередню пропозицію вже розробляється.

Передача сигналу мікрофона в API веб-аудіо, можливо, буде коли-небудь відбуватися так, як показано нижче.

var context = new window.webkitAudioContext (); navigator.webkitGetUserMedia ({audio: true}, function (stream) {var microphone = context.createMediaStreamSource (stream); var filter = context.createBiquadFilter (); // microphone -> filter -> destination. microphone.connect (filter) ; filter.connect (context.destination);}, onFailSoHard);

Щоб побачити, як API getUserMedia () зв'язується з API веб-аудіо, зайдіть на сайт crbug.com/112404 .

висновки

В цілому віддалений доступ до пристроїв через Інтернет завжди був досить складним завданням. багато пробували розв'язати цю проблему, але мало кому вдавалося це зробити. Більшість рішень ніколи не виходило за рамки пропрієтарного програмного забезпечення, тому вони не набули широкого поширення.

Справжня проблема полягає в тому, що модель безпеки для веб-додатків сильно відрізняється від традиційної. Особисто мені не хотілося б, щоб доступ до моєї камері був у першого-ліпшого сайту. Вирішити це питання досить складно.

Об'єднані платформи, наприклад PhoneGap , Допомогли розширити межі можливого, але це лише початок, і таке рішення є тимчасовим. Щоб веб-додатки могли успішно конкурувати з традиційними рішеннями, їм необхідний доступ до апаратного забезпечення комп'ютерів.

API getUserMedia () є першою спробою доступу до нового типу пристроїв. Сподіваюся, що в найближчому майбутньому з'являться і інші рішення.

додаткові ресурси

демонстраційні приклади

Capturing Audio & Video in HTML5

This article discusses APIs that are not yet fully standardized and still in flux. Be cautious when using experimental APIs in your own projects.

Вступ

Захоплення потокового відео і аудіо є пріоритетним напрямком в розробці веб-додатків на протязі багатьох років. Протягом довгого часу для виконання цих завдань ми покладалися на плагіни ( Flash і Silverlight ). Come on!

На допомогу прийшов HTML5. Можливо, цей момент не очевидний, але поширення HTML5 підняло питання доступу до апаратних ресурсів. Прекрасними прикладами цього є функції Geolocation (GPS), Orientation API (Акселерометр), WebGL (Графічні процесори) і API веб-аудіо (Звукове обладнання). Ці розробки дуже функціональні. Вони створені на основі API JavaScript високого рівня і спираються на апаратні можливості вихідного пристрою.

Ця стаття присвячена новому API під назвою navigator.getUserMedia () , Який надає веб-додатків доступ до відеокамери та мікрофону.

Історія появи getUserMedia ()

Історія появи API getUserMedia () досить цікава.

За останні кілька років з'явилося кілька різних API захоплення мультимедійних файлів. Багато хто усвідомив необхідність доступу до апаратних ресурсів з веб-додатків, і це привело до створення різних специфікацій. Ситуація остаточно заплуталася, і тоді консорціум W3C вирішив сформувати робочу групу. Її єдиним завданням стало навести порядок у цій сфері. Для цього робоча група по створенню правил для API пристроїв (DAP) повинна була об'єднати і стандартизувати існуючі пропозиції.

Зараз можна підвести підсумки того, що було зроблено в 2011 р

Етап 1: захоплення мультимедійних файлів в HTML

Специфікація захоплення мультимедійних файлів в HTML стала першим стандартом захоплення мультимедійної інформації в веб-додатках, створеним групою DAP. Його робота заснована на перевизначенні функції <input type = "file"> і додаванні нових значень для параметра accept.

Щоб дати користувачам можливість сфотографувати себе на веб-камеру, можна додати рядок capture = camera.

<Input type = "file" accept = "image / *; capture = camera">

Точно так само відбувається запис відео і звуку.

<Input type = "file" accept = "video / *; capture = camcorder"> <input type = "file" accept = "audio / *; capture = microphone">

Це досить зручно. Зокрема, мені подобається, що в цьому методі використовується файловий ввід. З точки зору семантики це має велике значення. Єдиний недолік цього API - неможливість додавання ефектів в реальному часі (наприклад, не можна виводити дані з веб-камери на елемент <canvas> і застосовувати фільтри WebGL). За допомогою захоплення мультимедійних файлів в HTML можна тільки записувати файли мультимедіа або робити знімки.

підтримка

  • Браузер Android 3.0 - один з перших прикладів реалізації цього API. Щоб побачити його в дії, подивіться це відео .
  • Chrome для Android (0.16)

Я не рекомендую використовувати цей API, якщо тільки ви не працюєте з одним з перерахованих вище браузерів. Розробники поступово переходять до getUserMedia (), і в перспективі навряд чи хто-небудь захоче займатися реалізацією захоплення мультимедійних файлів за допомогою HTML.

Етап 2: елемент пристрою

Багато хто вважав, що в API захоплення мультимедійних файлів в HTML занадто багато обмежень, тому з'явилася нова специфікація, що підтримує будь-які пристрої, включаючи ті, що з'являться в майбутньому. Не дивно, що ця розробка зажадала введення нового елемента <Device> , Який став кроком на шляху до створення API getUserMedia ().

Одним з перших браузерів, в якому була реалізована підтримка захоплення відео за допомогою елемента <device>, стала Opera. Скоро після цього ( точніше, в той же день ), Співтовариство WhatWG вирішило відмовитися від тега <device> на користь більш успішного API JavaScript під назвою navigator.getUserMedia (). Через тиждень в нову збірку Opera була додана підтримка оновленої специфікації getUserMedia (). В кінці цього року компанія Майкрософт приєдналася до розробки, випустивши експериментальний пакет для IE9 з підтримкою цієї специфікації.

Ось так міг виглядати тег <device>:

<Device type = "media" onchange = "update (this.data)"> </ device> <video autoplay> </ video> <script> function update (stream) {document.querySelector ( 'video'). Src = stream.url; } </ Script>

підтримка

На жаль, тег <device> не був реалізований ні в одному браузері. Таким чином, його можна не брати до уваги, хоча у тега <device> все ж було дві переваги. По-перше, він мав семантичний характер, а по-друге, дозволяв не обмежуватися аудіо- та відеопристроїв.

Переходимо до наступної технології.

Етап 3: WebRTC

Елемент <device> в кінцевому рахунку повністю зник.

В останні кілька місяців спроби створення API для захоплення даних мультимедіа почали приносити відчутні результати - багато в чому завдяки проекту WebRTC (Передача даних в Інтернеті в реальному часі). Розробку цієї специфікації курирує спеціальна робоча група W3C WebRTC . В даний час над реалізацією її підтримки в браузерах працюють такі відомі компанії, як Google, Opera, Mozilla, а також ряд інших .

WebRTC має пряме відношення до getUserMedia () - першому API в цьому наборі. Ця технологія забезпечує доступ до потоковим даними з мікрофона і відеокамери.

підтримка

WebRTC можна включити в браузері Chrome 18.0.1008 і його більш пізніх версіях на сторінці about: flags.

Початок роботи

Завдяки navigator.getUserMedia () нарешті з'явилася можливість перехоплювати дані з веб-камер і мікрофонів безпосередньо, тобто без допомоги плагінів. Доступ до камери тепер здійснюється за запитом, і для цього нічого не потрібно встановлювати. Ця можливість вбудована в браузер, і це досить цікаво.

включення

API getUserMedia () з'явився зовсім недавно, тому він реалізований тільки в збірках для розробників Google і Opera. У Chrome 18+ його можна включити на сторінці about: flags.

У Chrome 18+ його можна включити на сторінці about: flags

Включення getUserMedia () на сторінці about: flags браузера Chrome.

Для Opera ви можете завантажити одну з експериментальних збірок для Android або звичайних комп'ютерів .

визначення можливостей

Ця перевірка дозволяє переконатися в підтримці браузером функції navigator.getUserMedia.

function hasGetUserMedia () {// Note: Opera builds are unprefixed. return !! (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); } If (hasGetUserMedia ()) {// Good to go! } Else {alert ( 'getUserMedia () is not supported in your browser'); }

Отримання доступу до пристрою введення

Для доступу до веб-камері або мікрофону необхідно запросити дозвіл. Перший параметр методу getUserMedia () визначає тип даних, до яких вони вимагають доступ. Наприклад, якщо щоб звернутися до веб-камері, необхідно задати для нього значення video. Щоб використовувати одночасно камеру і мікрофон, потрібно вказати video, audio.

<Video autoplay> </ video> <script> var onFailSoHard = function (e) {console.log ( 'Reeeejected!', E); }; // Not showing vendor prefixes. navigator.getUserMedia ( 'video, audio', function (localMediaStream) {var video = document.querySelector ( 'video'); video.src = window.URL.createObjectURL (localMediaStream); // Note: onloadedmetadata does not fire in Chrome when using it with getUserMedia. // See crbug.com/110938. video.onloadedmetadata = function (e) {// Ready to go. Do some stuff.};}, onFailSoHard); </ Script>

Отже, що ж відбувається далі? Функція захоплення даних мультимедіа - прекрасний приклад спільної роботи різних API в HTML5. Вона використовується разом з іншими елементами HTML5: <audio> і <video>. Зверніть увагу: ми не додаємо атрибут src або елементи <source> в тег <video>. Замість того щоб вказувати URL файлу мультимедіа, ми передаємо URL елемента Blob з об'єкта LocalMediaStream, який представляє веб-камеру.

Ми також додаємо для тега <video> атрибут автоматичного програвання autoplay, щоб відео не зупинилася на першому ж кадрі. Додати елементи управління також нескладно.

Увага! У Chrome є неполадка: якщо передати в якості значення параметра тільки audio, код не працює ( crbug.com/112367 ). Та ж проблема з тегом <audio> виявлена ​​і в Opera.

В Opera і Chrome реалізовані різні версії цієї специфікації , Що дещо ускладнює її практичне використання на даному етапі.

Chrome

Нижче наведено фрагмент коду для Chrome 18+ (необхідно спочатку включити цю функцію на сторінці about: flags).

navigator.webkitGetUserMedia ( 'audio, video', function (localMediaStream) {var video = document.querySelector ( 'video'); video.src = window.webkitURL.createObjectURL (localMediaStream);}, onFailSoHard);

Opera:

Складання Opera для розробників засновані на оновленій версії специфікації. Нижче наведено фрагмент коду для Opera.

navigator.getUserMedia ({audio: true, video: true}, function (localMediaStream) {video.src = localMediaStream;}, onFailSoHard);

Існує кілька ключових відмінностей.

  • У getUserMedia () не використовуються префікси.
  • Об'єкт передається як перший аргумент, а не список рядків.
  • Значення video.src присвоюється безпосередньо об'єкту LocalMediaStream, а не URL даного Blob. Наскільки мені відомо, в Opera в кінцевому підсумку буде використовуватися URL об'єкта Blob.

Крос-браузерна підтримка

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

var video = document.querySelector ( 'video'); if (navigator.getUserMedia) {navigator.getUserMedia ({audio: true, video: true}, function (stream) {video.src = stream;}, onFailSoHard); } Else if (navigator.webkitGetUserMedia) {navigator.webkitGetUserMedia ( 'audio, video', function (stream) {video.src = window.webkitURL.createObjectURL (stream);}, onFailSoHard); } Else {video.src = 'somevideo.webm'; // fallback. }

Обов'язково ознайомтеся зі статтею Майка Тейлора (Mike Taylor) і Майка Робінсона (Mike Robinson) gUM Shield . Вона допоможе усунути протиріччя в варіантах коду для різних браузерів.

Безпека

У майбутньому в браузерах при виклику методу getUserMedia (), можливо, буде з'являтися інформаційна панель, що дозволяє користувачеві надавати або заборонити доступ до камери або мікрофона. На жаль, в специфікації приділено мало уваги питанням безпеки. Поки що така панель з дозволами не реалізована.

Забезпечення зворотної сумісності

Для тих, хто не може скористатися методом getUserMedia () (наприклад, якщо цей API не підтримує або з якоїсь причини стався збій запиту), єдине рішення - використовувати існуючі відеофайли.

// Not showing vendor prefixes or code that works cross-browser: function fallback (e) {video.src = 'fallbackvideo.webm'; } Function success (stream) {video.src = window.URL.createObjectURL (stream); } If (! Navigator.getUserMedia) {fallback (); } Else {navigator.getUserMedia ({video: true}, success, fallback); }

Демонстрація основних можливостей

Захоплення відео Зупинити

знімки екрану

В API <canvas> є метод ctx.drawImage (video, 0, 0), який дозволяє легко виводити кадри <video> на елемент <canvas>. Звичайно, тепер, коли з'явилася можливість введення відео за допомогою API getUserMedia (), можна легко створити додаток типу "фотокіоск" для роботи з потоковим відео.

<Video autoplay> </ video> <img src = ""> <canvas style = "display: none;"> </ canvas> var video = document.querySelector ( 'video'); var canvas = document.querySelector ( 'canvas'); var ctx = canvas.getContext ( '2d'); var localMediaStream = null; function snapshot () {if (localMediaStream) {ctx.drawImage (video, 0, 0); // "image / webp" works in Chrome 18. In other browsers, this will fall back to image / png. document.querySelector ( 'img'). src = canvas.toDataURL ( 'image / webp'); }} Video.addEventListener ( 'click', snapshot, false); // Not showing vendor prefixes or code that works cross-browser. navigator.getUserMedia ({video: true}, function (stream) {video.src = window.URL.createObjectURL (stream); localMediaStream = stream;}, onFailSoHard); <Video autoplay> </ video> <img src = > <canvas style = display: none;> </ canvas> var video = document

захоплення Зупинити

застосування ефектів

фільтри CSS

Фільтри CSS в даний час підтримуються в "нічних" збірках WebKit і Chrome 18+.

За допомогою фільтрів CSS до елементу <video> при захопленні можна застосувати деякі ефекти.

<Style> video {width: 307px; height: 250px; background: rgba (255,255,255,0.5); border: 1px solid #ccc; } .Grayscale { + Filter: grayscale (1); } .Sepia { + Filter: sepia (1); } .Blur { + Filter: blur (3px); } ... </ style> <video autoplay> </ video> <script> var idx = 0; var filters = [ 'grayscale', 'sepia', 'blur', 'brightness', 'contrast', 'hue-rotate', 'hue-rotate2', 'hue-rotate3', 'saturate', 'invert', '']; function changeFilter (e) {var el = e.target; el.className = ''; var effect = filters [idx ++% filters.length]; // loop through filters. if (effect) {el.classList.add (effect); }} Document.querySelector ( 'video'). AddEventListener ( 'click', changeFilter, false); </ Script>

Натисніть відео, щоб ознайомитися з фільтрами CSS

Захоплення відео Зупинити

текстури WebGL

Один із чудових прикладів використання функцій захоплення відео - висновок одержуваних в режимі реального часу даних в якості текстури WebGL. Я абсолютно не розбираюся в WebGL, тому пропоную вам ознайомитися з керівництвом і демонстраційним прикладом Джерома Етьєна (Jerome Etienne). У ньому йдеться про те, як за допомогою методу getUserMedia () і скрипта Three.js виводити потокове відео в WebGL.

Використання getUserMedia з API веб-аудіо

У цьому розділі описані можливі удосконалення і поліпшення цього API.

У мене є мрія: вбудувати AutoTune в браузер, використовуючи тільки відкриті веб-технології. Вона майже здійсненна. Вже є API getUserMedia () для введення звуку з мікрофона. Досить додати ефекти реального часу за допомогою API веб-аудіо , І все буде готово. Бракує лише інтеграції цих двох рішень ( crbug.com/112404 ), Хоча попередню пропозицію вже розробляється.

Передача сигналу мікрофона в API веб-аудіо, можливо, буде коли-небудь відбуватися так, як показано нижче.

var context = new window.webkitAudioContext (); navigator.webkitGetUserMedia ({audio: true}, function (stream) {var microphone = context.createMediaStreamSource (stream); var filter = context.createBiquadFilter (); // microphone -> filter -> destination. microphone.connect (filter) ; filter.connect (context.destination);}, onFailSoHard);

Щоб побачити, як API getUserMedia () зв'язується з API веб-аудіо, зайдіть на сайт crbug.com/112404 .

висновки

В цілому віддалений доступ до пристроїв через Інтернет завжди був досить складним завданням. багато пробували розв'язати цю проблему, але мало кому вдавалося це зробити. Більшість рішень ніколи не виходило за рамки пропрієтарного програмного забезпечення, тому вони не набули широкого поширення.

Справжня проблема полягає в тому, що модель безпеки для веб-додатків сильно відрізняється від традиційної. Особисто мені не хотілося б, щоб доступ до моєї камері був у першого-ліпшого сайту. Вирішити це питання досить складно.

Об'єднані платформи, наприклад PhoneGap , Допомогли розширити межі можливого, але це лише початок, і таке рішення є тимчасовим. Щоб веб-додатки могли успішно конкурувати з традиційними рішеннями, їм необхідний доступ до апаратного забезпечення комп'ютерів.

API getUserMedia () є першою спробою доступу до нового типу пристроїв. Сподіваюся, що в найближчому майбутньому з'являться і інші рішення.

додаткові ресурси

демонстраційні приклади

Провайдеры:
  • 08.09.2015

    Batyevka.NET предоставляет услуги доступа к сети Интернет на территории Соломенского района г. Киева.Наша миссия —... 
    Читать полностью

  • 08.09.2015
    IPNET

    Компания IPNET — это крупнейший оператор и технологический лидер на рынке телекоммуникаций Киева. Мы предоставляем... 
    Читать полностью

  • 08.09.2015
    Boryspil.Net

    Интернет-провайдер «Boryspil.net» начал свою работу в 2008 году и на данный момент является одним из крупнейших поставщиков... 
    Читать полностью

  • 08.09.2015
    4OKNET

    Наша компания работает в сфере телекоммуникационных услуг, а именно — предоставлении доступа в сеть интернет.Уже... 
    Читать полностью

  • 08.09.2015
    Телегруп

    ДП «Телегруп-Украина» – IT-компания с 15-летним опытом работы на рынке телекоммуникационных услуг, а также официальный... 
    Читать полностью

  • 08.09.2015
    Софтлинк

    Высокая скоростьМы являемся участником Украинского центра обмена трафиком (UA — IX) с включением 10 Гбит / сек... 
    Читать полностью