流媒體及FLV播放器相關知識點

lishiran發表於2009-07-28
一、 兩種協議區別介紹

Action Script 3.0(簡稱AS)開發Browser Player時,需要用NetStream,但現在NetStream.play只支援HttpFile兩種協議。上網檢查youtubetudouyouku,發現他們用的播放協議也都是Http。而以Flash Media Server(簡稱FMS)或Red5作為流媒體伺服器時,它們提供的是RTMP協議,且這兩種流媒體伺服器是專門做過最佳化的。這兩種協議,HTTPRTMP,有幾點不同:

[@more@]

1)用HTTP方式: 先透過IIS FLV下載到本地快取,然後再透過NetConnection的本地連線來播放這個FLV,這種方法是播放本地的影片,並不是播放伺服器的影片。因此在本地快取裡可以找到這個FLV。其優點就是伺服器下載完這個FLV,伺服器就沒有消耗了,節省伺服器消耗。其缺點就是FLV會快取在客戶端,對FLV的保密性不好。

2)用RTMP方式: 透過NetConnection連線到FMS/Red5伺服器,並實時播放伺服器的FLV檔案,這種方式可以任意選擇影片播放點,並不象HTTP方式需要快取完整個FLV檔案到本地才可以任意選擇播放點,其優點就是在本地快取裡是找不到這個FLV檔案的。其優點就是FLV不會快取在客戶端,FLV的保密性好,其缺點就是消耗伺服器資源,連線始終是實時的。

由以上分析可以知道,Http方式是本地播放,而RTMP方式是伺服器實時播放。

二、 AS介紹

AS 3.0開始採用物件導向的設計,而在執行速度上也有了很大的提高。在物件導向的基礎上,AS也採納了類C#JavaPackagenamespace邏輯組織結構,更方便於RIA的開發。

AS通常可以在3種環境下進行開發。

(1) 文字編輯器和編譯器。

安裝AS的編譯器,利用記事本等文字編輯器進行開發,儲存為AS檔案後進行編譯即可。通常可以利用Ant組織編譯生成swf

(2) 利用Adobe Flash CS 3進行開發

AdobeMacromedia併入旗下後,便推出了不同於以往Macromedia Flash 8.0版本號的Adobe Flash CS 3。在Flash CS3中,使用者可以方便的將設計FLASH場景、圖層等同編寫AS指令碼相結合。同時,由於Flash CS3內建了很多Flash控制元件,使用者可以將透過fl.control這個開發包方便的使用這些控制元件。

(3) 利用Flex Builder 3進行開發

這是一種基於EclipseIDE,熟悉Eclipse的使用者可以像編寫Java程式一樣來編寫AS。同時Flex Builder 3的主要功能是為基於Flex框架程式提供了良好的開發環境。若需要在Flex Builder 3AS工程中使用內建的控制元件,首先需要將Flash CS3中的標準庫匯入到場景中,然後釋出成為swc檔案。最後將此swc檔案匯入到AS的編譯路徑中即可。

三、基於ASFlv Player

(1) 自行編寫Flv Player

編寫Flv Player僅需要對AS相關NetStream操作部分有些瞭解, HTMLJS的基礎知識。下面是一個基本的範例:

package {

import fl.controls.Button;

import flash.display.Sprite;

import flash.events.*;

import flash.media.Video;

import flash.net.NetConnection;

import flash.net.NetStream;

import flash.text.TextField;

public class Player extends Sprite

{

private var _width:int;

private var _height:int;

private var _stream:NetStream;

private var _connection:NetConnection;

private var _video:Video;

private var _playbackTime:TextField = new TextField();

private var _duration:uint;

private var _info:TextField = new TextField();

private var btStart:Button = new Button();

private var btStop:Button = new Button();

private var btPause:Button = new Button();

private var movie:String = "";

private var status:Boolean = true;

public function Player()

{

initialize();

var param:Object = root.loaderInfo.parameters;

movie = String(param["movie"]);

_info.y = 360;

this.addChild(_info);

}

private function initialize():void{

_connection = new NetConnection();

_connection.connect(null);

_stream = new NetStream(_connection);

_stream.addEventListener(NetStatusEvent.NET_STATUS, onStatus);

_stream.bufferTime = 10;

_video = new Video();

this.addChild(_video);

_video.attachNetStream(_stream);

var client:Object = new Object( );

client.onMetaData = onMetaData;

_stream.client = client;

_playbackTime.y = 300;

addChild(_playbackTime);

addEventListener(Event.ENTER_FRAME, onEnterFrame);

btStart.label = "start";

btStart.y = 300;

btStart.x = 0;

btStart.addEventListener(MouseEvent.CLICK, startButtonAction);

addChild(btStart);

btStop.label = "stop";

btStop.y = 300;

btStop.x = 120;

btStop.addEventListener(MouseEvent.CLICK, stopButtonAction);

addChild(btStop);

btPause.label = "pause";

btPause.y = 300;

btPause.x = 240;

btPause.addEventListener(MouseEvent.CLICK, pauseButtonAction);

addChild(btPause);

}

private function startButtonAction(e:MouseEvent):void{

_stream.play(movie);

}

private function stopButtonAction(e:MouseEvent):void{

_stream.close();

}

private function pauseButtonAction(e:MouseEvent):void{

if(status){

_stream.pause();

status = false;

}else{

_stream.resume();

status = true;

}

}

private function onMetaData(data:Object):void {

_duration = data.duration;

}

private function onEnterFrame(event:Event):void {

if(_duration > 0 && _stream.time > 0) {

_playbackTime.text = Math.round(_stream.time) + " / " +

Math.round(_duration);

}

}

private function onStatus(event:NetStatusEvent):void {

if(_video.videoWidth > 0 && _video.width != _video.videoWidth) {

_width = _video.videoWidth;

_height = _video.videoHeight;

var param:Object = root.loaderInfo.parameters;

var widthString:String = String(param["width"]);

var heightString:String = String(param["height"]);

var width:int = -1;

var height:int = -1;

if(widthString != "undefined"){

width = int(widthString);

}

if(heightString != "undefined"){

height = int(heightString);

}

if(width == -1){

if(height == -1){

_video.width = _width;

_video.height = _height;

}else{

_video.height = height;

_video.width = _width * height / _height;

}

}else{

_video.width = width;

_video.height = _height * width / _width;

}

}

}

}

}

(2) 使用開源的Flv player

推薦使用Flowplayer,可以下載它的原始碼,同樣是利用ant進行編譯。但是需要注意的是,需要進行簡單的修改。

build.properties檔案中修改MTASC_BINSWFMILL_BIN的值

//MTASC_BIN=/opt/mtasc/mtasc

MTASC_BIN=bin/mtasc/mtasc.exe

// You should use swfmill version 0.2.11 (will not work with the newer version)

//SWFMILL_BIN=/usr/local/bin/swfmill

SWFMILL_BIN=bin/swfmill/swfmill.exe

skinbuild.xml檔案中

value="${SWFMILL_BIN}"

else="${SWFMILL_BIN}">

<!--原來是value="${SWFMILL_BIN_WIN}" else="${SWFMILL_BIN}" --&gt

將更改後,執行ant即可,就可以得到重新編譯好的flowplayer

當需要更改播放器皮膚,特別是需要將播放器皮膚提示資訊的英文改為中文,即修改skin.as部分程式碼,這時候就必須要重新編譯了。

四、支援RTMP協議的Red5 Server

Red5Java實現的一種開源的Flash流媒體伺服器,它支援FLVMP3格式的Streaming Audio/VideoFLV格式的Recording Client Stream、共享物件、實時流釋出等多種功能。

當使用Red5作為Server時,需要完成客戶端和伺服器端兩部分的工作。在伺服器端,寫自己的應用程式,即rtmp服務的提供。這個應用程式的入口應該extends ApplicationAdapter這個類,然後將它部署到Server上。伺服器端示例程式碼如下:

import org.red5.server.adapter.ApplicationAdapter;

public class Application extends ApplicationAdapter {

public Double add(Double a, Double b){

return a + b;

}

}

在客戶端由AS完成,去訪問伺服器端構造的服務,示例程式碼如下

nc = new NetConnection();

nc.connect("rtmp://localhost/myapp");

nc.onResult = function(obj) {

trace("The result is " + obj);

}

nc.call("add", nc, 1, 2);

這樣就完成了基本的實現了AS透過RTMP協議呼叫Red5 伺服器端所提供的服務。更多的具體內容,可以參考Red5文件去實踐。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/9099175/viewspace-1024676/,如需轉載,請註明出處,否則將追究法律責任。

相關文章