Real-Time Messaging Protocol ( RTMP ) — это протокол связи для потоковой передачи аудио, видео и данных через Интернет. Первоначально разработанный как фирменный протокол Macromedia для потоковой передачи между Flash Player и Flash Communication Server, Adobe (которая приобрела Macromedia) выпустила неполную версию спецификации протокола для публичного использования.
Протокол RTMP имеет несколько разновидностей:
Хотя основной целью создания RTMP было создание протокола для воспроизведения Flash-видео , он также используется в некоторых других приложениях, таких как Adobe LiveCycle Data Services ES .
RTMP — это протокол на основе TCP, который поддерживает постоянные соединения и обеспечивает связь с малой задержкой. Для бесперебойной доставки потоков и передачи как можно большего количества информации он разбивает потоки на фрагменты, и их размер динамически согласовывается между клиентом и сервером. Иногда он остается неизменным; размеры фрагментов по умолчанию составляют 64 байта для аудиоданных и 128 байтов для видеоданных и большинства других типов данных. Затем фрагменты из разных потоков могут чередоваться и мультиплексироваться по одному соединению. При более длинных фрагментах данных протокол, таким образом, несет только однобайтовый заголовок на фрагмент, поэтому несет очень мало накладных расходов . Однако на практике отдельные фрагменты обычно не чередуются. Вместо этого чередование и мультиплексирование выполняются на уровне пакетов, при этом пакеты RTMP по нескольким различным активным каналам чередуются таким образом, чтобы гарантировать, что каждый канал соответствует своей пропускной способности, задержке и другим требованиям к качеству обслуживания. Пакеты, чередующиеся таким образом, рассматриваются как неделимые и не чередуются на уровне фрагментов.
RTMP определяет несколько виртуальных каналов, по которым пакеты могут отправляться и приниматься, и которые работают независимо друг от друга. Например, есть канал для обработки запросов и ответов RPC, канал для данных видеопотока, канал для данных аудиопотока, канал для внеполосных управляющих сообщений (согласование размера фрагмента и т. д.) и т. д. Во время типичного сеанса RTMP несколько каналов могут быть активны одновременно в любой момент времени. Когда данные RTMP кодируются, генерируется заголовок пакета. Заголовок пакета указывает, среди прочего, идентификатор канала, по которому он должен быть отправлен, временную метку, когда он был сгенерирован (при необходимости), и размер полезной нагрузки пакета. Затем за этим заголовком следует фактическое содержимое полезной нагрузки пакета, которое фрагментируется в соответствии с согласованным в данный момент размером фрагмента, прежде чем оно будет отправлено по соединению. Сам заголовок пакета никогда не фрагментируется, и его размер не учитывается в данных в первом фрагменте пакета. Другими словами, фрагментации подвергается только фактическая полезная нагрузка пакета (медиаданным).
На более высоком уровне RTMP инкапсулирует аудио MP3 или AAC и видео потоки мультимедиа FLV1 и может выполнять удаленные вызовы процедур (RPC) с использованием формата Action Message Format . Все требуемые RPC-сервисы выполняются асинхронно, с использованием единой модели клиент/сервер запрос/ответ, так что коммуникация в реальном времени не требуется. [ требуется пояснение ] [2] [3]
Сеансы RTMP могут быть зашифрованы одним из двух методов:
В RTMP Tunneled (RTMPT) данные RTMP инкапсулируются и передаются через HTTP , а сообщения от клиента (в данном случае медиаплеера) адресуются на порт 80 (по умолчанию для HTTP) на сервере.
Хотя сообщения в RTMPT больше, чем эквивалентные нетуннелированные сообщения RTMP из-за заголовков HTTP, RTMPT может облегчить использование RTMP в сценариях, где использование нетуннелированного RTMP в противном случае было бы невозможно, например, когда клиент находится за брандмауэром, блокирующим исходящий трафик, отличный от HTTP и HTTPS.
Протокол работает путем отправки команд через POST URL и сообщений AMF через тело POST. Примером является
ОТПРАВИТЬ /открыть/1 HTTP/1.1
для открытия соединения.
Adobe выпустила спецификацию для версии 1.0 протокола от 21 декабря 2012 года. [4] На целевой веб-странице, ведущей к этой спецификации, отмечается, что «Чтобы принести пользу клиентам, желающим защитить свой контент, открытая спецификация RTMP не включает уникальные меры безопасности RTMP от Adobe». [5]
Документ, сопровождающий спецификацию Adobe, предоставляет «неисключительную, безвозмездную, непередаваемую, несублицензируемую, персональную, всемирную» патентную лицензию на все реализации протокола с двумя ограничениями: одно запрещает использование для перехвата потоковых данных («любая технология, которая перехватывает потоковое видео, аудио и/или содержимое данных для хранения на любом устройстве или носителе»), а другое запрещает обход «технологических мер по защите аудио, видео и/или содержимого данных, включая любые меры безопасности RTMP компании Adobe». [6]
Стефан Рихтер, автор нескольких книг о Flash , в 2008 году отметил, что, хотя Adobe неясно, какие патенты применяются к RTMP, патент США 7,246,356, по-видимому, является одним из них. [2]
В 2011 году Adobe подала в суд на Wowza Media Systems, заявив, среди прочего, о нарушении их патентов RTMP. [7] [8] [9] В 2015 году Adobe и Wowza объявили, что иски были урегулированы и отклонены с предубеждением. [10]
Пакеты отправляются по 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.
Ниже показан пример, полученный при выполнении Flash-клиентом следующего кода:
поток вар : NetStream = новый NetStream ( connectionObject );
это сгенерирует следующий фрагмент:
Пакет начинается с базового заголовка из одного байта (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), используют формат и имеют общую форму, показанную ниже:
(Строка) <Имя команды>(Номер) <Идентификатор транзакции>(Смешанный) <Аргумент> например, Null, String, Object: {key1:value1, key2:value2 ... }
Идентификатор транзакции используется для команд, которые могут иметь ответ. Значение может быть либо строкой, как в примере выше, либо одним или несколькими объектами, каждый из которых состоит из набора пар ключ/значение, где ключи всегда кодируются как строки, а значения могут быть любым типом данных AMF, включая сложные типы, такие как массивы.
Управляющие сообщения не кодируются AMF. Они начинаются с идентификатора потока 0x02, что подразумевает полный заголовок (тип 0), и имеют тип сообщения 0x04. За заголовком следуют шесть байтов, которые интерпретируются следующим образом:
Первые два байта тела сообщения определяют тип пинга, который, по-видимому [11], может принимать шесть возможных значений.
Pong — это название ответа на Ping, значения которого указаны выше.
Это относится к сообщениям, которые связаны с клиентским восходящим потоком и серверным нисходящим потоком бит-рейта. Тело состоит из четырех байтов, показывающих значение пропускной способности, с возможным расширением одного байта, который устанавливает тип ограничения. Он может иметь одно из трех возможных значений: жесткое, мягкое или динамическое (мягкое или жесткое).
Значение, полученное в четырех байтах тела. Существует значение по умолчанию в 128 байтов, и сообщение отправляется только тогда, когда требуется изменение.
После установления TCP-соединения сначала устанавливается RTMP-соединение, выполняя рукопожатие посредством обмена тремя пакетами с каждой стороны (также называемыми Chunks в официальной документации). Они упоминаются в официальной спецификации как C0-2 для отправленных клиентом пакетов и S0-2 для серверной стороны соответственно и их не следует путать с пакетами RTMP, обмен которыми возможен только после завершения рукопожатия. Эти пакеты имеют собственную структуру, и C1 содержит поле, устанавливающее временную метку «эпохи», но поскольку его можно установить равным нулю, как это делается в сторонних реализациях, пакет можно упростить. Клиент инициализирует соединение, отправляя пакет C0 с постоянным значением 0x03, представляющим текущую версию протокола. Он следует сразу за C1, не дожидаясь получения S0, который содержит 1536 байтов, причем первые четыре представляют временную метку эпохи, вторые четыре все равны 0, а остальные являются случайными (и которые можно установить равными 0 в сторонних реализациях). C2 и S2 являются эхом S1 и C1 соответственно, за исключением того, что вторые четыре байта являются временем получения соответствующего сообщения (вместо 0). После получения C2 и S2 рукопожатие считается завершенным.
На этом этапе клиент и сервер могут договориться о соединении, обмениваясь сообщениями в кодировке AMF . Они включают пары ключ-значение, которые относятся к переменным, необходимым для установления соединения. Пример сообщения от клиента:
( Вызов ) "connect" ( Идентификатор транзакции ) 1.0 ( Объект1 ) { app : "sample" , flashVer : "MAC 10,2,153,2" , swfUrl : null , tcUrl : "rtmpt://127.0.0.1/sample " , fpad : false , capabilities : 9947.75 , audioCodecs : 3191 , videoCodecs : 252 , videoFunction : 1 , pageUrl : null , objectEncoding : 3.0 }
Flash Media Server и другие реализации используют концепцию «приложения» для концептуального определения контейнера для аудио/видео и другого контента, реализованного как папка в корне сервера, которая содержит медиафайлы для потоковой передачи. Первая переменная содержит имя этого приложения как «sample», которое является именем, предоставленным Wowza Server для их тестирования. Строка flashVer
та же, что возвращается функцией Action-script getversion()
. audioCodec
И videoCodec
кодируются как двойные числа , и их значение можно найти в исходной спецификации. То же самое верно для переменной videoFunction
, которая в данном случае является самоочевидной константой SUPPORT_VID_CLIENT_SEEK. Особый интерес представляет , objectEncoding
которая будет определять, будет ли остальная часть коммуникации использовать расширенный формат AMF3 или нет. Поскольку версия 3 является текущей версией по умолчанию, Flash-клиенту необходимо явно указать в коде Action-script использовать AMF0, если это запрошено. Затем сервер отвечает последовательностью сообщений ServerBW, ClientBW и SetPacketSize, за которыми следует Invoke с примером сообщения.
( Invoke ) "_result" ( идентификатор транзакции ) 1.0 ( Object1 ) { fmsVer : "FMS/3,5,5,2004" , возможности : 31.0 , режим : 1.0 } ( Object2 ) { уровень : "status" , код : "NetConnection.Connect.Success" , описание : "Подключение успешно установлено" , данные : ( array ) { версия : "3,5,5,2004" }, clientId : 1728724019 , objectEncoding : 3.0 }
Некоторые значения выше сериализуются в свойства универсального объекта Action-script, который затем передается прослушивателю событий NetConnection. Он clientId
установит номер сеанса, который будет запущен соединением. Кодировка объекта должна соответствовать ранее установленному значению.
Чтобы начать видеопоток, клиент отправляет вызов "createStream", за которым следует сообщение ping, за которым следует вызов "play" с именем файла в качестве аргумента. Затем сервер ответит серией команд "onStatus", за которыми последуют видеоданные, инкапсулированные в сообщениях RTMP.
После установления соединения медиаданные отправляются путем инкапсуляции содержимого тегов FLV в сообщения RTMP типа 8 и 9 для аудио и видео соответственно.
Это относится к HTTP-туннелированной версии протокола. Он взаимодействует через порт 80 и передает данные AMF внутри HTTP-запроса POST и ответов. Последовательность для подключения следующая:
POST /fcs/ident2 HTTP / 1.1 Тип содержимого : application/x-fcs\r\nHTTP/1.0 404 Не найдено
POST /open/1 HTTP / 1.1 Тип содержимого : application/x-fcs\r\nHTTP/1.1 200 ОКТип содержимого: application/x-fcs\r\n 1728724019
Первый запрос имеет /fcs/ident2
путь, а правильный ответ — ошибка 404 Not Found. Затем клиент отправляет запрос /open/1, на который сервер должен ответить 200 ok, добавив случайное число, которое будет использоваться в качестве идентификатора сеанса для указанного сообщения. В этом примере в теле ответа возвращается 1728724019.
POST /idle/1728724019/0 HTTP / 1.1 HTTP/1.1 200 ОК 0x01
С этого момента это /idle/<session id>/<sequence #>
запрос на опрос, где идентификатор сеанса был сгенерирован и возвращен с сервера, а последовательность — это просто число, которое увеличивается на единицу для каждого запроса. Соответствующий ответ — 200 OK, с целым числом, возвращаемым в теле, обозначающим интервал времени. Данные AMF отправляются через/send/<session id>/<sequence #>
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 доступны в основных репозиториях с открытым исходным кодом (дистрибутивы Linux). К ним относятся фронтенд-приложения "rtmpdump", "rtmpsrv" и "rtmpsuck".
Разработка RTMPdump была возобновлена в октябре 2009 года за пределами США на сайте MPlayer . [12] Текущая версия отличается значительно улучшенной функциональностью и была переписана для использования преимуществ языка программирования C. В частности, основная функциональность была встроена в библиотеку (librtmp), которая может легко использоваться другими приложениями. Разработчики RTMPdump также написали поддержку librtmp для MPlayer , FFmpeg , XBMC , cURL , VLC и ряда других проектов программного обеспечения с открытым исходным кодом. Использование librtmp обеспечивает этим проектам полную поддержку RTMP во всех его вариантах без каких-либо дополнительных усилий по разработке.
FLVstreamer — это форк RTMPdump, без кода, который, по утверждению Adobe, нарушает DMCA в США. Он был разработан в ответ на попытку Adobe в 2008 году подавить RTMPdump. FLVstreamer — это RTMP-клиент, который сохраняет поток аудио- или видеоконтента с любого RTMP-сервера на диск, если шифрование (RTMPE) для потока не включено.
Контейнер Flash-видео в RTMP ограничен кодеком H264 в большинстве реализаций. По этой причине Veovera Software Organization, включая Adobe , Google и Veriskope, опубликовала расширенную спецификацию RTMP, [13] которая добавляет поддержку кодеков VP9 , H265 и AV1 в контейнер Flash-видео FLV .
{{cite journal}}
: Цитировать журнал требует |journal=
( помощь )