| 通信プロトコル | |
| 略語 | RTMP |
|---|---|
| 目的 | ストリーミング |
| 開発者 | マクロメディア |
| 導入 | () |
| に基づく | TCP |
| OSI層 | アプリケーション層(7) |
| ポート | tcp/1935 |
リアルタイムメッセージングプロトコル(RTMP)は、インターネット経由で音声、動画、およびデータをストリーミングするための通信プロトコルです。元々はMacromedia社がFlash PlayerとFlash Communication Server間のストリーミング用に独自プロトコルとして開発しましたが、 Adobe社(Macromedia社を買収)は、このプロトコルの不完全な仕様を一般向けに公開しました。
RTMP プロトコルには複数のバリエーションがあります。
RTMP の主な目的はFlash Video を再生するためのプロトコルでしたが、 Adobe LiveCycle Data Services ESなどの他のアプリケーションでも使用されています。
RTMPは、持続的な接続を維持し、低遅延通信を可能にするTCPベースのプロトコルです。ストリームをスムーズに配信し、可能な限り多くの情報を送信するために、ストリームをフラグメントに分割し、そのサイズはクライアントとサーバー間で動的にネゴシエートされます。フラグメントのサイズは変更されない場合もあります。デフォルトのフラグメントサイズは、オーディオデータの場合は64バイト、ビデオデータおよび他のほとんどのデータタイプの場合は128バイトです。異なるストリームからのフラグメントはインターリーブされ、単一の接続で多重化されます。したがって、データチャンクが長い場合、プロトコルはフラグメントごとに1バイトのヘッダーのみを伝送するため、オーバーヘッドはごくわずかです。ただし、実際には、個々のフラグメントは通常インターリーブされません。代わりに、インターリーブと多重化はパケットレベルで行われ、複数の異なるアクティブチャネルにまたがるRTMPパケットは、各チャネルが帯域幅、遅延、その他のサービス品質要件を満たすようにインターリーブされます。このようにインターリーブされたパケットは不可分なものとして扱われ、フラグメントレベルではインターリーブされません。
RTMPは、パケットを送受信できる複数の仮想チャネルを定義しており、これらのチャネルは互いに独立して動作します。例えば、RPCリクエストとレスポンスを処理するチャネル、ビデオストリームデータ用のチャネル、オーディオストリームデータ用のチャネル、帯域外制御メッセージ(フラグメントサイズネゴシエーションなど)用のチャネルなどがあります。一般的なRTMPセッションでは、複数のチャネルが同時にアクティブになる場合があります。RTMPデータがエンコードされると、パケットヘッダーが生成されます。パケットヘッダーには、送信先のチャネルのID、生成時刻のタイムスタンプ(必要な場合)、パケットのペイロードサイズなどが指定されます。このヘッダーの後には、パケットの実際のペイロードコンテンツが続きます。ペイロードコンテンツは、接続を介して送信される前に、合意されたフラグメントサイズに従ってフラグメント化されます。パケットヘッダー自体はフラグメント化されず、そのサイズはパケットの最初のフラグメントのデータにはカウントされません。つまり、実際のパケット ペイロード (メディア データ) のみが断片化の対象となります。
より高レベルでは、RTMPはMP3またはAACオーディオ、FLV1ビデオなどのマルチメディアストリームをカプセル化し、アクションメッセージフォーマット(Action Message Format )を使用してリモートプロシージャコール(RPC)を行うことができます。必要なRPCサービスは、単一のクライアント/サーバー要求/応答モデルを使用して非同期的に実行されるため、リアルタイム通信は必要ありません。[ 3 ] [ 4 ]
RTMP セッションは、次の 2 つの方法のいずれかを使用して暗号化できます。
RTMP Tunneled (RTMPT) では、RTMP データはカプセル化されてHTTP経由で交換され、クライアント (この場合はメディア プレーヤー) からのメッセージはサーバー上のポート 80 (HTTP のデフォルト) に送信されます。
RTMPT のメッセージは HTTP ヘッダーのため、同等の非トンネル RTMP メッセージよりも大きくなりますが、クライアントが非HTTP および非 HTTPS の送信トラフィックをブロックする ファイアウォールの背後にある場合など、非トンネル RTMP を使用できないシナリオでは、RTMPT によって 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年に、Adobeはどの特許がRTMPに適用されるかについては曖昧だが、米国特許7,246,356がその1つであるようだと指摘した。[ 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 パケットのいずれであるかを定義します。
以下に、フラッシュ クライアントが次のコードを実行したときにキャプチャされた例を示します。
var stream : NetStream =新しいNetStream ( connectionObject );これにより、次のチャンクが生成されます。
| 16進コード | アスキー |
|---|---|
03 00 0B 68 00 00 19 14 00 00 00 00 0200 0C63 72 65 61 74 65 53 74 72 65 61 6D 00 40 00 00 00 00 00 00 00 05 | ␃ ␀ @ I ␀ ␀ ␙ ␔ ␀ ␀ ␀ ␀ ␂␀ ␌c r e a t e S t r e a m ␀ @ ␀ ␀ ␀ ␀ ␀ ␀ ␀ ␅ |
パケットは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」コマンド)の文字列を表します。その後ろには0x00(数値)があり、これは値が2.0のトランザクションIDです。最後のバイトは0x05(null)で、これは引数がないことを意味します。
上記で示した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タイプを定義し、明らかに6つの値を取ることができる[ 12 ]。
Pongは Ping への応答の名前であり、使用される値は上記のとおりです。
これは、クライアントのアップストリームおよびサーバーのダウンストリームのビットレートに関するメッセージです。本体は帯域幅の値を示す4バイトで構成され、制限タイプを設定する1バイトの拡張バイトが含まれる場合があります。制限タイプは、ハード、ソフト、またはダイナミック(ソフトまたはハード)の3つの値のいずれかになります。
本文の4バイトで受信される値。デフォルト値は128バイトで、変更が必要な場合にのみメッセージが送信されます。

TCP接続を確立した後、まずRTMP接続が確立され、各側から3つのパケット(公式ドキュメントではチャンクとも呼ばれます)を交換することでハンドシェイクが行われます。公式仕様では、これらのパケットは、クライアント側が送信したパケットはC0-2、サーバー側はS0-2と呼ばれています。ハンドシェイク完了後にのみ交換可能なRTMPパケットとは混同しないでください。これらのパケットは独自の構造を持ち、C1には「エポック」タイムスタンプを設定するフィールドが含まれていますが、サードパーティの実装と同様に、この値は0に設定できるため、パケットは簡素化されます。クライアントは、現在のプロトコルバージョンを表す定数値0x03を含むC0パケットを送信することで接続を初期化します。S0の受信を待たずに、C1に直接送信されます。S0は1536バイトで構成され、最初の4バイトはエポックタイムスタンプ、次の4バイトはすべて0、残りはランダムです(サードパーティの実装では0に設定できます)。 C2とS2はそれぞれS1とC1のエコーですが、2番目の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列は、ActionScriptgetversion()関数によって返されるものと同じです。audioCodecと はdouble型videoCodecとしてエンコードされており、その意味は元の仕様に記載されています。変数についても同様で、この場合はSUPPORT_VID_CLIENT_SEEK定数です。特に注目すべきは、残りの通信で拡張AMF3形式を使用するかどうかを定義する です。現在のデフォルトはバージョン3であるため、Flashクライアントは、AMF0が要求された場合、ActionScriptコードで明示的にAMF0を使用するように指示する必要があります。サーバーは、ServerBW、ClientBW、SetPacketSizeのメッセージシーケンスで応答し、最後にサンプルメッセージを含むInvokeが続きます。 videoFunctionobjectEncoding
(呼び出し) "_result" (トランザクションID ) 1.0 (オブジェクト1 ) { fmsVer : "FMS/3,5,5,2004" 、機能: 31.0 、モード: 1.0 } (オブジェクト2 ) {レベル: "status" 、コード: "NetConnection.Connect.Success" 、説明: "接続に成功しました" 、データ: (配列) {バージョン: "3,5,5,2004" }、クライアントID : 1728724019 、オブジェクトエンコーディング: 3.0 }上記の値の一部は、汎用アクションスクリプトオブジェクトのプロパティにシリアル化され、NetConnectionイベントリスナーに渡されます。これにより、clientId接続によって開始されるセッションの番号が確立されます。オブジェクトのエンコーディングは、以前に設定された値と一致する必要があります。
ビデオストリームを開始するには、クライアントは「createStream」呼び出しを送信し、その後にpingメッセージを送信し、さらにファイル名を引数として「play」呼び出しを送信します。サーバーは、一連の「onStatus」コマンドと、RTMPメッセージにカプセル化されたビデオデータを返信します。
接続が確立されると、FLV タグの内容を、それぞれオーディオとビデオのタイプ 8 と 9 の RTMP メッセージにカプセル化してメディアが送信されます。
これは、プロトコルのHTTPトンネリングバージョンを指します。ポート80を介して通信し、AMFデータをHTTP POSTリクエストとレスポンスに含めて渡します。接続シーケンスは以下のとおりです。
POST /fcs/ident2 HTTP / 1.1コンテンツタイプ: application/x-fcs\r\n HTTP/1.0 404 見つかりません POST /open/1 HTTP / 1.1コンテンツタイプ: 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を返さなければなりません。この200 okには、当該通信のセッション識別子として使用される乱数が付加されます。この例では、レスポンスボディに1728724019が返されます。
POST /idle/1728724019/0 HTTP / 1.1 HTTP/1.1 200 OK 0x01ここからは/idle/<session id>/<sequence #>ポーリングリクエストとなり、セッションIDはサーバーから生成され返されます。シーケンスはリクエストごとに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は、Adobeが米国でDMCAに違反していると主張するコードを含まないRTMPdumpのフォークです。これは、2008年にAdobeがRTMPdumpを抑制しようとしたことへの対応として開発されました。FLVstreamerは、ストリームで暗号化(RTMPE)が有効になっていない場合、任意のRTMPサーバーからのオーディオまたはビデオコンテンツのストリームをディスクに保存するRTMPクライアントです。
上記のバリエーションはRTMPをベースに追加されたものです。しかし、FLVとRTMPのコーデックの選択肢が限られているため、業界ではフォーマットとプロトコルに直接機能を追加する必要がありました。
RTMPは、サポートするコーデックのセットを識別するために、標準のFourCCではなく、独自の4ビット「コーデックID」を内部的に使用します。オーディオコーデックIDとビデオコーデックIDは異なる名前空間に属するとみなされるため、同じ値を使用しても競合は発生しません。例えば、Adobeのベースライン標準では、オーディオコーデック7はG.711A、ビデオコーデック7はH.264です。
中国では、Kingsoft Cloudが2018年にH.265をビデオコーデック「12」に割り当て、すぐにビリビリなどの業界関係者にも採用されました。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ソフトウェア組織によって公開されました。
E-RTMP で導入された機能強化には次のものが含まれます。
VideoPacketType.Metadataあらゆるビデオメタデータをアクションメッセージフォーマット(AMF)で書き込むことを可能にします。(AMFは、FLVビデオストリームの一部としてではなく、プロトコルメッセージング層の従来のRTMPで使用されます。)E-RTMPは、既存のRTMP実装との相互運用性を確保しながら、RTMPの機能を強化します。例えば、従来のデコーダーは予約済み(「新しい」)ヘッダーを含むフレームをデコードする方法を認識できませんが、それでも適切に転送することは可能です。
E-RTMPではFLVフォーマット層に多くの変更が加えられているため、E-RTMPにはE-RTMPとは独立して使用できるFLVファイルフォーマットの拡張機能も含まれています。ffmpegはこのフォーマットを「拡張FLV」と呼んでいます。[ 15 ]
プロデューサー:
インジェスター:
インジェスター、拡張 FLV のみ: