リアルタイムメッセージングプロトコル(RTMP)は、インターネット上で音声、動画、データをストリーミング配信するための通信プロトコルです。元々はマクロメディア社がFlash PlayerとFlash Communication Server間のストリーミング配信用に独自に開発したプロトコルでしたが、マクロメディア社を買収したアドビ社が、プロトコルの仕様書の不完全なバージョンを一般向けに公開しました。
RTMPプロトコルには複数のバリエーションが存在する。
RTMPの主な目的はFlashビデオを再生するためのプロトコルとして開発されたものですが、 Adobe LiveCycle Data Services ESなどの他のアプリケーションでも使用されています。
RTMPは、永続的な接続を維持し、低遅延通信を可能にするTCPベースのプロトコルです。ストリームをスムーズに配信し、できるだけ多くの情報を送信するために、ストリームをフラグメントに分割し、そのサイズはクライアントとサーバー間で動的にネゴシエートされます。場合によっては、サイズは変更されません。デフォルトのフラグメントサイズは、オーディオデータの場合は64バイト、ビデオデータおよびその他のほとんどのデータタイプの場合は128バイトです。異なるストリームからのフラグメントは、インターリーブされ、単一の接続上で多重化される場合があります。データチャンクが長い場合、プロトコルはフラグメントごとに1バイトのヘッダーのみを伝送するため、オーバーヘッドはごくわずかです。ただし、実際には、個々のフラグメントは通常インターリーブされません。代わりに、インターリーブと多重化はパケットレベルで行われ、複数の異なるアクティブチャネルにわたるRTMPパケットは、各チャネルが帯域幅、遅延、およびその他のサービス品質要件を満たすようにインターリーブされます。このようにインターリーブされたパケットは分割不可能なものとして扱われ、フラグメントレベルではインターリーブされません。
RTMPは、パケットの送受信に使用できる複数の仮想チャネルを定義しており、これらのチャネルは互いに独立して動作します。たとえば、RPC要求と応答を処理するチャネル、ビデオストリームデータ用のチャネル、オーディオストリームデータ用のチャネル、帯域外制御メッセージ(フラグメントサイズネゴシエーションなど)用のチャネルなどがあります。通常のRTMPセッションでは、複数のチャネルが同時にアクティブになることがあります。RTMPデータがエンコードされると、パケットヘッダーが生成されます。パケットヘッダーには、送信先のチャネルID、生成日時(必要な場合)、パケットのペイロードサイズなどが指定されます。このヘッダーの後には、パケットの実際のペイロードコンテンツが続きます。ペイロードコンテンツは、接続を介して送信される前に、現在合意されているフラグメントサイズに従ってフラグメント化されます。パケットヘッダー自体はフラグメント化されず、そのサイズはパケットの最初のフラグメントのデータには含まれません。つまり、フラグメント化されるのは実際のパケットペイロード(メディアデータ)のみです。
より高レベルでは、RTMPはMP3またはAACオーディオとFLV1ビデオマルチメディアストリームをカプセル化し、アクションメッセージフォーマットを使用してリモートプロシージャコール(RPC)を行うことができます。必要なRPCサービスはすべて非同期で行われ、単一のクライアント/サーバー要求/応答モデルを使用するため、リアルタイム通信は必要ありません。[ 3 ] [ 4 ]
RTMPセッションは、以下の2つの方法のいずれかを使用して暗号化できます。
RTMPトンネル(RTMPT)では、RTMPデータはカプセル化され、HTTPを介して交換されます。クライアント(この場合はメディアプレーヤー)からのメッセージは、サーバー上のポート80(HTTPのデフォルトポート)に送信されます。
RTMPTのメッセージはHTTPヘッダーがあるため、同等の非トンネルRTMPメッセージよりも大きくなりますが、RTMPTは、非トンネルRTMPの使用が不可能なシナリオ、例えばクライアントが非HTTPおよび非HTTPSの送信トラフィックをブロックするファイアウォールの背後にある場合などに、RTMPの使用を容易にする可能性があります。
このプロトコルは、POST URL を介してコマンドを送信し、POST ボディを介して AMF メッセージを送信することで機能します。例は次のとおりです。
POST /open/1 HTTP/1.1
接続を開くため。
Adobeは、2012年12月21日付けでプロトコルのバージョン1.0の仕様を公開しました。[ 5 ]その仕様へのリンクとなるウェブランディングページには、「コンテンツを保護したいお客様のために、オープンRTMP仕様にはAdobe独自のセキュアRTMP対策は含まれていません」と記載されています。[ 6 ]
Adobeの仕様書に付属する文書では、プロトコルのすべての実装に対して「非独占的、ロイヤリティフリー、譲渡不可、再許諾不可、個人的、世界的」な特許ライセンスを付与しているが、2つの制限がある。1つはストリーミングデータの傍受(「ストリーミングビデオ、オーディオ、および/またはデータコンテンツを傍受してデバイスまたはメディアに保存するあらゆる技術」)に使用することを禁止し、もう1つは「オーディオ、ビデオ、および/またはデータコンテンツの保護のための技術的措置(AdobeのセキュアRTMP措置を含む)」を回避することを禁止している。[ 7 ]
Flashに関する書籍を何冊か執筆しているステファン・リヒターは、2008年に、アドビはRTMPに適用される特許について曖昧な説明をしているが、米国特許第7,246,356号はその一つであると思われると指摘した。[ 3 ]
2011年、AdobeはWowza Media Systemsを提訴し、RTMP特許の侵害などを主張した。[ 8 ] [ 9 ] [ 10 ] 2015年、AdobeとWowzaは訴訟が和解し、棄却されたと発表した。[ 11 ]

パケットは、クライアントとサーバー間で最初に確立される TCP 接続を介して送信されます。パケットにはヘッダーとボディが含まれており、接続コマンドと制御コマンドの場合は、アクション メッセージ フォーマット(AMF) を使用してエンコードされます。ヘッダーは、基本ヘッダー(図では他の部分から切り離して示されています) とチャンク メッセージ ヘッダーに分割されます。基本ヘッダーはパケットの唯一の固定部分であり、通常は 1 つの複合バイトで構成され、最上位 2 ビットがチャンク タイプ (仕様ではfmt ) であり、残りがストリーム ID を形成します。前者の値に応じて、メッセージ ヘッダーの一部のフィールドを省略し、その値を以前のパケットから取得できます。一方、後者の値に応じて、基本ヘッダーに 1 バイトまたは 2 バイトを追加できます (合計 3 バイト (c) の図の場合)。基本ヘッダー(BH)の残りの 6 ビット (最下位ビット) の値が0 の場合、BH は 2 バイトで、ストリーム ID 64 から 319 (64+255) を表します。値が 1 の場合、BH は 3 バイト (最後の 2 バイトは 16 ビット リトルエンディアンでエンコード) で、ストリーム ID 64 から 65599 (64+65535) を表します。値が 2 の場合、BH は 1 バイトで、低レベルのプロトコル制御メッセージとコマンド用に予約されています。チャンク メッセージ ヘッダーには、メッセージ サイズ (バイト単位)、タイムスタンプ デルタ、メッセージタイプなどのメタデータ情報が含まれています。この最後の値は 1 バイトで、パケットがオーディオ、ビデオ、コマンド、または RTMP Ping などの「低レベル」RTMP パケットであるかどうかを定義します。
以下に、Flashクライアントが以下のコードを実行した際にキャプチャされた例を示します。
var stream : NetStream =新しいNetStream ( connectionObject );これにより、以下のチャンクが生成されます。
パケットは、1バイトの基本ヘッダー(0x03)で始まります。このヘッダーの最上位2ビット(b 00 000011)はチャンクヘッダータイプ0を定義し、残りのビット(b00 000011)はチャンクストリームID 3を定義します。ヘッダータイプの4つの可能な値とその重要度は次のとおりです。
最後のタイプ (b11) は、集約メッセージの場合に常に使用されます。上記の例では、2 番目のメッセージの ID は 0xC3 (b11000011) で始まり、すべてのメッセージ ヘッダー フィールドはストリーム ID が 3 のメッセージ (そのすぐ上のメッセージ) から派生する必要があることを意味します。ストリーム ID を構成する最下位 6 ビットは、3 ~ 63 の値を取ることができます。一部の値には特別な意味があり、たとえば 1 は拡張 ID フォーマットを表し、その場合は 2 バイトが続きます。値 2 は、Ping や Set Client Bandwidth などの低レベル メッセージ用です。
RTMPヘッダーの次のバイト(上記のサンプルパケットの値を含む)は、次のようにデコードされます。
メッセージタイプIDバイトは、パケットに音声/ビデオデータ、リモートオブジェクト、またはコマンドが含まれているかどうかを定義します。考えられる値は次のとおりです。
ヘッダーに続いて、0x02 はサイズ 0x000C の文字列で、値は 0x63 0x72 ... 0x6D ("createStream" コマンド) です。その次に、トランザクション ID の値 2.0 である 0x00 (数値) があります。最後のバイトは 0x05 (ヌル) で、引数がないことを意味します。
上記に示したメッセージタイプの中には、PingやSet Client/Server Bandwidthなど、AMFエンコーディング形式を使用しない低レベルのRTMPプロトコルメッセージとみなされるものがあります。一方、コマンドメッセージは、AMF0(メッセージタイプ0x14)でもAMF3(0x11)でも、AMF形式を使用し、以下に示す一般的な形式をとります。
(文字列) <コマンド名> (番号)<取引ID> (混合)<引数> 例:null、文字列、オブジェクト:{key1:value1, key2:value2 ... } トランザクションIDは、応答を伴うコマンドに使用されます。値は、上記の例のような文字列、または1つ以上のオブジェクトのいずれかになります。各オブジェクトは、キーと値のペアのセットで構成され、キーは常に文字列としてエンコードされ、値は配列などの複雑な型を含む、任意のAMFデータ型にすることができます。
制御メッセージはAMFエンコードされていません。ストリームIDは0x02で始まり、これは完全な(タイプ0)ヘッダーを意味し、メッセージタイプは0x04です。ヘッダーの後には6バイトが続き、これらは次のように解釈されます。
メッセージ本文の最初の 2 バイトは Ping タイプを定義し、これは明らかに[ 12 ] 6 つの可能な値を取ることができます。
PongはPingに対する応答の名称であり、上記の値が使用されます。
これは、クライアントのアップストリームとサーバーのダウンストリームのビットレートに関するメッセージです。本文は帯域幅の値を示す4バイトで構成され、制限タイプを設定する1バイトの拡張が含まれる場合があります。制限タイプには、ハード、ソフト、ダイナミック(ソフトまたはハードのいずれか)の3つの値のいずれかを指定できます。
受信値は、メッセージ本文の4バイトに格納されます。デフォルト値は128バイトで、変更が必要な場合にのみメッセージが送信されます。

TCP接続を確立した後、まずRTMP接続が確立され、両側から3つのパケット(公式ドキュメントではチャンクとも呼ばれる)を交換するハンドシェイクが実行されます。これらは公式仕様では、クライアント側が送信するパケットはC0-2、サーバー側はS0-2と呼ばれ、ハンドシェイクが完了した後にのみ交換できるRTMPパケットと混同しないように注意が必要です。これらのパケットは独自の構造を持ち、C1には「エポック」タイムスタンプを設定するフィールドが含まれていますが、サードパーティの実装で行われているように、これをゼロに設定できるため、パケットを簡略化できます。クライアントは、現在のプロトコルバージョンを表す定数値0x03を含むC0パケットを送信して接続を初期化します。S0が最初に受信されるのを待たずに、C1を直接送信します。C1には1536バイトが含まれており、最初の4バイトはエポックタイムスタンプを表し、次の4バイトはすべて0で、残りはランダムです(サードパーティの実装では0に設定できます)。 C2とS2はそれぞれS1とC1のエコーであり、ただし後半の4バイトは(0ではなく)それぞれのメッセージが受信された時刻を表します。C2とS2が受信されると、ハンドシェイクは完了したとみなされます。
この時点で、クライアントとサーバーはAMFエンコードされたメッセージを交換することで接続を確立できます。これらのメッセージには、接続確立に必要な変数に関連するキーと値のペアが含まれます。クライアントからのメッセージの例は次のとおりです。
(呼び出し) "connect" (トランザクションID ) 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-scriptgetversion()関数によって返されるものと同じです。audioCodecおよびはdouble 型videoCodecとしてエンコードされ、その意味は元の仕様で確認できます。変数についても同様で、この場合は説明不要なSUPPORT_VID_CLIENT_SEEK定数です。特に注目すべきは、残りの通信で拡張AMF3フォーマットを使用するかどうかを定義するです。バージョン 3 が現在のデフォルトであるため、Action-script コードで、AMF0 が要求された場合は、Flash クライアントに明示的に AMF0 を使用するように指示する必要があります。その後、サーバーは ServerBW、ClientBW、SetPacketSize メッセージ シーケンスで応答し、最後に Invoke が続き、例のメッセージが返されます。videoFunctionobjectEncoding
(呼び出し) "_result" (トランザクションID ) 1.0 (オブジェクト1 ) { fmsVer : "FMS/3,5,5,2004" , capabilities : 31.0 , mode : 1.0 } (オブジェクト2 ) { level : "status" , code : "NetConnection.Connect.Success" , description : "接続成功" , data : (配列) { version : "3,5,5,2004" }, clientId : 1728724019 , objectEncoding : 3.0 }上記の値の一部は、汎用アクションスクリプトオブジェクトのプロパティにシリアル化され、その後、NetConnectionイベントリスナーに渡されます。これにより、clientId接続によって開始されるセッションの番号が設定されます。オブジェクトのエンコーディングは、以前に設定された値と一致する必要があります。
ビデオストリームを開始するには、クライアントは「createStream」呼び出し、続いてpingメッセージ、そしてファイル名を引数として指定した「play」呼び出しを送信します。サーバーは、一連の「onStatus」コマンドと、RTMPメッセージにカプセル化されたビデオデータで応答します。
接続が確立されると、FLVタグの内容をオーディオ用とビデオ用それぞれタイプ8とタイプ9のRTMPメッセージにカプセル化することで、メディアが送信されます。
これは、HTTPトンネル版プロトコルを指します。ポート80を介して通信し、 HTTP POSTリクエストとレスポンスの中にAMFデータを渡します。接続手順は以下のとおりです。
POST /fcs/ident2 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 コンテンツタイプ: 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 OK 0x01今後は、セッションIDが/idle/<session id>/<sequence #>サーバーから生成されて返されるポーリングリクエストであり、シーケンスはリクエストごとに1ずつ増加する単なる数値です。適切なレスポンスは200 OKで、本文にはインターバル時間を示す整数が返されます。AMFデータは、/send/<session id>/<sequence #>
RTMPは以下の3つの段階で実装されます。
オープンソースのRTMPクライアントコマンドラインツールrtmpdumpは、Adobeが暗号化に使用するRTMPEプロトコルを含む、RTMPストリーム全体を再生またはディスクに保存するように設計されています。RTMPdumpは、Linux、Android、Solaris、 Mac OS X、その他のほとんどのUnix系オペレーティングシステム、およびMicrosoft Windowsで動作します。当初はWindows 98を含むすべての32ビット版Windowsをサポートしていましたが、バージョン2.2以降はWindows XP以降でのみ動作します(ただし、以前のバージョンも完全に機能します)。
rtmpdumpソフトウェアスイートのパッケージは、主要なオープンソースリポジトリ(Linuxディストリビューション)で入手可能です。これには、フロントエンドアプリケーションである「rtmpdump」、「rtmpsrv」、「rtmpsuck」が含まれます。
RTMPdump の開発は、2009 年 10 月に米国以外でMPlayerサイトにて再開されました。[ 13 ]現在のバージョンでは機能が大幅に改善され、 C プログラミング言語の利点を活用するために書き直されました。特に、主要な機能はライブラリ (librtmp) に組み込まれ、他のアプリケーションから簡単に使用できるようになりました。RTMPdump の開発者は、MPlayer、FFmpeg、XBMC、cURL、VLC、およびその他の多数のオープンソース ソフトウェア プロジェクト向けに librtmp のサポートも作成しました。librtmp を使用することで、これらのプロジェクトは追加の開発作業なしに、すべてのバリアントの RTMP を完全にサポートできます。
FLVstreamerはRTMPdumpのフォーク版で、Adobeが米国DMCAに違反すると主張するコードは含まれていません。これは、2008年にAdobeがRTMPdumpを抑制しようとしたことへの対応として開発されました。FLVstreamerはRTMPクライアントであり、ストリームで暗号化(RTMPE)が有効になっていない場合、任意のRTMPサーバーからのオーディオまたはビデオコンテンツのストリームをディスクに保存します。
上記のバリアントはRTMPの上に追加されたものです。しかし、FLVとRTMPのコーデック選択肢が限られているため、業界はフォーマットとプロトコルに直接機能を追加する必要に迫られました。
RTMPは、サポートするコーデックセットを識別するために、標準のFourCCではなく、独自の4ビットの「コーデックID」を内部的に使用します。オーディオとビデオのコーデックIDは異なる名前空間に属するとみなされるため、同じ値を使用しても競合は発生しません。たとえば、Adobeのベースライン標準では、オーディオコーデック7はG.711A、ビデオコーデック7はH.264です。
中国では、Kingsoft Cloudが2018年にH.265をビデオコーデック「12」に割り当て、この慣行はすぐにBilibiliなどの他の業界プレーヤーにも受け入れられた。2020年には、ZLMediaKitのXia ChuがOpusをオーディオコーデック13に割り当てた。[ 14 ]
E-RTMPによって、コード化されたIDフィールドへのアドホックな追加機能はすべて廃止されました。E-RTMPはID 12と13を再利用しないため、中国のアドホック拡張機能との互換性が確保されています。
拡張RTMP(E-RTMP)は、リアルタイムメッセージングプロトコル(RTMP)およびFLV仕様の拡張であり、既存のRTMPインフラストラクチャとの互換性を維持しながらストリーミングワークフローを最新化します。[ 2 ]オープン仕様として開発されたE-RTMPは、 Adobe、Google、Twitchなどの貢献を受けてVeovera Software Organizationによって公開されました。
E-RTMPで導入された機能強化には以下が含まれます。
VideoPacketType.Metadata(AMF)で任意のビデオメタデータを書き込むことができます。(AMFは、FLVビデオストリームの一部としてではなく、オリジナルのRTMPのプロトコルメッセージング層で使用されます。)E-RTMPは、RTMPの機能を強化しつつ、既存のRTMP実装との相互運用性を確保します。例えば、従来のデコーダは予約済み(「新規」)ヘッダーを含むフレームをデコードする方法を知りませんが、それでも適切に転送することは可能です。
E-RTMPではFLVフォーマットレイヤーに多くの変更が加えられているため、E-RTMPにはE-RTMPとは独立して使用できるFLVファイルフォーマットの拡張機能も含まれています。ffmpegはこのフォーマットを「拡張FLV」と呼んでいます。[ 15 ]
プロデューサー:
摂取者:
摂取者、強化FLVのみ: