мы хотим совершать видео-звонки из браузера удаленному абоненту, сидящему за софтфоном или устройством, поддерживающим SIP. Нужно это может быть, например, вот зачем:
- хотим сделать систему online-консультаций для интернет-магазинов, которая позволит посетителям сайта вести видео-беседу с консультантом, сидящим за привычным мессенжером.
- хотим дополнить систему телеконференций на базе Polycom возможностью подключения участников, у которых кроме браузера ничего нет.
Технологии
Я не буду полностью повторять всех выкладок из прошлой статьи, а перейду сразу к выводам. Если мы хотим, чтобы:
- поддерживались все десктопные браузеры
- не нужно было ставить дополнительный софт
- система была устойчива к помехам в сети
- задержки были минимальными
то на данный момент другого выхода, кроме как делать решения на базе Adobe Flash Player и протоколаRTMFP, у нас нет, как бы печально это ни звучало. Светлое будущее совсем не за горами: Гугл обещал в скором времени включить в Хром поддержку очень интересной технологии WebRTC, о которой я обязательно напишу в отдельной статье. Ну а пока используем то, что уже есть у пользователей.
Поддержка видео в Adobe Flash Player
Flash на данный момент умеет воспроизводить потоки, сжатые несколькими кодеками:
- H264
- Sorenson Spark H263
- On2 VP6
- Flash Screen Video
Из всего этого «богатства» нам интересен лишь H264, потому как найти поддержку остальных вариантов в софтфонах и SIP-устройствах практически нереально.
С захватом и кодированием видео с камеры все значительно хуже. Поддержка кодирования H264 появилась только в недавно вышедшей версии FP11, а до этого единственным вариантом был Sorenson Spark. 11-ая версия к сожалению пока не установлена у подавляющего большинства пользователей, поэтому приходится считаться и с теми, у кого есть только FP10.
Надо также не забывать, с кем мы имеем дело. Adobe умудрилась «сломать» воспроизведения некоторых видов H264 потоков в Flash Player версий 11.0 — 11.2. Проблема заключается в воспроизведении потоков, пакетизированных в режиме packetization-mode: 0, а именно этот режим используется большинством софтфонов. Подробности про баг можно почитать в багтрекере компании.
Итого получается следующая картина. Для успешного соединения c SIP-клиентом по H264 нам нужно:
- выполнять транскодинг Sorenson -> H264 в одну сторону, если у пользователя FP версии ниже 11
- выполнять транскодинг H264 -> H264 (для изменения пакетизации) в одну сторону, если у пользователя FP 11 с вышеупомянутым багом
- пускать трафик как есть, во всех остальных случаях.
Для транскодинга хорошо подходит связка ffmpeg и libx264. Для производительности транскодинга крайне важно наличие на сервере поддержки MMX, SSE и похожих технологии как можно более поздних версий. Видео-кодеки умеют их использовать, ускоряясь при этом в разы.
Видео — это не голос
На первый взгляд может показаться, что единственная разница между передачей видео и голоса — это ширина используемого канала. Это безусловно так, но есть еще ряд существенных отличий.
Аудио-поток обычно разбивается на кадры по 10-20 мс, каждый из которых кодируется и декодируется отдельно от остальных. Для видео это было бы слишком расточительно, поэтому для большинства кадров кодируется не само изображение, а его разница с предыдущим кадром. Для еще лучшего сжатия разница берется с немного «сдвинутым» предыдущим кадром, чтобы компенсировать движение объектов. Вообще про сжатие видео можно писать отдельный циклы статей и я не буду тут на этом останавливаться.
Важно другое. Если мы потеряли один кадр аудио-потока, то мы можем это просто замаскировать, например проиграв еще раз предыдущий кадр, и мало кто это заметит. А в видео такой трюк не пройдет, потому как последующие кадры должны быть наложены на потерянный. Отсюда появляются артефакты, которые сами не пропадут, если только не попросить удаленную сторону прислать независимо сжатый кадр (key frame). В SIP это можно сделать двумя способами: на уровне сигнализации через SIP INFO, и на уровне медиа через RTCP.
Далее необходимо учитывать ограничение на MTU канала между участниками разговора, которое обычно равно примерно 1500 байтам (на IP фрагментацию в случае NAT полагаться нельзя). Любой аудио-кадр в такое ограничение влезет, а вот видео-кадр чаще всего нет. Отсюда и возникает потребность в разбиении кадров на куски, которая называется пакетизация, с которой как раз и связан баг в некоторых версиях Flash Player.
Результат
В итоге, если аккуратненько пройтись по всем граблям, и везде подстелить необходимое количество сена, можно получить вполне работающее решение. Нам удалось интегрировать поддержку видео-звонков из браузера в нашу облачную платформу RTCKit, которая в свою очередь позволяет встроить данный функционал в любой веб-сервис за считанные часы, сэкономив при этом кучу времени.
Потестировать все это можно без регистрации на нашей тестовой странице. Разрешение для видео там ограничено 352×288. Мы тестировали софтфоны Jitsi и LinPhone, интересно было бы услышать отзывы про другие клиенты с поддержкой H264. Нагрузку от хабра-эффекта постараемся выдержать! Важное замечание: если вы звоните через RTCKit из браузера в браузер, и при этом у вас достаточно дружественный NAT, то вместо всего описанного используется технология RTMFP Peer-2-Peer.