2019獨角獸企業重金招聘Python工程師標準>>>
Kurento媒體服務器可以被兩種外部Kurento客戶端控制,如Java或JavaScript。這些客戶端使用Kuernto協議來和KMS通信。Kurento 協議是基于WebSocket協議,并使用了JSON-RPC V2.0 消息來提交請求和發送響應。
JSON-RPC 消息格式
Kurento協議使用JSON-RPC V2.0 編碼它的消息,下面的章節將討論如何在JSON消息中使用這種格式。
Request 消息
一個RPC調用可以表示為向服務端發送一個Request消息,Request消息有下列成員變量:
-
jsonrpc: 指定JSON-RPC 協議的版本的字符串,它必須是"2.0"。
-
id: 由客戶端建立的唯一標識符,包含一個字符串或數字。 服務端必須在Response消息中以相同的值回復。 這個成員變量被用于在兩個消息間地內容進行關聯。
-
method: 被激活方法名 。
-
params: 用于被激活方法的結構體,它包含了參數值。
下面的JSON顯示了一個示例請求的格式:
{"jsonrpc": "2.0","id": 1,"method": "create","params": {"type": "PlayerEndPoint","constructorParams": {"pipeline": "6829986","uri": "http://host/app/video.mp4"},"sessionId": "c93e5bf0-4fd0-4888-9411-765ff5d89b93"}
}
成功的響應消息
當一個RPC調用讓服務端回復一個響應消息時,如果是一個成功的響應,那么響應消息將包含如下成員變量:
-
jsonrpc:指定JSON-RPC協議的版本的字符串,它必須是"2.0".
-
id:它強制性地和請求消息中的id值一致。
-
result: 它的值是由服務端被激活的方法來確定的。如果連接被拒絕,它返回一個拒絕屬性的消息,拒絕屬性包含了消息代碼,以及為什么session被拒絕,并且不會有被定義的sessionId。
下面是一個成功響應示例:
{"jsonrpc": "2.0","id": 1,"result": {"value": "442352747","sessionId": "c93e5bf0-4fd0-4888-9411-765ff5d89b93"}
}
出錯的響應消息
當一個RPC調用讓服務端回復一個響應消息時,如果是一個出錯的響應,那么響應消息將包含如下成員變量:
-
jsonrpc: 指定JSON-RPC協議的版本的字符串,它必須是"2.0".
-
id: 它強制性地和請求消息中的id值一致。如果檢測到請求消息中id是錯誤的(如錯誤或無效的請求),它就為空。
-
error: 一個消息,通過下面成員變量來描述這個錯誤:
-
code: 標識遇到的錯誤類型的整數值
-
message: 錯誤的簡單描述
-
data: 原始或結構體的值,包含了關于錯誤的額外信息。它可以被忽略,它的值是由服務端定義的。
-
下面顯示了一個典型的出錯響應:
{"jsonrpc": "2.0","id": 1,"error": {"code": "33","message": "Invalid paramter format"}
}
JSON-RPC之上的Kurento API
如在Kurento API章節所述,Kurento媒體服務器提供了一套完整成熟的API,讓應用程序以多種方式處理媒體。
為了使用這些豐富的API, Kurento客戶端要求在客戶端和服務端之間實現全雙式通信。基于這個原因,Kurento協議是基于WebSocket傳輸的。
在發出命令之前,Kurento客戶端需要先請求和Kurento媒體服務器的URL: ws://hostname:port/kurento建立WebSocket連接。一旦這個WebSocket連接已建立,Kurento協議提供了五種不同的類型的請求/響應消息:
-
ping: 客戶端和KMS之間保活。
-
create: 實例化一個新的媒體對象,如管道或媒體元件。
-
invoke: 調用已創建對象的方法。
-
subscribe: 創建對象中的事件訂閱。
-
unsubscribe: 移除一個事件的訂閱。
-
release: 刪除對象并釋放其資源。
Kurento協議還允許Kurento媒體服務器向客戶端發送請求:
- onEvent: 這個請求是在事件發生時,Kurento媒體服務器向客戶端發送請求。
Ping
為了保證客戶端和Kurento Media Server之間的WebSocket連接,實現了保持活動方法。 此方法基于客戶端發送的ping方法,必須使用來自服務器的pong消息進行回復。 如果在時間間隔內未獲得響應,則客戶端知道與媒體服務器的連接已丟失。參數間隔是從服務器接收Pong消息的超時時間,以毫秒為單位。 默認情況下,此值為240000(即40秒)。 這是ping請求的示例:
{"id": 1,"method": "ping","params": {"interval": 240000},"jsonrpc": "2.0"
}
對ping請求的響應必須包含具有固定名稱為pong的value參數的result對象。 以下片段顯示了對上一個ping請求的pong響應:
{"id": 1,"result": {"value": "pong"},"jsonrpc": "2.0"
}
Create
Create消息請求 Kurento API 對象的創建。參數 type 指定了被創建對象的類型。參數 constructorParams 包含了創建該對象需要的所有信息。每個消息都需要不同的 constructorParams 來創建對象,這些參數是在Kurento API章節中定義的。
最后,參數sessionId為當前session的標識符。這個參數的值是由Kurento Media Server在每次響應時發送給客戶端。只有第一次的從客戶端到服務端的請求不需要這個‘sessionId’(因為這時候客戶端還未收到這個值)。
下面的例子展示了一個request消息請求,它請求創建一個MediaPipeline類型對象:
{"id": 2,"method": "create","params": {"type": "MediaPipeline","constructorParams": {},"properties": {}},"jsonrpc": "2.0"
}
響應消息中, 在域value中包含了媒體管道id。消息id還會要被用在協議的其它請求中,sessionId要在每個響應中返回, 標識當前會話。
{"id": 2,"result": {"value": "6ba9067f-cdcf-4ea6-a6ee-d74519585acd_kurento.MediaPipeline","sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}
響應消息包含字段值中包含新對象的標識符。 像往常一樣,消息id必須與請求消息匹配。 每個響應中還返回sessionId。 以下示例顯示請求消息,請求在現有介質管道(由參數mediaPipeline標識)中創建WebRtcEndpoint類型的對象。 請注意,在此請求中,sessionId已存在,而在上一個示例中,它不是(因為在那一點對于客戶端是未知的):
{"id": 3,"method": "create","params": {"type": "WebRtcEndpoint","constructorParams": {"mediaPipeline": "6ba9067f-cdcf-4ea6-a6ee-d74519585acd_kurento.MediaPipeline"},"properties": {},"sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}
以下示例顯示請求消息,請求在現有介質管道(由參數mediaPipeline標識)中創建WebRtcEndpoint類型的對象。 請注意,在此請求中,sessionId已存在,而在上一個示例中,它不是(因為在那一點對于客戶端是未知的):
{"id": 3,"result": {"value": "6ba9067f-cdcf-4ea6-a6ee-d74519585acd_kurento.MediaPipeline/087b7777-aab5-4787-816f-f0de19e5b1d9_kurento.WebRtcEndpoint","sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}
Invoke
Invoke 消息請求對指定對象調用一個操作。
參數 object 指示了被調用操作的對象的id,
參數 operation 指示了被調用操作的名稱。
參數 operationParams 包含了執行操作需要的參數。
以下示例顯示請求消息,請求調用連接到WebRtcEndpoint的PlayerEndpoint上的操作connect:
{"id": 5,"method": "invoke","params": {"object": "6ba9067f-cdcf-4ea6-a6ee-d74519585acd_kurento.MediaPipeline/76dcb8d7-5655-445b-8cb7-cf5dc91643bc_kurento.PlayerEndpoint","operation": "connect","operationParams": {"sink": "6ba9067f-cdcf-4ea6-a6ee-d74519585acd_kurento.MediaPipeline/087b7777-aab5-4787-816f-f0de19e5b1d9_kurento.WebRtcEndpoint"},"sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}
響應消息包含執行對象中調用操作時返回的值,如果操作未返回任何值,則返回空值。
以下示例顯示調用操作connect(不返回任何內容)時的典型響應:
{"id": 5,"result": {"sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}
Release
Release 消息請求釋放指定對象。參數 object 指定了要釋放的對象的id:
{"id": 36,"method": "release","params": {"object": "6ba9067f-cdcf-4ea6-a6ee-d74519585acd_kurento.MediaPipeline","sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}
響應消息只包含sessionID, 下面是一個示例:
{"id": 36,"result": {"sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}
Subscribe
Subscribe消息請求訂閱指定對象的某種類型的事件。參數 object 指定了要訂閱事件的對象id. 參數 type 指定了事件的類型。如果客戶端訂閱了一個對象的某種事件,每次對象的這個事件發生后, Kurento Media Server就會使用 onEvent 方法發送一個請求到客戶端。這種類型的請求會在后面的章節再講解。
以下示例顯示請求消息,請求在PlayerEndpoint對象上預訂事件類型EndOfStream:
{"id": 11,"method": "subscribe","params": {"type": "EndOfStream","object": "6ba9067f-cdcf-4ea6-a6ee-d74519585acd_kurento.MediaPipeline/76dcb8d7-5655-445b-8cb7-cf5dc91643bc_kurento.PlayerEndpoint","sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}
響應消息包含了訂閱標識符,這個值會在后面的解除訂閱中要用到。
下面的示例顯示一個訂閱請求的響應消息,屬性 value 的值包含了訂閱id:
{"id": 11,"result": {"value": "052061c1-0d87-4fbd-9cc9-66b57c3e1280","sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}
Unsubscribe
Unsubscribe 消息請求解除前面事件的訂閱。參數 subscription 包含了從服務端收到的成功訂閱后的訂閱id。
以下示例顯示請求消息,請求取消給定對象353be312-b7f1-4768-9117-5c2f5a087429的訂閱:
{"id": 38,"method": "unsubscribe","params": {"subscription": "052061c1-0d87-4fbd-9cc9-66b57c3e1280","object": "6ba9067f-cdcf-4ea6-a6ee-d74519585acd_kurento.MediaPipeline/76dcb8d7-5655-445b-8cb7-cf5dc91643bc_kurento.PlayerEndpoint","sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}
響應消息包含了sessionId。下面的示例顯示了一個解除訂閱請求的響應:
{"id": 38,"result": {"sessionId": "bd4d6227-0463-4d52-b1c3-c71f0be68466"},"jsonrpc": "2.0"
}
OnEvent
當客戶端訂閱了對象的某類事件后,每當對象的這類事件發生時,服務端都會發送一個onEvent請求。這也是為什么Kurento協議要使用Websocket并要在客戶端和服務端間使用全雙工的工作模式。服務端發送到客戶端的請求包含了事件的所有信息:
-
source: 事件的對象源。
-
type: 事件的類型。
-
timestamp:媒體服務器時間
-
tags: 可以使用setSendTagsInEvents和addTag方法在每個元素中標記媒體元素。 這些標記是鍵值元數據,可供開發人員用于自定義目的。 媒體服務器在此字段中為每個事件返回標簽。
下面的顯示了服務端發送到客戶端的提醒:
{"jsonrpc":"2.0","method":"onEvent","params":{"value":{"data":{"source":"681f1bc8-2d13-4189-a82a-2e2b92248a21_kurento.MediaPipeline/e983997e-ac19-4f4b-9575-3709af8c01be_kurento.PlayerEndpoint","tags":[],"timestamp":"1441277150","type":"EndOfStream"},"object":"681f1bc8-2d13-4189-a82a-2e2b92248a21_kurento.MediaPipeline/e983997e-ac19-4f4b-9575-3709af8c01be_kurento.PlayerEndpoint","type":"EndOfStream"}}
}
通知消息沒有 id 字段是因為響應不是必須的。
網絡問題
KMS處理的資源是高消耗的,因此,KMS實現了一個垃圾收集器。
當客戶端斷開連接后超過4分鐘,媒體元件就會被收集。在這個時間后,這些媒體元件會被自動處理。
因此,客戶端和KMS間的websocket連接可以在任何時間激活。當網絡臨時中斷中,KMS實現了一個和客戶端重連的機制。
有一種基于上面格式特殊類型的消息,這個消息允許客戶端重新連接到前面連接KMS:
{"jsonrpc": "2.0","id": 7,"method": "connect","params": {"sessionId":"4f5255d5-5695-4e1c-aa2b-722e82db5260"}
}
如果KMS回應如下:
{"jsonrpc": "2.0","id": 7,"result": {"sessionId":"4f5255d5-5695-4e1c-aa2b-722e82db5260"}
}
則表示客戶端重新連接到了同一個KMS。如果連接到了其它KMS, 則消息如下:
{"jsonrpc":"2.0","id": 7,"error":{"code":40007,"message":"Invalid session","data":{"type":"INVALID_SESSION"}}
}
在這種情況下,客戶端應該再次調用原始的連接以獲得一個新的sessionId:
{"jsonrpc":"2.0","id": 7,"method":"connect"
}
Kurento API
為了實現一個Kurento客戶端,你需要仔細閱讀本文檔。而知道所有細節的最好的方式是查看IDL文件,它定義了Kurento元件的接口。我們已經定義了基于JSON的通用IDL格式。從它開始,我們為Java和JavaScript生成了客戶端代碼。Kurento API定義了下列IDL文件:
- KMS core
- KMS elements
- KMS filters
Example: WebRTC in loopback
本章節描述了Kurento客戶端和Kurento Media Server實現了下WebRTC回話功能的消息交互。它完整地展示了教程中的過程 ,步驟如下:
[ 1 ] 客戶端發送一個創建媒體管道的請求消息:
{"id":1,"method":"create","params":{"type":"MediaPipeline","constructorParams":{},"properties":{}},"jsonrpc":"2.0"
}
[ 2 ] KMS回應一個包含有媒體管道ID和媒體會話ID(sessionId)的響應消息:
{"id":1,"result":{"value":"c4a84b47-1acd-4930-9f6d-008c10782dfe_MediaPipeline","sessionId":"ba4be2a1-2b09-444e-a368-f81825a6168c"},"jsonrpc":"2.0"
}
[ 3 ] 這里是列表文本 客戶端發送一個創建WebRtcEndpoint的請求:
{"id":2,"method":"create","params":{"type":"WebRtcEndpoint","constructorParams":{"mediaPipeline":"c4a84b47-1acd-4930-9f6d-008c10782dfe_MediaPipeline"},"properties": {},"sessionId":"ba4be2a1-2b09-444e-a368-f81825a6168c"},"jsonrpc":"2.0"
}
[ 4 ] KMS創建一個WebRtcEndpoint,并回給客戶端這個媒體元件的標識符:
{"id":2,"result":{"value":"c4a84b47-1acd-4930-9f6d-008c10782dfe_MediaPipeline/e72a1ff5-e416-48ff-99ef-02f7fadabaf7_WebRtcEndpoint","sessionId":"ba4be2a1-2b09-444e-a368-f81825a6168c"},"jsonrpc":"2.0"
}
[ 5 ] 客戶端調用WebRtcEndpoint的連接原語來創建一個回放:
{"id":3,"method":"invoke","params":{"object":"c4a84b47-1acd-4930-9f6d-008c10782dfe_MediaPipeline/e72a1ff5-e416-48ff-99ef-02f7fadabaf7_WebRtcEndpoint","operation":"connect","operationParams":{"sink":"c4a84b47-1acd-4930-9f6d-008c10782dfe_MediaPipeline/e72a1ff5-e416-48ff-99ef-02f7fadabaf7_WebRtcEndpoint"},"sessionId":"ba4be2a1-2b09-444e-a368-f81825a6168c"},"jsonrpc":"2.0"
}
[ 6 ] KMS執行連接并回應這個操作:
{"id":3,"result":{"sessionId":"ba4be2a1-2b09-444e-a368-f81825a6168c"},"jsonrpc":"2.0"
}
[ 7 ] 客戶端調用WebRtcEndpoint的processOffer原語來進行WebRTC的SDP協商:
{"id":4,"method":"invoke","params":{"object":"c4a84b47-1acd-4930-9f6d-008c10782dfe_MediaPipeline/e72a1ff5-e416-48ff-99ef-02f7fadabaf7_WebRtcEndpoint","operation":"processOffer","operationParams":{"offer":"SDP"},"sessionId":"ba4be2a1-2b09-444e-a368-f81825a6168c"},"jsonrpc":"2.0"
}
[ 8 ] KMS執行SDP協商并返回SDP回答:
{"id":4,"result":{"value":"SDP"},"jsonrpc":"2.0"
}
Kurento Module Creator
默認的Kurento客戶端(java和JavaScript)是使用一個叫作 Kurento Module Creator的工具創建的。因此,這個工具同樣可以被用來創建基于其它語言的定制化客戶端。
Kurento Module Creator在Ubuntu機器上使用如下命令安裝:
sudo apt-get install kurento-module-creator
這個工具的目的是為了生成客戶端代碼,以及生成服務端需要的glue代碼。對于代碼生成,它通常使用Freemarker 作為模板引擎。通常的使用Kurento Module Creater 的方式是運行如下命令:
kurento-module-creator -c <CODEGEN_DIR> -r <ROM_FILE> -r <TEMPLATES_DIR>
在這里 :
-
CODEGEN_DIR: 生成文件的目的路徑
-
ROM_FILE: 包含這個文件的 Kurento Media Element Description (kmd)文件列表或文件夾的空間劃分。例如: 你可以看下 Kurento Media Server內部源代碼。
-
TEMPLATES_DIR: 包含模版文件的目錄。例如:你可以看一下內部 java 和 javascript 的模版。