Протокол обмена сообщениями в реальном времени (RTMP ) изначально был проприетарным протокол, разработанный Macromedia для потоковой передачи аудио, видео и данных через Интернет между проигрывателем Flash и сервером. Macromedia теперь принадлежит Adobe, которая выпустила неполную версию спецификации протокола для публичного использования.
Протокол RTMP имеет несколько разновидностей:
В то время как основной мотивацией RTMP было протокол для воспроизведения Flash-видео, он также используется в некоторых других приложениях, таких как Adobe LiveCycle Data Services ES.
RTMP - это протокол на основе TCP, который поддерживает обеспечивает постоянные соединения и обеспечивает связь с малой задержкой. Для бесперебойной доставки потоков и передачи как можно большего количества информации потоки разбиваются на фрагменты, и их размер динамически согласовывается между клиентом и сервером. Иногда его оставляют без изменений; размеры фрагментов по умолчанию составляют 64 байта для аудиоданных и 128 байтов для видеоданных и большинства других типов данных. Затем фрагменты из разных потоков могут чередоваться и мультиплексироваться через одно соединение. Таким образом, с более длинными фрагментами данных протокол переносит только однобайтовый заголовок на фрагмент, поэтому возникают очень небольшие накладные расходы. Однако на практике отдельные фрагменты обычно не чередуются. Вместо этого перемежение и мультиплексирование выполняются на уровне пакетов, при этом пакеты RTMP по нескольким различным активным каналам перемежаются таким образом, чтобы гарантировать соответствие каждого канала своей пропускной способности, задержке и другим требованиям к качеству обслуживания. Пакеты, перемежаемые таким образом, рассматриваются как неделимые и не перемежаются на уровне фрагментов.
RTMP определяет несколько виртуальных каналов, по которым пакеты могут отправляться и приниматься и которые работают независимо друг от друга. Например, есть канал для обработки запросов и ответов RPC, канал для данных видеопотока, канал для данных аудиопотока, канал для сообщений внеполосного управления (согласование размера фрагмента и т. Д.) И т. Д.. Во время типичного сеанса RTMP несколько каналов могут быть активны одновременно в любой момент времени. Когда данные RTMP кодируются, генерируется заголовок пакета. Заголовок пакета определяет, среди прочего, идентификатор канала, по которому он должен быть отправлен, метку времени, когда он был сгенерирован (при необходимости), и размер полезной нагрузки пакета. Затем за этим заголовком следует фактическое содержимое полезной нагрузки пакета, которое перед отправкой по соединению фрагментируется в соответствии с согласованным в настоящее время размером фрагмента. Сам заголовок пакета никогда не фрагментируется, и его размер не учитывается в данных в первом фрагменте пакета. Другими словами, фрагментации подвержена только фактическая полезная нагрузка пакета (мультимедийные данные).
На более высоком уровне RTMP инкапсулирует MP3 или AAC аудио и FLV1 видео потоки мультимедиа и может выполнять удаленную процедуру вызывает (RPC), используя формат сообщения действия . Любые требуемые службы RPC выполняются асинхронно с использованием единой модели запрос / ответ клиент / сервер, так что связь в реальном времени не требуется.
Сеансы RTMP могут быть зашифрованы с использованием любого из два метода:
В RTMP Туннелированные (RTMPT), данные RTMP инкапсулированы и обмениваются через HTTP, а сообщения от клиента (в данном случае медиаплеера) адресованы на порт 80 (по умолчанию для HTTP) на сервере.
Хотя сообщения в RTMPT больше, чем эквивалентные сообщения RTMP без туннелирования из-за заголовков HTTP, RTMPT может облегчить использование RTMP в сценариях, где использование RTMP без туннелирования в противном случае было бы невозможно, например например, когда клиент находится за брандмауэром , который блокирует исходящий трафик, отличный от HTTP и HTTPS.
Протокол работает, отправляя команды через URL-адрес POST и сообщения AMF через тело POST. Например,
POST / open / 1 HTTP / 1.1
для открытия соединения.
Adobe выпустила спецификацию для версии 1.0 протокола от 21 декабря 2012 г. На целевой веб-странице, ведущей к этой спецификации, отмечается, что «В интересах клиентов, которые хотят для защиты их содержания открытая спецификация RTMP не включает уникальные меры безопасности RTMP Adobe ».
Документ, сопровождающий спецификацию Adobe, предоставляет« неисключительный, бесплатный, непередаваемый, не подлежащий сублицензированию, персональный, всемирный «патентная лицензия на все реализации протокола, с двумя ограничениями: одно запрещает использование для перехвата потоковых данных (« любая технология, которая перехватывает потоковое видео, аудио и / или содержимое данных для хранения на любом устройстве или носителе »), а другой запрещает обход «технологических мер защиты аудио, видео и / или содержимого данных, включая любые меры безопасности RTMP Adobe».
Стефан Рихтер, автор какого-то бу ks on Flash, в 2008 году отметил, что, хотя Adobe нечетко указывает, какие патенты применяются к RTMP, США Патент 7 246 356, кажется, является одним из них.
В 2011 году Adobe подала в суд на Wowza Media Systems, заявив, среди прочего, о нарушении их патентов на RTMP. В 2015 году Adobe и Wowza объявили, что судебные процессы были урегулированы и отклонены с предубеждением.
Пакеты отправляются через TCP-соединение, которое сначала устанавливается между клиентом и сервером.. Они содержат заголовок и тело, которое в случае команд соединения и управления кодируется с использованием формата сообщения действия (AMF). Заголовок разделен на основной заголовок (показанный на схеме отдельно от остальных) и заголовок сообщения фрагмента. Основной заголовок является единственной постоянной частью пакета и обычно состоит из одного составного байта, где два наиболее значимых бита - это тип блока (fmt в спецификации), а остальные образуют идентификатор потока. В зависимости от значения первого, некоторые поля заголовка сообщения могут быть опущены, а их значение получено из предыдущих пакетов, в то время как в зависимости от значения последнего базовый заголовок может быть расширен одним или двумя дополнительными байтами (как в случае диаграммы, содержащей всего три байта (c)). Если значение оставшихся шести битов основного заголовка (BH) (наименее значимое) равно 0, то BH составляет два байта и представляет от идентификатора потока 64 до 319 (64 + 255); если значение равно 1, то BH составляет три байта (последние два байта закодированы как 16-битный Little Endian) и представляет от идентификатора потока 64 до 65599 (64 + 65535); если значение равно 2, то BH составляет один байт и зарезервирован для сообщений и команд управления протоколом низкого уровня. Заголовок сообщения фрагмента содержит информацию о метаданных, такую как размер сообщения (измеряется в байтах), разность отметок времени и тип сообщения. Это последнее значение представляет собой один байт и определяет, является ли пакет звуковым, видео, командным или «низкоуровневым» пакетом RTMP, таким как RTMP Ping.
Пример показан ниже, когда клиент флэш-памяти выполняет следующий код:
var stream: NetStream = new NetStream (connectionObject);
будет сгенерирован следующий блок:
шестнадцатеричный код | ASCII |
---|---|
0300 0B 68 00 00 19 1400 00 00 00 0200 0C 63 72 65 61 74 65 53 74 72 65 61 6D 00 40 00 00 00 00 00 00 00 05 | ␃␀ @ I ␀ ␀ ␙ ␔␀ ␀ ␀ ␀ ␂␀ ␌ create S tream ␀ @ ␀ ␀ ␀ ␀ ␀ ␀ ␀ ␅ |
Пакет начинается с базового заголовка из одного байта (0x03), где два старших бита (b 00 000011) определяют тип заголовка блока, равный 0, а остальные ( b00 000011 ) определяют идентификатор потока фрагментов, равный 3. Четыре возможных значения типа заголовка и их значения:
Последний тип (b11) всегда используется в случае агрегированных сообщений, где в приведенном выше примере второе сообщение будет начинаться с идентификатора 0xC3 (b11000011) и будет означать, что все поля заголовка сообщения должны быть получены из сообщение с идентификатором потока 3 (которое будет сообщением прямо над ним). Шесть младших значащих битов, образующих идентификатор потока, могут принимать значения от 3 до 63. Некоторые значения имеют особое значение, например 1, обозначающее расширенный формат идентификатора, и в этом случае за ним будут следовать два байта. Значение два предназначено для сообщений низкого уровня, таких как Ping и Set Client Bandwidth.
Следующие байты заголовка RTMP (включая значения в приведенном выше примере пакета) декодируются следующим образом:
Байт идентификатора типа сообщения определяет, содержит ли пакет аудио / видеоданные, удаленный объект или команду. Вот некоторые возможные значения:
После заголовка 0x02 обозначает строку размером 0x000C и значениями 0x63 0x72... 0x6D (команда «createStream»). После этого у нас есть 0x00 (число), которое является идентификатором транзакции со значением 2.0. Последний байт - 0x05 (ноль), что означает отсутствие аргументов.
Некоторые из типов сообщений, показанных выше, такие как Ping и Set Client / Server Bandwidth, считаются сообщениями протокола RTMP низкого уровня, которые не используют Формат кодирования AMF. С другой стороны, командные сообщения, будь то AMF0 (тип сообщения 0x14) или AMF3 (0x11), используют формат и имеют общую форму, показанную ниже:
(String)(Number) (Смешанный) напр. Null, String, Object: {key1: value1, key2: value2...}
Идентификатор транзакции используется для команд, которые могут иметь ответ. Значение может быть либо строкой, как в приведенном выше примере, либо одним или несколькими объектами, каждый из которых состоит из набора пар ключ / значение, где ключи всегда кодируются как строки, а значения могут быть любым типом данных AMF, включая сложные типы, такие как массивы.
Управляющие сообщения не кодируются AMF. Они начинаются с идентификатора потока 0x02, что подразумевает полный заголовок (тип 0) и имеет тип сообщения 0x04. За заголовком следуют шесть байтов, которые интерпретируются как таковые:
Первые два байта тела сообщения определяют тип Ping, который, очевидно, может принимать шесть возможных значений.
Pong - это имя для ответа на эхо-запрос со значениями, указанными выше.
Это относится к сообщениям, которые имеют отношение к скорости передачи данных восходящего и нисходящего потоков клиента. Тело состоит из четырех байтов, показывающих значение полосы пропускания с возможным расширением на один байт, который устанавливает тип ограничения. Он может иметь одно из трех возможных значений: жесткий, мягкий или динамический (мягкий или жесткий).
Значение, полученное в четырех байтах тела. Существует значение по умолчанию 128 байтов, и сообщение отправляется только тогда, когда требуется изменение.
После установления TCP-соединения сначала устанавливается соединение RTMP, которое выполняет рукопожатие посредством обмена тремя пакетами с каждой стороны (также упоминается как Чанки в официальной документации). В официальной спецификации они упоминаются как C0-2 для пакетов, отправленных клиентом, и S0-2 для стороны сервера соответственно, и их не следует путать с пакетами RTMP, которыми можно обмениваться только после завершения рукопожатия. Эти пакеты имеют собственную структуру, а C1 содержит поле, устанавливающее временную метку «эпохи», но, поскольку это может быть установлено в ноль, как это сделано в реализациях сторонних производителей, пакет можно упростить. Клиент инициализирует соединение, отправляя пакет C0 с постоянным значением 0x03, представляющим текущую версию протокола. Он следует прямо с C1, не дожидаясь получения S0 первым, который содержит 1536 байтов, причем первые четыре представляют временную метку эпохи, вторые четыре все равны 0, а остальные являются случайными (и которые могут быть установлены на 0 в третьей стороне реализации). C2 и S2 являются эхо-сигналом S1 и C1 соответственно, за исключением того, что вторые четыре байта являются временем получения соответствующего сообщения (вместо 0). После получения C2 и S2 рукопожатие считается завершенным.
На этом этапе клиент и сервер могут согласовать соединение, обмениваясь сообщениями с кодировкой AMF. К ним относятся пары ключ-значение, которые относятся к переменным, которые необходимы для установления соединения. Пример сообщения от клиента:
(Invoke) "connect" (Transaction ID) 1.0 (Object1) {app: "sample", flashVer: "MAC 10,2,153,2", swfUrl: null, tcUrl: " rtmpt: //127.0.0.1/sample ", fpad: false, возможности: 9947.75, audioCodecs: 3191, videoCodecs: 252, videoFunction: 1, pageUrl: null, objectEncoding: 3.0}
Сервер Flash Media и другие реализации используют концепция «приложения» для концептуального определения контейнера для аудио / видео и другого контента, реализованного как папка в корне сервера, которая содержит медиафайлы для потоковой передачи. Первая переменная содержит имя этого приложения как «образец», которое является именем, предоставленным сервером Wowza для их тестирования. Строка flashVer
аналогична строке, возвращаемой функцией Action-script getversion ()
. audioCodec
и videoCodec
кодируются как двойные, и их значение можно найти в исходной спецификации. То же самое верно и для переменной videoFunction
, которая в данном случае является самоочевидной константой SUPPORT_VID_CLIENT_SEEK. Особый интерес представляет objectEncoding
, который определяет, будет ли остальная часть обмена данными использовать расширенный формат AMF3 или нет. Поскольку версия 3 является текущей версией по умолчанию, флэш-клиент должен явно указать в коде сценария действия использовать AMF0, если это требуется. Затем сервер отвечает последовательностью сообщений ServerBW, ClientBW и SetPacketSize, за которыми, наконец, следует Invoke с примером сообщения.
(Invoke) "_result" (идентификатор транзакции) 1.0 (Object1) {fmsVer: "FMS / 3,5,5,2004", возможности: 31.0, режим: 1.0} (Object2) {level: "status", код: "NetConnection.Connect.Success", описание: "Соединение успешно", данные: (массив) {версия: "3,5,5,2004"}, clientId: 1728724019, objectEncoding: 3.0}
Некоторые из значения, указанные выше, сериализованы в свойства универсального объекта Action-script, который затем передается в прослушиватель событий NetConnection. clientId
устанавливает номер для сеанса, который будет запущен соединением. Кодировка объекта должна соответствовать ранее установленному значению.
Чтобы запустить видеопоток, клиент отправляет вызов createStream, за которым следует сообщение проверки связи, за которым следует вызов «play» с именем файла в качестве аргумента. Затем сервер ответит серией команд onStatus, за которыми следуют видеоданные, инкапсулированные в сообщениях RTMP.
После того, как соединение установлено, медиа отправляется путем инкапсуляции содержимого тегов FLV в сообщения RTMP типа 8 и 9 для аудио и видео соответственно.
Это относится к версии протокола с HTTP-туннелированием. Он обменивается данными через порт 80 и передает данные AMF внутри запроса и ответов HTTP POST. Последовательность подключения следующая:
POST / fcs / identify2 HTTP / 1.1 Content-Type: application / x-fcs \ r \ n HTTP / 1.0 404 Not Found
POST / open / 1 HTTP / 1.1 Content -Type: application / x-fcs \ r \ n HTTP / 1.1 200 OK Content-Type: application / x-fcs \ r \ n 1728724019
Первый запрос имеет путь / fcs / identify2
и правильный ответ - ошибка 404 Not Found. Затем клиент отправляет запрос / open / 1, на который сервер должен ответить сообщением 200 ok, добавив случайное число, которое будет использоваться в качестве идентификатора сеанса для указанного сообщения. В этом примере в теле ответа возвращается 1728724019.
POST / idle / 1728724019/0 HTTP / 1.1 HTTP / 1.1 200 OK 0x01
С этого момента / idle /
является запросом на опрос, в котором идентификатор сеанса был сгенерирован и возвращен из server, а последовательность - это просто число, которое увеличивается на единицу для каждого запроса. Соответствующий ответ - 200 OK с целым числом, возвращенным в теле, обозначающим интервал времени. Данные AMF отправляются через / send /
RTMP реализуется на трех этапах:
Инструмент командной строки клиента RTMP с открытым исходным кодом rtmpdump предназначен для воспроизведения или сохраните на диск полный поток RTMP, включая протокол RTMPE, который Adobe использует для шифрования. RTMPdump работает в Linux, Android, Solaris, Mac OS X и большинстве других операционных систем, производных от Unix, а также в Microsoft Windows. Первоначально поддерживая все версии 32-битной Windows, включая Windows 98, начиная с версии 2.2 программное обеспечение будет работать только в Windows XP и выше (хотя более ранние версии остаются полностью функциональными).
Пакеты программного обеспечения rtmpdump доступны в основных репозиториях с открытым исходным кодом (дистрибутивы GNU / Linux). К ним относятся интерфейсные приложения «rtmpdump», «rtmpsrv» и «rtmpsuck».
Разработка RTMPdump была возобновлена в октябре 2009 г. за пределами США, на сайте MPlayer. В текущей версии значительно улучшены функциональные возможности, и она была переписана, чтобы воспользоваться преимуществами языка программирования C. В частности, основная функциональность была встроена в библиотеку (librtmp), которую могут легко использовать другие приложения. Разработчики RTMPdump также написали поддержку librtmp для MPlayer, FFmpeg, XBMC, cURL, VLC и ряд других программных проектов с открытым исходным кодом. Использование librtmp обеспечивает этим проектам полную поддержку RTMP во всех его вариантах без каких-либо дополнительных усилий по разработке.
FLVstreamer - это форк RTMPdump без кода, который, по утверждению Adobe, нарушает DMCA в США. Это было разработано как ответ на попытку Adobe в 2008 году подавить RTMPdump. FLVstreamer - это клиент RTMP, который сохраняет поток аудио- или видеоконтента с любого сервера RTMP на диск, если шифрование (RTMPE) не включено в потоке.