
RTMP(real time messaging protocol)協議
本文為Adobe rtmp規范1.0的中文介紹,其中內容大部分都是翻譯自rtmp官方檔案rtmp_specification_1.0.pdf
具體文章目錄參見文章內側邊欄
介紹
Adobe的實時訊息傳輸協議(RTMP)通過可靠的流傳輸(如TCP [RFC0793])提供雙向訊息多路傳輸服務,用于在端到端之間傳輸帶有時序資訊的視頻,音頻和資料訊息的并行流, 穿過多層流,RTMP訊息塊流不提供任何控制的優先級別和相似形式,但是可以用于高層協議提供這樣的優先級,例如:一段實時視頻服務會選擇丟棄給緩慢的客戶的視頻資訊確保音頻資訊可以及時被接收,RTMP訊息塊流包含它自己的入隊協議控制訊息,也提供一個高層協議機制用于嵌入用戶的控制訊息,
定義
有效負載:Payload
包含在包中的資料,就像音頻樣本或者壓縮的視頻資料,
包:Packet
一個資料包由固定的包頭和有效負載資料組成,一些底層協議或許需要包的封裝來被定義,
埠:Port
在TCP/IP協議中定義的用正整數表示的埠號用于在傳輸中提取以區分目標主機的不同應用,用于OSI傳輸層的傳輸選擇(TSEL)就是埠,
傳輸地址:Transport address
網路地址和埠的組合識別一個傳輸層終端埠,例如一個IP地址和TCP埠,資料包從一個源傳輸層地址傳送到目標段的傳輸層地址,
訊息流:Message stream
一個通信的邏輯通道,允許訊息流通,
訊息流ID:Message stream ID
每一個訊息擁有一個分配的ID識別跟隨的訊息流,
訊息塊:Chunk
訊息的片段,訊息被分成小的部分,在他們在網路中發送之前交叉存盤,訊息塊確保定制時間戳的端到端全訊息傳送,穿過多層流,
訊息塊流:Chunk stream
一個通信的邏輯通道,允許訊息塊在一個特定的方向上流通,訊息塊流可以從客戶端傳送到服務器,也可以相反,
訊息塊流ID:Chunk stream ID
每一個訊息塊有一個分配的ID用于識別更隨的訊息塊流,
復合技術:Multiplexing
把分開的音視頻資料組合成一條音視頻流的程序,使同時傳送許多音視頻資料成為可能,
逆復合技術:DeMultiplexing
復合的反向程序,交叉存取組裝的音頻視頻資料,使他們成為最初的音視頻資料
遠程程序呼叫:Remote Procedure Call (RPC)
允許客戶端或服務器在對等端呼叫子例程或程序的請求,
Action Message Format (AMF)
一種緊湊的二進制格式,用于序列化ActionScript object graphs, 可以透過 AMF overHTTP的方式將flash端資料編碼后傳回server,server端的remoting adaptor接收到資料后則會譯碼回正確的native物件,交給正確的程式處理,
位元組順序,對齊和時間格式
所有的整數欄位都被引入到了位元組順序當中,位元組0是第一個顯示出來的,也是一個詞和一個欄位中最重要的,這種順序就是通常所說的“大端”,如果沒有特殊說明,在本檔案中數字常量都是用十進制表示,
除另有規定外,RTMP中的所有資料都是位元組對齊的,例如,一個16位欄位可能處于奇數位元組偏移處, 在指定填充的地方,填充位元組應該是0,
RTMP中的時間戳相對于未指定的時期是以整數毫秒為單位給出的, 通常,每個流將以時間戳0開始,但這不是必需的,只要兩個終端在時間點上達成一致, 請注意,這意味著跨多個流(尤其是來自不同主機)的任何同步都需要一些RTMP外的其他機制,
時間戳必須始終在線性的增加,允許應用程式處理異步傳輸,帶寬度量,檢測,和流控制,
由于時間戳長度為32位,因此它們每隔49天,17小時,2分鐘,47.296秒滾動一次, 由于流可以連續運行,可能持續數年,RTMP應用程式應該在處理時間戳時使用序列號演算法[RFC1982],并且應該能夠處理回繞, 例如,假定所有相鄰的時間戳都在2^31 - 1毫秒之間,所以10000會在4000000000之后,而3000000000會在4000000000之前,
時間戳增量delta也被指定為相對于先前時間戳的無符號整數毫秒數, 時間戳增量delta可以是24位或32位,
RTMP塊流
本節介紹實時訊息傳送協議塊流(RTMP塊流), 它為更高級別的多媒體流協議提供復用和打包服務, 雖然RTMP Chunk Stream旨在與實時訊息傳送協議配合使用,但它可以處理發送訊息流的任何協議, 每條訊息都包含時間戳和有效負載型別標識, RTMP Chunk Stream和RTMP一起適用于各種音頻 - 視頻應用,從一對一和一對多實時廣播到視頻點播服務,再到互動式會議應用,
當與可靠的傳輸協議(如TCP [RFC0793])一起使用時,RTMP塊流提供了保證所有訊息在多個流中按時間排序的端到端傳送, RTMP塊流不提供任何優先級或類似的控制形式,但可以由更高級別的協議提供這種優先級,
訊息格式
可以拆分成塊以支持復用的訊息格式取決于更高級別的協議, 但是,訊息格式應該包含下列創建塊所必需的欄位,
時間戳:
訊息的時間戳,這個欄位可以傳輸4個位元組,
長度:
訊息的有效負載的長度,如果訊息頭不能被省略,它應該包含在長度中,這個欄位在訊息塊包頭中占有3個位元組,
型別ID:
協議控制訊息的型別欄位的范圍是被保留的,這些傳播資訊的訊息由RTMP訊息塊和高層協議處理,所有其他的型別ID可被高層協議使用,對RTMP訊息塊來說當做不透明的值,實際上,RTMP Chunk Stream中的任何內容都不需要將這些值用作型別; 所有(非協議)訊息可以是相同型別的,或者應用程式可以使用型別id來區分同步蹤跡而不是型別, 該欄位占用塊頭中的1個位元組,
訊息流ID:
訊息流ID可以是任意的值, 復合到相同塊流上的不同訊息流可以基于它們的訊息流ID進行逆復合操作, 除此之外,就RTMP塊流而言,這是一個不透明的值, 該欄位以小尾數格式占用塊頭中的4個位元組,
握手
RTMP連接始于握手, rtmp握手與其他協議的握手不同; 它由三個相同大小的塊組成,而不是由可變大小的塊組成,
客戶端(連接已初始化的終端)和服務器都發送相同的三個塊, 為了說明,由客戶端發送的3個塊分別為C0, C1, C2,由服務端發送的3個塊分別為S0, S1, S2,
握手的順序
握手以客戶端發送C0和C1訊息塊位開始,客戶端必須等到S1到達在發送C2,客戶端必須等到S2接收到才可以發送其他的資料;服務端必須等到C0到達才發送S0和S1,在C1之后也會等待,服務端必須等到C1到達才發送S2,服務端必須等到C2到達后才發送其他資料,
C0和S0格式
C0和S0都是單個8位位元組,可以看成一個8位整形欄位,

8位元版本:在C0中,這個欄位識別客戶端需求的RTMP的版本,在S0中,這個欄位識別服務器端選擇的RTMP的版本,被定義的是版本3,0到2是早前的版本使用的,4到31保留用于未來使用,32到255還沒有被允許,不能區分客戶的請求的版本的服務應該以3回傳,客戶端可以選擇降級到版本3,或放棄握手,
C1和S1格式
C1和S1包長度為1536個8位位元組,包含以下欄位:

time(4個位元組):這個欄位包含時間戳,被當做后續訊息塊從終端發送的時間點,也許是0,或者一些任意的值,為了同步多路訊息塊流,終端或許希望發送其他訊息塊流的時間戳的當前值,
zero(4各個位元組):這個欄位必須全0,
random data(1528個位元組):這個欄位可以包含任何任意的值,因為每個終端必須區分自己初始化的握手的回傳資料和對方初始化的握手的回傳資料,這個資料應該發送一些亂數,但是沒有必要用密碼保護亂數和動態值,
C2和S2格式
C2和S2包長度為1536個8位位元組,分別類似于S1和C1的原樣回傳,由一下幾個欄位組成:

time(4個位元組):
這個欄位必須包含由對端發送的S1(對應C2)或者C1(對應S2)的時間戳.
time2(4個位元組):
這個欄位必須包含先前的由對端發送的資料包(S1或者C1)被讀取的時間戳,
random echo(1528個位元組):
這個欄位必須包含在對端發送的S1(對應C2)或S2(對應C1)資料包中的隨機資料欄位, 任何一方都可以使用time和time2欄位與當前時間戳一起快速估算連接的帶寬和/或延遲,但這不太可能有用,
握手程序圖

下面的表格描述了握手程序的幾個階段
| 階段 | 描述 |
|---|---|
| 未初始化 | 協議版本在此階段發送, 客戶端和服務器都未初始化, 客戶端發送資料包C0中的協議版本, 如果服務器支持該版本,則發送S0和S1作為回應, 否則,服務器將采取適當的措施進行回應, 在RTMP中,此操作正在終止連接, |
| 版本發送 | 在未初始化狀態之后,客戶端和服務器都處于版本已發送狀態, 客戶端正在等待資料包S1,服務器正在等待資料包C1, 在接收到等待的資料包時,客戶端發送C2并且服務器發送S2, 狀態然后變成Ack發送, |
ACK發送 |
客戶端和服務端分別等待S2和C2, |
| 握手完成 | 客戶端和服務交換訊息, |
訊息分塊
握手后,連接復用一個或多個訊息塊流,每個塊流從一個訊息流攜帶一種型別的訊息,每個創建的塊都有一個與其關聯的唯一ID,稱為塊流ID,這些塊通過網路傳輸,發送時,每個塊必須在下一個塊之前全部發送,在接收端,根據塊流ID將塊組合成訊息,
分塊允許將較高級別協議中的大的型訊息分解為較小的訊息,例如防止較大的低優先級訊息(例如視頻)阻塞較小的高優先級訊息(如音頻或控制),
分塊還允許以較少的開銷發送小訊息,因為分塊頭包含資訊的壓縮表示資訊,這些壓縮訊息本來應該包含在訊息本身的,
塊大小是可配置的,它可以使用Set Chunk Size控制訊息進行設定,
訊息塊格式
每一個訊息塊有頭部和資料組成,頭部自身可以被分割成三個部分:

訊息塊基本頭(1到3個位元組):這個欄位編碼了訊息塊流的ID和訊息塊的型別,訊息塊型別決定了訊息包頭的編碼格式,長度完全取決于可變長的訊息塊流ID,
訊息塊訊息頭(0,3,7或11位元組):這個欄位編碼正在傳送的訊息的資訊,長度可以利用在訊息塊頭中詳細的訊息塊型別來決定,
擴展時間戳(0或4位元組):此欄位在某些情況下是存在的,取決于訊息塊訊息頭中的編碼時間戳或時間戳增量欄位,
訊息塊塊資料(可變大小):該塊的有效負載,直至配置的最大塊大小,
訊息塊基本頭
訊息塊基本頭對訊息塊流的ID和訊息塊的型別進行編碼(在下面的圖表中用fmt表示),訊息塊型別決定了編碼的訊息頭的格式,訊息塊基本頭欄位可以是1,2或者3個位元組長,取決于訊息塊流ID,
該協議支持多達65597個ID為3-65599的流, ID0,1和2被保留, 值0指示2位元組形式和64-319范圍內的ID(the second byte + 64), 值1表示3位元組形式,ID在64-65599((the third byte) * 256 + the second byte + 64)范圍內, 在3-63范圍內的值表示完整的流ID, 塊ID為2的流ID保留,用于低級別的協議控制訊息和命令,
在訊息塊基本頭中0-5位元(最不重要的)代表了訊息塊流ID,
訊息塊流ID 2-63 可以被編碼成這個欄位的單位元組的版本號,

塊流ID 64-319可以以2位元組的形式被編碼, ID計算為(第二個位元組+ 64),

可以在此欄位的3位元組版本中對塊流ID 64-65599進行編碼, ID計算為((第三位元組)* 256 +(第二位元組)+64),

cs id(6位元):這個欄位包含了訊息塊流ID,值從2到63,值0和1用于代表這個欄位的2個或者3個位元組的版本號,
fmt(2位元):這個欄位標識訊息塊訊息頭使用的四種格式之一,見下一小節
cs id -64(8或者16個位元):
這個欄位包含了訊息塊流ID減64,例如ID 365在cs id段用1表示,在16位元的cs id -64段用301表示,
值為64到319的訊息塊流ID可以被2位元組或者3位元組的版本號來表示,
訊息塊訊息頭
在訊息塊訊息頭中有四種不同的格式,由訊息塊基本頭的fmt欄位選擇,應該使用最簡潔的表達方式表示每一個訊息塊訊息頭,
型別0
型別0的訊息塊有11個位元組長,這個型別必須在訊息塊流開始時和訊息流的時間戳回溯時使用

時間戳(3個位元組):對于型別0的塊,訊息的絕對時間戳發送到此處, 如果時間戳大于或等于16777215(十六進制0xFFFFFF),則該欄位必須是16777215,表示存在擴展時間戳欄位以編碼完整的32位時間戳, 否則,這個欄位應該是整個時間戳,
型別1
型別1的訊息塊有7個位元組長,訊息流ID沒有被包含,這個訊息塊得到和先前訊息塊同樣的流ID,帶有可變長的訊息的流(例如許多視頻格式)在型別0訊息塊后應該使用這種格式作為每一個訊息的第一個訊息塊,

型別2
型別2塊頭長度為3個位元組, 流ID和訊息長度都不包含在內; 該塊與前面的塊具有相同的流ID和訊息長度, 具有固定大小訊息的流(例如,某些音頻和資料格式)應該在第一個訊息之后使用這種格式作為每個訊息的第一個塊,

型別3
型別3 的訊息塊沒有頭,流ID,訊息長度和時間戳delta,這個型別的訊息塊在之前的訊息塊中取值,當單一的訊息被分裂成訊息塊,所有的訊息塊除了第一個,其余都應該使用這種型別,流由同樣大小的訊息組成,
公共頭欄位
塊訊息頭中每個欄位的描述:
| 欄位 | 描述 |
|---|---|
| timestamp delta (3 bytes) | 對于型別1或型別2塊,此處可以看到發送前一個塊的時間戳和當前塊的時間戳之間的差異, 如果增量大于或等于16777215(十六進制0xFFFFFF),則該欄位必須是16777215,表示擴展時間戳欄位以編碼完整的32位增量的形式存在, 否則,這個欄位應該是實際的增量, |
| message length (3 bytes) | 對于型別0和型別1的訊息塊,訊息的長度會出現在這里,注意這一般和訊息塊有效負載長度是不一樣的,訊息塊的有效負載長度是除了最后一個訊息塊的所有訊息塊的最大的長度, |
| message type id (1 byte) | 對于型別0和型別1的訊息塊,訊息的型別出現在這里, |
| message stream id (4 bytes) | 對于型別為0的塊,存盤訊息流ID, 訊息流ID以little-endian格式存盤, 通常,同一塊流中的所有訊息將來自同一個訊息流, 雖然可以將單獨的訊息流多路復用到同一個塊流中,但這會破壞頭壓縮的優點, 但是,如果一個訊息流關閉并且另一個隨后打開,則沒有理由通過發送新的型別為0的塊來重新使用現有的塊流, |
擴展時間戳
Extended Timestamp欄位用于編碼大于16777215(0xFFFFFF)的時間戳或時間戳增量; 也就是說,對于時間戳或時間戳增量,它們不適合型別0,1或2塊的24位欄位, 該欄位對完整的32位時間戳或時間戳增量進行編碼, 這個欄位用于表示將型別0塊的時間戳欄位或型別1或2塊的時間戳增量欄位設定為16777215(0xFFFFFF), 當相同塊流ID的最新型別0,1或2的塊指示存在擴展時間戳欄位時,該欄位出現在型別3的塊中,
示例
共有2個示例
示例1
本例給出了一個簡單的音頻訊息流,這個例子示范了資訊的冗余,

下表顯示了在此流中生成的塊, 從訊息3開始,資料傳輸得到優化, 除此之外,每訊息只有1位元組的開銷,

示例2
本例說明一個很長的訊息被分割成很多訊息塊,

這里是分割出來的訊息塊

訊息塊1的包頭資料詳細介紹了307個位元組的訊息的全部,
注意這兩個例子,型別3訊息塊可以用作兩種不同的方式,第一種是表示一條訊息的延續,第二種是表示一條新訊息的開始,這個新訊息可以從已經存在的資料中衍生出來,
協議控制訊息
RTMP塊流使用訊息型別ID 1,2,3,5和6作為協議控制訊息, 這些訊息包含RTMP Chunk Stream協議所需的資訊,
這些協議控制訊息務必具有訊息流ID 0 (稱為控制流)并且以塊流ID 2 發送,協議控制訊息一旦被接收就會立即生效,同時時間戳被忽略,
設定訊息塊大小
協議控制訊息1:設定訊息塊大小,用來通知對方新的最大的訊息塊大小,
訊息塊的大小可以被設定成一個默認的值,128位元組,但是客戶端或者服務端可以改變這個值,并且發送訊息通知對方更新,例如:假設一個客戶端想要發送131位元組的音頻資料,訊息塊的大小為128位元組,在這種情況下,客戶端可以發送這個協議控制訊息給服務端以通知訊息塊的大小被設定成了131位元組,那么客戶端就可以用一個訊息塊發送音頻資料,
最大塊大小應該不能小于128個位元組,并且必須不能小于1個位元組, 每個方向的最大塊大小都是獨立維護的,

0: 這一位必須為0,
chunk size 塊大小(31位):該欄位保存新的最大塊大小(以位元組為單位),這將用于發件人的所有后續塊,直至另行通知, 有效大小為1到2147483647(0x7FFFFFFF)(含); 但是,大于16777215(0xFFFFFF)的所有大小都是等效的,因為沒有塊大于一條訊息,并且沒有訊息大于16777215位元組,
中斷訊息
協議控制訊息2:中止訊息,用于通知對方是否正在等待塊完成訊息,然后丟棄部分接收到的訊息, 對方接收塊流ID作為該協議訊息的有效載荷, 應用程式可能會在關閉時發送此訊息,以指示不需要進一步處理訊息,

chunk stream ID 塊流ID (32 位): 該欄位保存塊流ID,對應的當前訊息將被丟棄,
Acknowledgement
客戶端或服務器在收到等于視窗大小的位元組后,必須向對端發送Acknowledgement確認, 視窗大小是發送方未收到接收方確認而發送的最大位元組數, 該訊息指定了序列號,它是到當前為止收到的位元組數,

sequence number 序列號(32 位):欄位表示到當前為止收到的位元組數,
Window Acknowledgement Size
客戶端或服務器發送此訊息以通知對方在發送Acknowledgement 確認之間使用的視窗大小, 發送人希望在發送視窗大小位元組后得到對方的確認,

設定對等帶寬
客戶端或服務器發送此訊息來限制另一方的輸出帶寬, 收到此訊息的另一方通過將已發送但未確認的資料量限制為此訊息中指示的視窗大小這種方式用來限制其輸出帶寬,如果視窗大小與發送給此訊息發送者的最后一個視窗大小不同,那么接收此訊息的另一方應該使用"Window Acknowledgement Size"訊息進行回應,

限制型別Limit Type是以下值之一:
- 0 - Hard:對方應該限制其輸出帶寬到指定的視窗大小,
- 1 - Soft:對方應該限制其輸出帶寬到本訊息中指示的視窗或已經生效的限制,以較小者為準,
- 2 - Dynamic:如果以前的限制型別是Hard,請將此訊息視為Hard型別訊息,否則可以直接忽視,
RTMP訊息格式
本部分主要介紹RTMP訊息的格式,在網路物體之間使用較低級傳輸層(如RTMP塊流)傳輸這些訊息,
雖然RTMP旨在與RTMP塊流一起使用,但它可以使用任何其他傳輸協議發送訊息, RTMP Chunk Stream和RTMP一起適用于各種音視頻應用,從一對一和一對多實時廣播到視頻點播服務,再到互動式會議應用,
RTMP訊息格式
服務器和客戶端通過網路發送RTMP訊息以相互通信, 訊息可能包括音頻,視頻,資料或任何其他訊息,
RTMP訊息有兩部分,頭部和有效負載,
訊息頭
訊息頭包含以下欄位:
| 欄位 | 描述 |
|---|---|
| Message Type | 一個位元組的欄位來表示訊息型別, 一系列的型別ID(1-6)被保留用于協議控制訊息 |
| Length | 三位元組欄位,以位元組表示有效負載的大小, 它以big-endian格式設定, |
| Timestamp | 包含訊息時間戳的四位元組欄位, 這4個位元組按big-endian順序排列, |
| Message Stream Id | 標識訊息流的三位元組欄位, 這些位元組以big-endian格式設定, |

訊息有效負載
訊息的另一部分是有效負載,它是訊息中包含的實際資料, 例如,它可能是一些音頻樣本或壓縮的視頻資料,
用戶控制訊息
RTMP使用訊息型別ID 4 作為用戶控制訊息, 這些訊息包含RTMP流層使用的資訊, 帶有ID 1,2,3,5和6的協議訊息由RTMP塊流協議使用,
用戶控制訊息應該使用訊息流ID 0(稱為控制流),并且當通過RTMP塊流發送時,在訊息流ID 2上發送,用戶控制訊息在流中被接收時生效, 他們的時間戳被忽略,
客戶端或服務器發送此訊息以通知對端用戶控制事件, 該訊息攜帶事件型別和事件資料,

訊息資料Event Data的前2個位元組用于標識事件型別Event Type, 事件型別后面跟著事件資料, 事件資料欄位的大小是可變的, 但是,在訊息必須通過RTMP塊流層的情況下,最大塊的大小應該足夠大,以允許這些訊息適合單個塊,
RTMP命令訊息
本節介紹在服務器和客戶端之間用于相互通信的不同型別的訊息和命令,
在服務器和客戶端之間交換的不同型別的訊息包括用于發送音頻資料的音頻訊息,用于發送視頻資料的視頻訊息,用于發送任何用戶資料的資料訊息,共享物件訊息和命令訊息, 共享物件訊息提供了一種通用的方式來管理多個客戶端和服務器之間的分布式資料, 命令訊息在客戶端和服務器之間傳送AMF編碼的命令, 客戶端或服務器可以通過流使用命令訊息請求對方的遠程程序呼叫(RPC),
訊息型別
服務器和客戶端通過網路發送訊息以相互通信, 訊息可以是任何型別,包括音頻訊息,視頻訊息,命令訊息,共享物件訊息,資料訊息和用戶控制訊息,
命令訊息
命令訊息在客戶端和服務器之間傳送AMF編碼命令, 這些訊息的AMF0編碼的訊息型別值為20,AMF3編碼的訊息型別值為17, 這些訊息被發送來執行一些操作,例如connect,createStream,publish, play, pause等, 諸如onstatus,result等命令訊息用于通知發送者有關請求的命令的狀態, 命令訊息由命令名稱,事務ID和包含相關引數的命令物件組成, 客戶端或服務器可以通過流使用命令訊息請求對方的遠程程序呼叫(RPC),
資料訊息
客戶端或服務器發送此訊息用于向對方發送元資料或任何用戶資料, 元資料包括有關資料(音頻,視頻等)的詳細資訊,如創建時間,持續時間,主題等, AMF0的訊息型別值為18,AMF3的訊息型別值為15,
共享物件訊息
共享物件是一個Flash物件(name-value對的集合),在多個客戶端,實體等之間同步的, AMF0的訊息型別19和AMF3的訊息型別16保留用于共享物件事件, 每條訊息可以包含多個事件,

支持以下事件型別:

音頻訊息
客戶端或服務器發送此訊息來向對等方發送音頻資料, 訊息型別值8保留給音頻訊息,
視頻訊息
客戶端或服務器發送此訊息以向對等方發送視頻資料, 訊息型別值9保留給視頻訊息,
聚合訊息
聚合訊息是單個訊息,訊息型別22用于聚合訊息,


聚合訊息的訊息流ID會覆寫聚合內的子訊息的訊息流ID,
聚合訊息的時間戳與第一個子訊息之間的差異是用于將子訊息的時間戳重新歸一化為流時間尺度的偏移量, 將偏移量添加到每個子訊息的時間戳以達到標準化的流時間, 第一個子訊息的時間戳應該與聚合訊息的時間戳相同,所以偏移量應該為零,
后向指標包含前一個訊息的大小,包括其頭部, 它被包含來匹配FLV檔案的格式并用于向后搜索,
使用聚合訊息有幾個性能優勢:
- 訊息塊流最多可以在塊內發送單個完整的訊息, 因此,增加塊大小并使用聚合訊息可減少發送的塊的數量,
- 子訊息可以連續地存盤在記憶體中, 在進行系統呼叫向網路上發送資料時效率更高,
用戶控制訊息事件
客戶端或服務器發送此訊息以通知對端關于用戶控制事件,
支持以下用戶控制事件型別:

命令型別
客戶端和服務器交換AMF編碼的命令,發送方發送一條命令訊息,其中包含命令名稱,事務ID和包含相關引數的命令物件,例如,connect命令包含'app'引數,它告訴客戶端連接到的服務器應用程式名稱,接收方處理該命令并以相同的事務ID發送回應,回應字串可以是_result,_error或方法名稱,例如verifyClient或contactExternalServer,
_result或_error命令字串表示回應,事務ID指示回應參考的未完成的命令,它與IMAP和許多其他協議中的標簽相同,命令字串中的方法名稱指示發送方正試圖在接收方端運行方法,
以下類物件用于發送各種命令:
NetConnection:一個物件,它是服務器和客戶端之間連接的更高級別表示,NetStream:表示發送音頻流,視頻流和其他相關資料的通道的物件,我們還發送控制資料流的播放,暫停等命令,
NetConnection命令
NetConnection管理客戶端應用程式和服務器之間的雙向連接, 另外,它為異步遠程方法呼叫提供支持,
以下命令可以在NetConnection上發送:
connectcallclosecreateStream
connect
客戶端向服務端發送連接(connect)命令請求連接一個服務器應用實體,以下為命令的結構:

以下是連接命令的命令物件中使用的name-value對的描述:

audioCodecs屬性的標志值:

videoCodecs屬性的標志值:

videoFunction屬性的標志值:

物件編碼(object Encoding)屬性的值:

以下是服務端到客戶端命令的結構:

以下是連接命令中的訊息流:

命令執行期間的訊息流是:
- 客戶端將連接命令發送到服務器以請求連接服務器應用程式實體,
- 接收到連接命令后,服務器將協議訊息
'Window Acknowledgement Size'發送給客戶端, 服務器還連接到connect命令中提到的應用程式, - 服務器將協議訊息
'Set Peer Bandwidth'發送給客戶端, - 在處理協議訊息
'Set Peer Bandwidth'后,客戶端向服務器發送協議訊息'Window Acknowledgement Size', - 服務器將型別為
User Control Message(StreamBegin)的另一個協議訊息發送給客戶端, - 服務器發送結果命令訊息,通知客戶端連接狀態(成功/失敗), 該命令指定事務ID(連接命令始終等于1), 該訊息還指定了屬性,例如
Flash Media Server版本(字串), 此外,它還指定其他連接回應相關資訊,如級別(字串),代碼(字串),描述(字串),物件編碼(數字)等,
Call
NetConnection物件的呼叫方法在接收端運行遠程程序呼叫(RPC), 被呼叫的RPC名稱作為引數傳遞給call命令,
從發送方到接收方的命令結構如下:

回應的命令結構如下:

createStream
客戶端將此命令發送到服務器以創建用于訊息通信的邏輯通道,音頻,視頻和元資料的發布是通過使用createStream命令創建的流通道執行的,
NetConnection是默認通信通道,其流ID為0,協議和一些命令訊息(包括createStream)使用默認通信通道,
從客戶端到服務器的命令結構如下所示:

從服務器到客戶端的命令結構如下:

NetStream命令
NetStream定義了流式音頻,視頻和資料訊息可以通過將客戶端連接到服務器的NetConnection流動的通道, 一個NetConnection物件可以為多個資料流支持多個NetStream,
以下命令可以由客戶端在NetStream上發送到服務器:
playplay2deleteStreamcloseStreamreceiveAudioreceiveVideopublishseekpause
服務器使用'onStatus'命令將NetStream狀態更新發送到客戶端:

play
客戶端將此命令發送到服務器以播放流, 播放串列也可以使用此命令多次創建,
如果您想要創建一個可在不同直播流或錄像流之間切換的動態播放串列,請多次呼叫play,每次給reset傳遞false,相反,如果要立即播放指定的資料流,請清空播放佇列中的其他流,給reset傳遞true,
從客戶端到服務器的命令結構如下所示:

Play命令中的訊息流:

命令執行期間的訊息流是:
- 在客戶端收到服務器回傳的
createStream命令的成功結果后,客戶端就開始發送play命令, - 在收到
play命令后,服務器發送協議訊息來設定塊大小, - 服務器發送另一個協議訊息(用戶控制),用于指定事件
'StreamIsRecorded'的和該訊息中的流ID, 該訊息在前2個位元組中攜帶事件型別,在最后4個位元組中攜帶流ID, - 服務器發送另一個指定事件
'StreamBegin'的協議訊息(用戶控制),以指示流傳輸到客戶端的開始, - 如果客戶端發送的播放命令成功了,則服務器發送
onStatus命令訊息NetStream.Play.Start和NetStream.Play.Reset,NetStream.Play.Reset只有在客戶端發送的播放命令設定了重置標志時才由服務器發送, 如果沒有找到要播放的流,則服務器發送onStatus訊息NetStream.Play.StreamNotFound, - 在此之后,服務器發送客戶端播放所需的音頻和視頻資料,
play2
與播放命令不同,play2可以切換到不同的位元率流,而不改變播放內容的時間線, 服務器維護多個檔案,用于支持客戶端在play2中請求的所有位元率,
從客戶端到服務器的命令結構如下所示:

在ActionScript 3語言參考[AS3]中描述了NetStreamPlayOptions物件的公共屬性,
下圖顯示了該命令的訊息流:

deleteStream
當NetStream物件被破壞時,NetStream發送deleteStream命令,
從客戶端到服務器的命令結構如下所示:

服務器不發送任何回應,
receiveAudio
NetStream發送receiveAudio訊息以通知服務器是否將音頻發送給客戶端,
從客戶端到服務器的命令結構如下所示:

如果在將Bool Flag設定為false的情況下發送receiveAudio命令,則服務器不會發送任何回應, 如果Bool Flag設定為true,則服務器會使用狀態訊息NetStream.Seek.Notify和NetStream.Play.Start作為回應,
receiveVideo
NetStream發送receiveVideo訊息以通知服務器是否將視頻發送給客戶端,
從客戶端到服務器的命令結構如下所示:

如果在將Bool Flag設定為false的情況下發送receiveVideo命令,則服務器不會發送任何回應, 如果Bool Flag設定為true,則服務器會使用狀態訊息NetStream.Seek.Notify和NetStream.Play.Start作為回應,
publish
客戶端發送publish命令以將已命名的流發布到服務器, 使用該名稱,任何客戶端都可以播放此流并接收已發布的音頻,視頻和資料訊息,
從客戶端到服務器的命令結構如下所示:

服務器使用onStatus命令進行回應以標記publish的開始,
seek
客戶端發送seek命令來查找媒體檔案或播放串列中的偏移量(以毫秒為單位),
從客戶端到服務器的命令結構如下所示:

當seek成功時,服務器發送狀態訊息NetStream.Seek.Notify, 如果失敗,它將回傳一個_error訊息,
pause
客戶端發送暫停命令以通知服務器暫停或開始播放,
從客戶端到服務器的命令結構如下所示:

當流暫停時,服務器發送狀態訊息NetStream.Pause.Notify,當流處于未暫停狀態時發送NetStream.Unpause.Notify, 如果失敗,將回傳一個_error訊息,
訊息交換示例
以下是幾個解釋RTMP訊息交換的示例,
發布錄制的視頻
此示例說明發布者如何發布流并將視頻流式傳輸到服務器, 其他客戶端可以訂閱此發布的流并播放視頻,

廣播共享物件訊息
此示例說明在創建和更改共享物件期間交換的訊息, 它還說明了共享物件訊息廣播的程序,

從錄像的流發布元資料
本示例描述了發布元資料的訊息交換,

FMS: Flash Media Server
參考:
- rtmp_specification_1.0.pdf
記得幫我點贊哦!
精心整理了計算機各個方向的從入門、進階、實戰的視頻課程和電子書,按照目錄合理分類,總能找到你需要的學習資料,還在等什么?快去關注下載吧!!!

念念不忘,必有回響,小伙伴們幫我點個贊吧,非常感謝,
我是職場亮哥,YY高級軟體工程師、四年作業經驗,拒絕咸魚爭當龍頭的斜杠程式員,
聽我說,進步多,程式人生一把梭
如果有幸能幫到你,請幫我點個【贊】,給個關注,如果能順帶評論給個鼓勵,將不勝感激,
職場亮哥文章串列:更多文章

本人所有文章、回答都與著作權保護平臺有合作,著作權歸職場亮哥所有,未經授權,轉載必究!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/581.html
標籤:其他
