ビデオの例:ビデオジュークボックス

Flash Player 9 以降、Adobe AIR 1.0 以降

次の例では、順番に再生されるビデオのリストを動的にロードする、シンプルなビデオジュークボックスを構築します。 こうすると、一連のビデオチュートリアルを閲覧したり、ユーザーが要求したビデオの再生前にどの広告を再生するかを指定したりできるようなアプリケーションを構築することができます。この例は、ActionScript 3.0 の次のような機能を示しています。

  • ビデオファイルの再生の進行状況に基づく再生ヘッドの更新

  • ビデオファイルのメタデータの監視および解析

  • ネットストリームの特定のコーデックの処理

  • 動的にロードされた FLV のロード、再生、一時停止、停止

  • ネットストリームのメタデータに基づく、表示リストの Video オブジェクトのサイズ変更

このサンプルのアプリケーションのファイルを入手するには、 www.adobe.com/go/learn_programmingAS3samples_flash_jp を参照してください。 ビデオジュークボックスアプリケーションのファイルは、Samples/VideoJukebox フォルダーにあります。 このアプリケーションは次のファイルで構成されています。

ファイル

説明

VideoJukebox.fla

または

VideoJukebox.mxml

Flex(MXML)または Flash(FLA)のメインアプリケーションファイル。

VideoJukebox.as

このクラスは、アプリケーションの主な機能を提供します。

playlist.xml

ビデオジュークボックスにロードされるビデオファイルをリストするファイル。

ビデオプレイリストファイルのロード

外部の 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 オブジェクトを設定します。

ユーザーインターフェイスの作成

ユーザーインターフェイスを構築するには、表示リストに 5 つの 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 というインスタンス名を与えます。次のコードは、Slider インスタンスの liveDragging プロパティを true に設定し、Slider インスタンスの 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 プロパティを manual に設定します。

positionBar.mode = ProgressBarMode.MANUAL;

最後に、表示リストに Label インスタンスを追加し、 positionLabel というインスタンス名を与えます。Label インスタンスの値は、Timer インスタンスによって設定されます。

ビデオオブジェクトのメタデータの監視

Flash Player がロードされた各ビデオのメタデータを検出すると、 onMetaData() コールバックハンドラーが NetStream オブジェクトの client プロパティで呼び出されます。次のコードではオブジェクトを初期化し、指定のコールバックハンドラーを設定します。

client = new Object(); 
client.onMetaData = metadataHandler;

metadataHandler() メソッドは、コードの前部で指定されたメタプロパティにデータをコピーします。これにより、アプリケーション全体で、いつでも現在のビデオのメタデータにアクセスすることが可能になります。 次に、ステージ上の Video オブジェクトは、メタデータから返されたサイズに合わせてサイズ変更されます。 最後に、再生中のビデオのサイズに合わせて 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; 
}

Video の動的なロード

ビデオを動的にロードするには、アプリケーションで NetConnection および NetStream オブジェクトを使用する必要があります。 次のコードは NetConnection オブジェクトを作成し、 null connect() メソッドに渡します。 null を指定すると、Flash Player は、Flash Media Server などのサーバーではなく、ローカルサーバー上のビデオに接続します。

次のコードは、NetConnection および NetStream インスタンスの両方を作成し、 netStatus イベントのイベントリスナーを定義し、 client オブジェクトを 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 が実行されるたびに、ProgressBar クラスの setProgress() メソッドを呼び出すことで positionBar プログレスバーインスタンスの現在の位置が更新され、Label インスタンスである positionLabel は、現在のビデオの経過時間と合計時間によって更新されます。

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 プロパティを設定します。ビデオジュークボックスアプリケーションでは、Slider インスタンスである volumeSlider の値を変更することでボリュームレベルを変更することができます。次のコードは、NetStream オブジェクトの soundTransform プロパティに設定されている SoundTransform オブジェクトに Slider コンポーネントの値を割り当てることで、ボリュームレベルを変更する方法を示します。

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; 
    } 
}