Red5 是一個采用 Java 開發的開源免費 Flash 流媒體服務器。Red5 基於 Java 和一些功能強大的開源框架,為企業級應用奠定了標准。它使用 RTMP,RTMPT,RTMPS 和 RTMPE 流媒體協議, 支持:將音頻(MP3)和視頻(FLV,MP4,F4V,3GP)轉換成播放流;錄制客戶端播放流;共享對象;現場直播流發布;遠程調用。Red5 為即時通信,遠程教育,流媒體開發,多人在線游戲等提供了一個簡單易行的方案。本文通過對 Red5 的介紹,讓讀者了解如何使用 Red5 快速搭建一個流媒體服務器和如何在服務器上開發部署相應的流媒體應用。
流媒體文件是目前非常流行的網絡媒體格式之一,這種文件允許用戶一邊下載一邊播放,從而大大減少了用戶等待播放的時間。另外通過網絡播放流媒體文件時,文件本身不會在本地磁盤中存儲,這樣就節省了大量的磁盤空間開銷。正是這些優點,使得流媒體文件被廣泛應用於網絡播放。
流 媒體服務器是通過建立發布點來發布流媒體內容和管理用戶連接的。流媒體服務器能夠發布從視頻采集卡或攝像機等設備中傳來的實況流,也可以發布事先存儲的流 媒體文件,並且發布實況流和流媒體文件的結合體。一個媒體流可以由一個媒體文件構成,也可以由多個媒體文件組合而成,還可以由一個媒體文件目錄組成。
Flash Media Server,簡稱 FMS,是 Flash 大家庭裡的一員,被稱為是目前開發 Web 音視頻應用程序(比如,視頻聊天室、視頻會議系統、播客系統、音視頻留言等等)的最方便最快捷的解決方案。也在 web 應用程序開發上有著越來越廣泛的應用。當然 FMS 這種優良功能並不是免費提供給廣大用戶的,幾千美金每個點的價格讓很多開發人員望而卻步。於是,大家開始嘗試尋找一種更合適的解決方案,開源的 Red5 便成為了人們的新寵。
Red5 是一個采用 Java 開發的開源的 Flash 流媒體服務器,功能上與 FMS 類似。它支持:把音頻(MP3)和視頻(FLV)轉換成播放流;錄制客戶端播放流(只支持 FLV);共享對象;現場直播流發布;遠程調用。Red5 使用 RSTP 作為流媒體傳輸協議,包括在線錄制,Flash 流媒體播放,在線聊天,視頻會議等一些基本功能。國內外基於 Red5 的流媒體應用產品也在不斷推廣,例如在線視頻會議 Openmeeting,大型 Flash 網游功夫之王 2。
隨 著 Internet 發展,單純的文字和圖形已經遠遠不能滿足需求,而是逐漸向聲音和視頻等多媒體方向過渡。目前在網絡上傳輸音頻/視頻等多媒體文件時,一般有下載和流式傳輸 兩種選擇。由於音頻/視頻包含大量的數據,所以他們占據的存儲空間都比較大,在帶寬受限的網絡環境中下載可能要耗費數分鐘甚至數小時,所以這種處理方法的 延遲很大。如果換用流式傳輸的話,聲音、影像、動畫等多媒體文件將由專門的流媒體服務器負責向用戶連續、實時地發送,這樣用戶可以不必等到整個文件全部下 載完畢,而只需要經過幾秒鐘的啟動延時就可以了,當這些多媒體數據在客戶機上播放時,文件的剩余部分將繼續從流媒體服務器下載。
流 (Streaming)是近年在 Internet 上出現的新概念,其定義非常廣泛,主要是指通過網絡傳輸多媒體數據的技術總稱。流媒體包含廣義和狹義兩種內涵:廣義上的流媒體指的是使音頻和視頻形成穩定 和連續的傳輸流和回放流的一系列技術、方法和協議的總稱,即流媒體技術;狹義上的流媒體是相對於傳統的下載-回放方式而言的,指的是一種從 Internet 上獲取音頻和視頻等多媒體數據的新方法,它能夠支持多媒體數據流的實時傳輸和實時播放。通過運用流媒體技術,服務器能夠向客戶機發送穩定和連續的多媒體數 據流,客戶機在接收數據的同時以一個穩定的速率回放,而不用等數據全部下載完之後再進行回放。
由於受網絡帶寬、計算機處理能力和協議規范等 方面的限制,要想從 Internet 上下載大量的音頻和視頻數據,無論從下載時間和存儲空間上來講都是不太現實的,而流媒體技術的出現則很好地解決了這一難題。目前實現流媒體傳輸主要有兩種 方法:順序流(progressive streaming)傳輸和實時流(realtime streaming)傳輸,它們分別適合於不同的應用場合。
順 序流傳輸采用順序下載的方式進行傳輸,在下載的同時用戶可以在線回放多媒體數據,但給定時刻只能觀看已經下載的部分,不能跳到尚未下載的部分,也不能在傳 輸期間根據網絡狀況對下載速度進行調整。由於標准的 HTTP 服務器就可以發送這種形式的流媒體,而不需要其他特殊協議的支持,因此也常常被稱作 HTTP 流式傳輸。順序流式傳輸比較適合於高質量的多媒體片段,如片頭、片尾或者廣告等。
實 時流式傳輸保證媒體信號帶寬能夠與當前網絡狀況相匹配,從而使得流媒體數據總是被實時地傳送,因此特別適合於現場事件。實時流傳輸支持隨機訪問,即用戶可 以通過快進或者後退操作來觀看前面或者後面的內容。從理論上講,實時流媒體一經播放就不會停頓,但事實上仍有可能發生周期性的暫停現象,尤其是在網絡狀況 惡化時更是如此。與順序流傳輸不同的是,實時流傳輸需要用到特定的流媒體服務器,而且還需要特定網絡協議的支持。
Red5 是一個采用 Java 開發開源的 Flash 流媒體服務器。免費開源使軟件更加容易擴展,下載後你可以對源代碼進行修改;更加經濟,比起 FMS 高昂的費用,Red5 能為一般的應用節約大筆費用;同時服務器端的 Java 面向對象語言比起 FMS 服務器端的 ActionScript2 語言更加成熟。鑒於 Red5 的種種優勢,推出不久便被廣大用戶所接受。
Red 5 支持:
1. 把音頻(MP3)和視頻(FLV, F4V, MP4, 3GP)轉換成播放流;
2. 錄制客戶端播放流, 把攝像頭,麥克風等傳入的音頻視頻錄制保存到服務器;
3. 共享對象;
4. 現場直播流發布;
5. 遠程調用;
6. 協議:RTMP, RTMPT, RTMPS, and RTMPE。
為了便於開發人員進行二次開發,Red5 提供了很多接口。
一、JAVA 環境配置:下載的 JDK 安裝包,本文選擇的是jdk-6u10-rc2-bin-b32-windows-i586-p-12_sep_2008.exe。
二、確認你的安裝環境並選擇 Red5 安裝包:如果是 Windows 操作系統,可以下載對應的安裝文件 Red5 0.9 RC2(本文寫作時使用的該版本),如需下載最新版本或了解 Red5 其他相關信息,可以參考該頁面https://github.com/Red5/red5-server。
准備工作完成,一切就緒。
步驟一:首先安裝上面下載的 JDK 安裝包(備注:如果你先安裝 Red5,會提示找不到 JDK,你必須先完成步驟一再繼續以下操作)。安裝時首先安裝 JDK,必須記住安裝路徑,保持默認即可,默認是 C:\Program Files\Java\jdk1.6.0_10,然後安裝 JRE, 保持默認即可,默認是 C:\Program Files\Java\jre6。安裝完成後,必須配置環境變量,我的電腦–>屬性–>高級 選項卡–>環境變量 (N)–>找到 系統變量 (S) 下 新建(W),然後輸入 變量名(N):JAVA_HOME,變量值(V):上面 JDK 安裝路徑 C:\Program Files\Java\jdk1.6.0_10,確定即可,JDK 准備就緒。
步驟二:安裝 Red5,安裝 Red5 時,會要求輸入外網可訪問的 IP, 比如 121.52.209.62, 然後輸入可訪問的端口(Port),一般是 5080, 最後安裝完成即可。
經過上面精彩的介紹,相信大家對 Red5 會有所興趣,在這裡我給大家用一個簡單的應用實例,僅以登錄過程為例,來幫助大家更好的理解 Red5 中的一些概念和模型。本應用實例中,Server 端基於 Red5 0.9 RC2 采用 Java 編寫,而 Client 端則采用 Action Script。
由於 Red5 是在 Tomcat 中運行的,因此 Red5 項目與普通 JAVAEE 項目結構類似。不同點在於,Red5 的配置文件需要加上“red5-”前綴,在 Tomcat 啟動時,所有“red5-”被默認為 Red5 Server 的配置文件而不會被 Tomcat 加載,而後當 Red5 啟動時才會加載相應的配置文件。讓我們來看看 red5-web.xml 中都有哪些組成部分。
<bean id="web.context" class="org.red5.server.Context" autowire="byType"> <property name="scopeResolver" ref="red5.scopeResolver" /> <property name="serviceInvoker" ref="global.serviceInvoker" /> <property name="mappingStrategy" ref="global.mappingStrategy" /> <property name="clientRegistry" ref="IloveClientRegistry" /> </bean>
清單 1 中前三項 Property 為 Red5 項目默認的屬性。第四項“ClientRegistry”為項目自定義的 Context, 主要用於實現用戶注冊的功能。
<bean id="web.scope" class="org.red5.server.WebScope" init-method="register"> <property name="server" ref="red5.server" /> <property name="parent" ref="global.scope" /> <property name="context" ref="web.context" /> <property name="handler" ref="web.handler" /> <property name="contextPath" value="${webapp.contextPath}" /> <property name="virtualHosts" value="${webapp.virtualHosts}" /> </bean>
清單 2 中定義了 Red5 項目中 Scope 的默認值。如需要可以添加自己定義的 Scope,並給它賦值。
<bean id="web.handler" class="org.red5.server.webapps.Ilove.Application"> <property name="userInfoService" ref="userInfoService" /> </bean>
清單 3 重載了 web.handler,因此當有 Client 與 Server 提出連接請求時,org.red5.server.webapps.Ilove.Application 將被用於處理客戶請求。
接下來我們看下如何實現從 Flash 客戶端調用 Red5 應用的方法,以及如何使用 Scope 來判斷用戶登錄狀態。
圖 2 中展示了 Flash 客戶端中 ActionScript 面對不同 Connection 狀態的處理方法。由 Flash 客戶端發起的登錄請求,首先需要判斷當前與 Server 的 Connection 狀態, 只有狀態為”NetConnection.Connect,Sucess”時, 才可以向 Server 端調用方法“logicProcess”。 圖 3 中展示了不同 Connection 狀態時 Flash 客戶端會給出的提示。
public interface LoginInterface extends IStreamAwareScopeHandler { …… //用戶登錄時服務器端調用當前 connection 的方法 public String loginProcess(String[] args) throws FileNotFoundException, ParserConfigurationException, SAXException, IOException; //用戶登錄時服務器端報錯調用當前 connection 的方法 public void systemError(); /**用戶登出時客戶端端調用當前 connection 的方法 * * @param userName 需要剔除的用戶名 */ public void logoutProcess(String userName); …… }
如清單 4 所示,org.red5.server.webapps.Ilove.Application 實現了 LoginInterface 接口, 其中定義了一些客戶端可見的方法名稱。因為 org.red5.server.webapps.Ilove.Application 被定義為項目的 Handler,類中所有 public 方法都可以被客戶端調用。
public String loginProcess(String[] args) throws FileNotFoundException, ParserConfigurationException, SAXException, IOException { final IConnection conn = Red5.getConnectionLocal(); if (conn.getClient() == null) return SystemContent.NO_ENTRY; final IScope scope = conn.getScope(); final IClient client = conn.getClient(); final int code = (Integer) client.getAttribute("codeName"); //檢查當前登錄沖突 if (code == SystemContent.STATUS_CODE_DUPLICATEUSER) { //此用戶名已登錄,notify 客戶端不允許重復登錄 if (model.statusMap.get(args[0])) return SystemContent.NO_ENTRY; //如果沒有用戶登錄,則更新數據庫中 session 值為當前用戶 else { this.userInfoService.updateSession(args[0], (String) client .getAttribute("currentId")); } } //如果通過驗證,則 client 應該為 IloveStreamClient 類型 if (client instanceof IloveStreamClient) { boolean authenticated = ((IloveStreamClient) client) .isAuthenticated(); //當前驗證狀態 if (authenticated) { synchronized (model.statusMap) { model.statusMap.put(args[0], true); refreshUserList(conn, args[0], "refresh"); refreshUserList(conn, args[0], "add"); } invokeClientMethod(conn, "declarePublicSo", new Object[] { "chatingSO" }, null); messageAdapter .sendPublicMessage(so, "歡迎登錄!" + args[0], "系統機器人"); final String scheduleName = this.addScheduledJob(5000, new IloveUserListChecker(conn, args[0])); scope.setAttribute((String) client.getAttribute("currentId"), scheduleName); return args[0] + " found"; } } return args[0] + " not found"; }
如清單 5 所示,程序首先通過 Red5 的 GlobalScope 獲取當前用戶的 Credential,因為每個 Connection 在 Scope 中都是獨立存在的。登錄過程中會判斷當前用戶是否重復登錄,或者登錄信息是否正確。只有當用戶為 Authenticated 狀態時,服務器端才會調用 Flash 客戶端的方法,同時生成 shared Object 以幫助 Flash 客戶端初始化界面。
Red5 應用的部署
Red5 0.9 RC2 中已經內嵌了 Tomcat 服務器。因此 Red5 應用的部署和普通 JavaEE 應用在 Tomcat 中的部署方式是一樣的。這裡需要注意的是,上文中提到的 XML 配置文件必須是正確的,以防止運行報錯。圖 4 中是一個基於 Red5 應用的視頻聊天系統,當用戶登錄成功後,可以在當前的聊天室中與其他已登錄用戶進行文字交談或者視頻聊天。具體功能的實現就不在本文中闡述了。
圖 4. 視頻聊天系統界面
結束語