Kurento應用開發指南(以Kurento 5.0爲模板) 之二:示例教程helloworld

5. Kurento教程

這部分包含了如何使用Kurento框架的教程,以建立不一樣類型WebRTC和多媒體應用。
教程包含下面三個方面:
? Java: 
These show applications where clients interact with an application server based on Java EE technology. 
The application server hold the logic orchestrating the communication 
among the clients and controlling Kurento Server capabilities for them.

? Browser JavaScript: 
These show applications executing at the browser and communicating directly with the Kurento Media Server. 
In these tutorial, all the application logic is hold by the browser. Hence, no application
server is necessary. For these reasons, these applications need to be simple.

? Node.js: 
These show applications where clients interact with an application server based on Node.js technology. 
下面這個例子是使用Kurento建立的一個最簡單的WebRTC應用。
它實現一個WebRTC回看(一個WebRTC媒體流從客戶端發送到Kurento,而後再返回到客戶端)。
 html

5.1  Java 教程1 - Hello world

這個網頁應用程序是爲了給Java開發者介紹Kurento開發規則的。它包含一個基於WebRTC視頻回看功能。
 java

5.1.1 運行示例程序

在運行本示例前,須要先安裝 Kurento Media Server,可見前面的安裝指南。
另外,你還須要先在你的系統中安裝 JDK (at least version 7), Maven, Git, 以及Bower。
Bower的可使用npm(Node.js的包管理器)來安裝。在Ubuntu機器上,它的安裝命令以下:
# sudo apt-get install curl
# curl -sL https://deb.nodesource.com/setup | sudo bash -
# sudo apt-get install -y nodejs
# sudo npm install -g bower

爲了加載這個應用程序,你須要先從GibHub項目上克隆,安裝並運行主類,命令以下:
# git clone https://github.com/Kurento/kurento-tutorial-java.git
# cd kurento-tutorial-java/kurento-hello-world
# mvn clean compile exec:java
程序啓動後,就可用兼容WebRTC的瀏覽器(Chrom, Firefox),輸入URL http://localhost:8080/來測試。
 node

5.1.2 運行時的出錯

運行命令mvn clean compile exec:java 時的出錯處理
1. 錯誤提示:
[INFO] --------------------------------
[ERROR] No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format <plugin-prefix>:<goal>or<plugin-group-id>:<plugin-artifact-id>[:<plugin-version>]:<goal>. …

[ERROR]
[ERROR]  For more information about the errors and possible solution, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/NoGoalSpecifiedException

使用下面的命令追蹤錯誤的更詳細信息 
mvn –X 
解決辦法:
詳解解釋見它的提示網頁:
https://cwiki.apache.org/confluence/display/MAVEN/NoGoalSpecifiedException
在pom.xml文件中添加以下標籤:
<project>
  ...
  <build>
        <defaultGoal>compile</defaultGoal>
    ...
  </build>
  ...
</project>


2. 錯誤提示
bower jquery#>= 1.9.1           cached git://github.com/jquery/jquery.git#2.1.4
bower jquery#>= 1.9.1         validate 2.1.4 against git://github.com/jquery/jquery.git#>= 1.9.1
bower                           EACCES EACCES, mkdir '/opt/kurento/kurento-tutorial-java/kurento-one2many-call/src/main/resources/static/bower_components'


Stack trace:
Error: EACCES, mkdir '/opt/kurento/kurento-tutorial-java/kurento-one2many-call/src/main/resources/static/bower_components'
    at Error (native)


Console trace:
Error
    at StandardRenderer.error (/usr/local/lib/node_modules/bower/lib/renderers/StandardRenderer.js:82:37)
    at Logger.<anonymous> (/usr/local/lib/node_modules/bower/bin/bower:110:22)
    at Logger.emit (events.js:109:17)
    at Logger.emit (/usr/local/lib/node_modules/bower/node_modules/bower-logger/lib/Logger.js:29:39)
    at /usr/local/lib/node_modules/bower/lib/commands/index.js:45:20
    at _rejected (/usr/local/lib/node_modules/bower/node_modules/q/q.js:844:24)
    at /usr/local/lib/node_modules/bower/node_modules/q/q.js:870:30
    at Promise.when (/usr/local/lib/node_modules/bower/node_modules/q/q.js:1122:31)
    at Promise.promise.promiseDispatch (/usr/local/lib/node_modules/bower/node_modules/q/q.js:788:41)
    at /usr/local/lib/node_modules/bower/node_modules/q/q.js:604:44
System info:
Bower version: 1.4.1
Node version: 0.13.0-pre
OS: Linux 3.16.0-23-generic x64
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 7.512s
[INFO] Finished at: Wed Jul 08 18:16:09 CST 2015
[INFO] Final Memory: 17M/457M
[INFO] ------------------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.3.2:exec (default) on project kurento-hello-world: Command execution failed. Process exited with an error: 1 (Exit value: 1) -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.3.2:exec (default) on project kurento-hello-world: Command execution failed.
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:217)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:320)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
Caused by: org.apache.maven.plugin.MojoExecutionException: Command execution failed.
at org.codehaus.mojo.exec.ExecMojo.execute(ExecMojo.java:303)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
... 19 more
Caused by: org.apache.commons.exec.ExecuteException: Process exited with an error: 1 (Exit value: 1)
at org.apache.commons.exec.DefaultExecutor.executeInternal(DefaultExecutor.java:402)
at org.apache.commons.exec.DefaultExecutor.execute(DefaultExecutor.java:164)
at org.codehaus.mojo.exec.ExecMojo.executeCommandLine(ExecMojo.java:746)
at org.codehaus.mojo.exec.ExecMojo.execute(ExecMojo.java:292)
... 21 more
[ERROR] 
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException


解決方案:
是由於這句話:
Error: EACCES, mkdir '/opt/kurento/kurento-tutorial-java/kurento-one2many-call/src/main/resources/static/bower_components'
它在編譯過程當中會要建立和刪除目錄及文件,由於文件夾的權限不對,因此致使的這個錯誤。
使用命令更改文件夾的權限:
$ sudo chown username –R kurento-hello-world 
$ sudo chmod +777 kurento-hello-world
 jquery

5.1.3 示例程序的分析

Kurento提供給開發者一個 Kurento Java客戶端來控制 Kurento Media Server。
這個客戶端庫能夠被任何Java應用程序使用,如Server Side Web, Desktop, Android等。
它也兼容全部像JavaEE,Spring, Play, Vert.x, 和JavaFx框架。

這個Hello world的DEMO是Kurento最簡單的Web應用,下面的圖片是這個DEMO運行時的截圖。
 
Figure 6.1: Kurento Hello World Screenshot: WebRTC in loopback

這個應用程序的接口(一個HTML頁面)是由兩個HTML5標籤組成的: 
一個用來顯示本地視頻流(由攝像頭捕捉到的);
另外一個用來顯示由媒體服務器發送給客戶端的遠端視頻流。


這個應用程序的邏輯很簡單:
將本地流發送到Kurento Media Server,它不對流作任何修改直接返回給客戶端。
爲了實現這個邏輯,咱們須要建立一個由單個Media Element組成的Media Pipeline。
Media Element能夠是WebRtcEndpoint, 它具備WebRTC媒體流的全雙向數據交換能力。
這個媒體元素和它本身鏈接,所以,它的在瀏覽器接收到的媒體是從瀏覽器發送出去的。
這個媒體管道的示例圖以下:


這個頁面應用程序一樣的客戶-服務端架構。
在客戶端,它的邏輯是由JavaScript實現的。
  在服務端,咱們使用了Java應用程序服務器來消費Kurento Java Client API對Kurento Media Server能力的控制。
總之,這個示例的高級架構是三層。
爲了實現實體間的通訊使用了下面的技術:
? REST: 用於在JavaScript客戶端和Java應用程序的服務端進行通訊。
? WebSocket: 用於在 Kurento Java客戶端和 Kurento Media Server間進行通訊。
這個通訊是由Kurento協議實現的。更多細節見協議文檔
 
Figure 6.2: Kurento Hello World Media Pipeline in context


下面的時序圖顯示了三個應用程序接口層的交互時序:
i) JavaScript logic; 
ii) Application server logic (which uses the Kurento Java Client);
iii) Kurento Media Server


Note: 客戶和服務端的通訊能夠不須要REST,爲了簡單化,在這個DEMO中使用了REST。
在後面的例子中,客戶和服務端使用了更復雜的信令通訊機制,WebSockets。


The following sections analyze in deep the server (Java) and client-side (JavaScript) 
code of this application. The complete source code can be found in GitHub.
下面的章節深度分析了這個DEMO的服務端(Java)和客戶端(JavaScript)的代碼。完整的源碼能夠從GitHub上下載。


5.1.4 應用程序服務端邏輯
這個DEMO在服務端使用了Java的Spring Boot框架,這個技術能夠被嵌入到Tomcat網頁服務器中使用,從而簡化了開發進程。
Note: You can use whatever Java server side technology you prefer to build web applications with Kurento.
For example, a pure Java EE application, SIP Servlets, Play, Vert.x, etc. 
Here we chose Spring Boot for convenience.


在下面的示圖中,能夠看到服務端代碼的類圖。
這個DEMO的主類是HelloWorldApp, 如代碼中所見,KurentoClient是Spring Bean的實例。
這個組件用來建立Kurento Media Pipelines, 它用來給應用程序添加媒體的能力。
在這個實例中,咱們能夠看到須要對客戶端庫指定Kurento Media Server的位置。
在這個示例中,咱們假定它位於本機的8888端口。若是你要重構這個DEMO,你須要自已指定你的Kurento Media Server 實例的位置。


當Kurento Client被實例化後,就能夠準備和Kurento Media Server通訊並控制它的媒體能力。
 
Figure 6.3: Complete sequence diagram of Kurento Hello World (WebRTC in loopbak) demo


Figure 6.4: Server-side class diagram of the HelloWorld app
 
@ComponentScan
@EnableAutoConfiguration
public class HelloWorldApp {
      @Bean
      public KurentoClient kurentoClient() {
            return KurentoClient.create("ws://localhost:8888/kurento");
      }
      public static void main(String[] args) throws Exception {
            new SpringApplication(HelloWorldApp.class).run(args);
      }
}


如前所述,咱們使用了REST進行客戶端與Java應用程序服務端的通訊。
特別的,咱們在服務端使用Spring聲明 @RestController來實現REST服務。
下面來看HelloWorld-Controller類:
@RestController
public class HelloWorldController {
      @Autowired
      private KurentoClient kurento;


      @RequestMapping(value = "/helloworld", method = RequestMethod.POST)
      private String processRequest(@RequestBody String sdpOffer)
      throws IOException {
            // Media Logic
            MediaPipeline pipeline = kurento.createMediaPipeline();
            WebRtcEndpoint webRtcEndpoint = new WebRtcEndpoint.Builder(pipeline).build();
            webRtcEndpoint.connect(webRtcEndpoint);


            // SDP negotiation (offer and answer)
            String responseSdp = webRtcEndpoint.processOffer(sdpOffer);
            return responseSdp;
      }
}


應用程序邏輯是在processRequest方法中實現的。
POST請求將路徑 /helloworld 發送出去,它主要執行兩個部分:
? 配置媒體處理邏輯: 
在應用程序中,這個部分配置了Kurento如何來處理媒體。換句話說,是在這裏建立了媒體管道。
爲了這個目的,對象KurentoClient用來建立一個MediaPipeline對象,經過它,咱們所須要的媒體元素被建立並鏈接。
在這個例子中,咱們只須要初始化一個WebRtcEndpoint來接收WebRTC流,而後再把它發回給客戶端。


? WebRTC SDP 協商: 
在WebRTC中,SDP (Session Description protocol) 用來在App間進行媒體數據交換的協商。
這種協商的發生是基於SDP提交和回答的交換機制。
在這個例子中,咱們假設SDP的提交和回答包含了全部WebRTC ICE候選者。
這個協商是在 processRequest 方法的第二部分實現的,在瀏覽器客戶端使用了SDP提交,
而後由WebRtcEndPoint生成一個SDP回答並返回。

 git

5.1.5  客戶端邏輯

接着來看客戶端的應用程序,它是一個單頁面應用程序框架(SPA)。
爲了呼叫前面建立REST服務,咱們使用了JavaScript庫jQuery。
另外,咱們使用了Kurento JavaScript 應用庫,叫作Kurento-utils.js,來簡化瀏覽器中WebRTC的管理。
這個庫依賴於adapter.js,它是一個JavaScript WebRTC應用,由Google管理,它抽象了瀏覽器的差別。
最後這個應用程序也須要jquery.js。


These libraries are linked in the index.html web page, and are used in the index.js. 
In the start function we can see how jQuery is used to send a POST request to the path /helloworld, 
where the application server REST service is listening. 
The function WebRtcPeer.startSendRecv abstracts the WebRTC internal details (i.e. PeerConnection and getUserStream)
and makes possible to start a full-duplexWebRTC communication, using the HTML video tag with id videoInput to 
show the video camera (local stream) and the video tag videoOutput to show the remote stream provided by the Kurento Media Server.


var webRtcPeer;
function start() {
      console.log("Starting video call ...");
      showSpinner(videoInput, videoOutput);
      webRtcPeer =
            kurentoUtils.WebRtcPeer.startSendRecv(videoInput, videoOutput, onOffer, onError);
}


function onOffer(sdpOffer) {
      console.info('Invoking SDP offer callback function ' + location.host);
      $.ajax({    
            url : location.protocol + '/helloworld',
            type : 'POST',
          dataType : 'text',
          contentType : 'application/sdp',
          data : sdpOffer,
          success : function(sdpAnswer) {
          console.log("Received sdpAnswer from server. Processing ...");
          webRtcPeer.processSdpAnswer(sdpAnswer);
    },
      error : function(jqXHR, textStatus, error) {
      onError(error);
    }
});
}
function onError(error) {
    console.error(error);
}

 github

5.1.6 依賴庫

This Java Spring application is implemented using Maven. 
The relevant part of the pom.xml is where Kurento dependencies are declared. 
As the following snippet shows, we need two dependencies: the Kurento Client Java dependency 
(kurento-client) and the JavaScript Kurento utility library (kurento-utils) for the client-side:
<dependencies>  
<dependency>
    <groupId>org.kurento</groupId>
    <artifactId>kurento-client</artifactId>
    <version>[5.0.0,6.0.0)</version>
  </dependency>
  <dependency>
    <groupId>org.kurento</groupId>
    <artifactId>kurento-utils-js</artifactId>
    <version>[5.0.0,6.0.0)</version>
  </dependency>
</dependencies>


Kurento framework uses Semantic Versioning for releases.
Notice that range [5.0.0,6.0.0) downloads the latest version of Kurento artefacts 
from Maven Central in version 5 (i.e. 5.x.x). Major versions are released when incompatible changes are made.
Note: We are in active development. You can find the latest version of Kurento Java Client at Maven Central. 


Kurento Java Client has a minimum requirement of Java 7. 
Hence, you need to include the following in the properties section:
<maven.compiler.target>1.7</maven.compiler.target>
<maven.compiler.source>1.7</maven.compiler.source>

 web

相關文章
相關標籤/搜索