視訊範例:視訊點播機Flash Player 9 以及更新的版本,Adobe AIR 1.0 以及更新的版本 下列範例會建立簡單的視訊點唱機,它能動態地載入要依序播放的視訊清單。這讓您建立的應用程式可讓使用者瀏覽一系列的視訊教學課程,或者指定在傳遞使用者要求的視訊之前,應該播放哪些廣告。這個範例將示範下列 ActionScript 3.0 的功能:
若要取得此樣本的應用程式檔案,請參閱 www.adobe.com/go/learn_programmingAS3samples_flash_tw。您可以在 Samples/VideoJukebox 資料夾中找到「視訊點唱機」應用程式檔案,此應用程式是由下列檔案組成:
載入外部視訊播放清單檔案外部 playlist.xml 檔案會指定要載入哪些視訊,以及要播放它們的順序。為了載入 XML 檔案,您必須使用 URLLoader 物件以及 URLRequest 物件,如下列程式碼所示: uldr = new URLLoader(); uldr.addEventListener(Event.COMPLETE, xmlCompleteHandler); uldr.load(new URLRequest(PLAYLIST_XML_URL)); 此程式碼是置於 VideoJukebox 類別的建構函式中,因此在執行其它程式碼之前會先載入檔案。一旦 XML 檔案載入完成,就會呼叫 xmlCompleteHandler() 方法,以便將外部檔案剖析為 XML 物件,如下列程式碼所示: private function xmlCompleteHandler(event:Event):void { playlist = XML(event.target.data); videosXML = playlist.video; main(); } playlist XML 物件包含來自外部檔案的原始 XML,而視訊 XML 則是一種 XMLList 物件,只包含視訊節點。在下列程式碼片段中可以看到樣本 playlist.xml 檔案: <videos> <video url="video/caption_video.flv" /> <video url="video/cuepoints.flv" /> <video url="video/water.flv" /> </videos> 最後,xmlCompleteHandler() 方法會呼叫 main() 方法,它會在顯示清單上設定各種組件實體,並設定用來載入外部 FLV 檔的 NetConnection 與 NetStream 物件。 建立使用者介面若要建立使用者介面,您必須拖曳五個 Button 實體到顯示清單上,並為它們指定下列實體名稱:playButton、pauseButton、stopButton、backButton 和 forwardButton。 對於每一個 Button 實體,您都必須指定其 click 事件的處理常式,如下列程式碼片段所示: playButton.addEventListener(MouseEvent.CLICK, buttonClickHandler); pauseButton.addEventListener(MouseEvent.CLICK, buttonClickHandler); stopButton.addEventListener(MouseEvent.CLICK, buttonClickHandler); backButton.addEventListener(MouseEvent.CLICK, buttonClickHandler); forwardButton.addEventListener(MouseEvent.CLICK, buttonClickHandler); buttonClickHandler() 方法會使用 switch 陳述式判斷按下的是哪個按鈕實體,如下列程式碼所示: private function buttonClickHandler(event:MouseEvent):void { switch (event.currentTarget) { case playButton: ns.resume(); break; case pauseButton: ns.togglePause(); break; case stopButton: ns.pause(); ns.seek(0); break; case backButton: playPreviousVideo(); break; case forwardButton: playNextVideo(); break; } } 接下來,將 Slider 實體加入至顯示清單,並為它指定實體名稱為 volumeSlider。下列程式碼會將滑動軸實體的 liveDragging 屬性設定為 true,並為滑動軸實體的 change 事件定義事件偵聽程式: volumeSlider.value = volumeTransform.volume; volumeSlider.minimum = 0; volumeSlider.maximum = 1; volumeSlider.snapInterval = 0.1; volumeSlider.tickInterval = volumeSlider.snapInterval; volumeSlider.liveDragging = true; volumeSlider.addEventListener(SliderEvent.CHANGE, volumeChangeHandler); 將 ProgressBar 實體加入至顯示清單,並為它指定實體名稱為 positionBar。將此實體的 mode 屬性設定為手動,如下列程式碼片段所示: positionBar.mode = ProgressBarMode.MANUAL; 最後,將 Label 實體加入至顯示清單,並為它指定實體名稱為 positionLabel。計時器實體將會設定這個 Label 實體的值。 偵聽視訊物件的中繼資料當 Flash Player 遇到每個載入視訊的中繼資料時,就會針對 NetStream 物件的 client 屬性呼叫 onMetaData() 回呼處理常式。下列程式碼會初始化 Object,並設定指定的回呼處理常式: client = new Object(); client.onMetaData = metadataHandler; metadataHandler() 方法會將其資料複製到程式碼前面部分所定義的 meta 屬性。這可讓您在整個應用程式中隨時存取目前視訊的中繼資料。接下來,會調整「舞台」上視訊物件的大小,以符合從中繼資料傳回的尺寸。最後,會移動 positionBar 進度列實體,並根據目前播放的視訊大小調整大小。下列程式碼包含整個 metadataHandler() 方法: private function metadataHandler(metadataObj:Object):void { meta = metadataObj; vid.width = meta.width; vid.height = meta.height; positionBar.move(vid.x, vid.y + vid.height); positionBar.width = vid.width; } 動態載入 視訊若要動態載入各個視訊,應用程式必須使用 NetConnection 與 NetStream 物件。下列程式碼會建立 NetConnection 物件,並將 null 傳遞給 connect() 方法。透過指定 null,Flash Player 會連接至本機伺服器上的視訊,而不會連接至伺服器,如 Flash Media Server。 下列程式碼會建立 NetConnection 與 NetStream 實體、為 netStatus 事件定義事件偵聽程式,並將 client Object 指定給 client 屬性: nc = new NetConnection(); nc.connect(null); ns = new NetStream(nc); ns.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); ns.client = client; 每次變更視訊狀態時,就會呼叫 netStatusHandler() 方法。這包括當視訊開始或停止播放、正在緩衝或是如果找不到視訊串流時。下列程式碼會列出 netStatusHandler() 事件: private function netStatusHandler(event:NetStatusEvent):void { try { switch (event.info.code) { case "NetStream.Play.Start": t.start(); break; case "NetStream.Play.StreamNotFound": case "NetStream.Play.Stop": t.stop(); playNextVideo(); break; } } catch (error:TypeError) { // Ignore any errors. } } 上述程式碼會評估 info 物件的程式碼屬性,並將程式碼篩選為「NetStream.Play.Start」、「NetStream.Play.StreamNotFound」或「NetStream.Play.Stop」。其它所有程式碼將會遭忽略。如果網路串流已開始,程式碼就會啟動 Timer 實體並更新播放磁頭。如果找不到或無法停止網路串流,就會停止 Timer 實體,而且應用程式會嘗試播放在播放清單中的下一個視訊。 每次 Timer 執行時,positionBar 進度列實體會呼叫 ProgressBar 類別的 setProgress() 方法以更新其目前的位置,而 positionLabel Label 實體則會以目前視訊的已經過時間及總時間來更新。 private function timerHandler(event:TimerEvent):void { try { positionBar.setProgress(ns.time, meta.duration); positionLabel.text = ns.time.toFixed(1) + " of " meta.duration.toFixed(1) + " seconds"; } catch (error:Error) { // Ignore this error. } } 控制視訊的音量您可以設定 NetStream 物件的 soundTransform 屬性,針對動態載入的視訊控制音量。視訊點唱機應用程式可讓您變更 volumeSlider Slider 實體的值以修改音量。下列程式碼將說明如何變更音量,方法是將 Slider 組件的值指定給 SoundTransform 物件,而該物件會設定為 NetStream 物件的 soundTransform 屬性: private function volumeChangeHandler(event:SliderEvent):void { volumeTransform.volume = event.value; ns.soundTransform = volumeTransform; } 控制視訊播放當視訊到達視訊串流的結尾或是使用者跳到上一個或下一個視訊時,應用程式的其餘部分就會控制視訊播放。 下列方法會從目前選取的索引之 XMLList 擷取視訊 URL: private function getVideo():String { return videosXML[idx].@url; } playVideo() 方法會呼叫 NetStream 物件的 play() 方法以載入目前選取的視訊: private function playVideo():void { var url:String = getVideo(); ns.play(url); } playPreviousVideo() 方法會遞減目前的視訊索引、呼叫 playVideo() 方法以載入新視訊檔案,並將進度列設定成可以看見: private function playPreviousVideo():void { if (idx > 0) { idx--; playVideo(); positionBar.visible = true; } } 最後一個方法 playNextVideo() 會遞增視訊索引並呼叫 playVideo() 方法。如果目前的視訊是播放清單中的最後一個視訊,就會呼叫 Video 物件的 clear() 方法,而進度列實體的 visible 屬性會設定為 false: private function playNextVideo():void { if (idx < (videosXML.length() - 1)) { idx++; playVideo(); positionBar.visible = true; } else { idx++; vid.clear(); positionBar.visible = false; } } |
|