• お役立ち

Brightcoveの動画をFlashコンテンツに読み込む

  • このエントリーをはてなブックマークに追加
  • LINEで送る

今回、うちで協力させていただいているFlash案件で、ブライトコーブさんの動画プラットフォームを読み込んで表示する機会がありました。ドキュメントの解読など、ちょっと組み込みまでに苦労したので、備忘録を兼ねて記事にまとめました。

※2011.07.22追記:
「イベントハンドラの設定と動画の読み込み」の項目に、フルスクリーン時のイベントハンドラの記述を追加しました。
※2011.07.22さらに追記:
なぜかフルスクリーンイベントが発生しない不具合に遭遇しているので、一旦フルスクリーン関係の記述に打ち消し線を設定しました。
※2011.07.27追記:
Brightcoveインスタンスの生成時に指定するパラメータのうち、「playerId」の語尾の「d」が大文字になっていたのを修正しました。また、「playerKey」というパラメータも必要なようなので、追加しました。また、「skipContentCall」というパラメータも追加しました。
※2011.07.28追記:
フルスクリーン時のイベントが取れるようになりました。Event.FULLSCREENではなく、FullScreenEvent.FULL_SCREENなんですね。そのあたりを改めて加筆しました。
※2011.09.21追記:
APIの通信先が*.brightcove.comから*.brightcove.co.jpに変更になったそうなので、その部分を反映しました。

Brightcoveとは?

動画配信のプラットフォームや、スマホ向けのアプリ配信のプラットフォームのサービスを提供してらっしゃる会社さんみたいです。今回はこちらの動画配信プラットフォームのサービスを使いました。

オンライン動画を簡単に | Brightcove

上記ページにもあるように、動画のアップロード、エンコード、コンテンツ管理、プレーヤーの外観設定など様々な設定ができるようです。今回はそのあたりの作業は先方でやっていただいたので省略します(というより、やり方はわかっていません(汗))。うちに課せられた作業は、

  • 製作中のFlashコンテンツの中に、
  • ブライトコーブの所定の動画IDの動画を、
  • ブライトコーブの所定のプレイヤーIDのプレイヤーで表示し、
  • 動画の再生が終了したら次の処理に移る。

・・・というものです。

必要なファイルの入手

開発時に必要なファイルは、BrightcovePlayer.asBrightcovePlayerAPI.swcです。それぞれ下記で入手します。

BrightcovePlayer.as
下記ページ「要件」の所から、サンプルファイルをダウンロードします。ダウンロードしたファイルの中にasファイルが入ってます。
・Flash ドキュメントに Brightcove プレーヤを埋め込む | Brightcove Support

※2011.09.21現在で上記ファイルを再度ダウンロードしたところ、上記に含まれるBrightcovePlayer.asの中では、APIのURLなどの指定が全て「~.brightcove.com」になっていました。このため、現時点ではこれらの箇所を手動で「~.brightcove.co.jp」に書き換える必要がありそうです。
BrightcovePlayerAPI.swc
下記ページ冒頭の文中に、「プレーヤAPI SWCを含むZipファイルをダウンロード」というリンクがあります。ここからダウンロードしたファイルの中にswcファイルが入ってます。
・プレーヤ API SWC | Brightcove Support

asファイルとswcファイルが手に入ったら、作業中のプロジェクト内の適切な場所に保存します。swcファイルは忘れずにflaファイルの方にパスを通しましょう。

スクリプトのポイント

準備ができたらスクリプトを記述します。完成形のサンプルは本記事の末尾に表示しますので、まずはステップ毎に説明を。

BrightcovePlayerインスタンスの生成

var config:Object = { };
config["@videoPlayer"] = "14459790001";
config["playerId"] = "441686777001";
config["playerKey"] = "441686777001";
config["width"] = 400;
config["height"] = 200;
config["isVid"] = true;
config["isUI"] = true;
config["skipContentCall"] = true;

player = new BrightcovePlayer(config);

まずはBrightcovePlayerクラスのインスタンスを作成します。コンストラクタには引数として以下のパラメータを持つオブジェクトを指定します。

パラメータ 説明
@videoPlayer 表示する動画の動画ID
playerId / playerKey 動画を表示するプレイヤーのプレイヤーID。このプレイヤーIDを変更することで、プレイヤーの外観を変更できます。シークバーの有無やプレイヤーのサイズなどは、ブライトコーブ側の管理画面(?)で設定できるようです。ブライトコーブのドキュメントには「どのプレーヤをページにロードするかを変更したい場合、playerId パラメータと playerKey パラメータの両方の値を変更する必要があります。」という記述がありました。
width / height プレイヤー領域の幅と高さ。上記ブライトコーブ側の設定によっては、ここでwidthとheightを指定しても無視され、強制的にデフォルトのサイズで表示されることもあるようです。
isVid / isUI 実はよく意味をわかってませんが、これらの値をtrueにしないと、うまく動画を読み込めませんでした・・・。なので、お約束的な設定ということで。
skipContentCall デフォルトでは、プレイヤーが読み込まれると、指定された動画データがロードされ、その動画に割り当てられたキャプチャ画像(静止画)が表示されます。このパラメータをtrueに設定すると、明示的にVideoPlayerModule.loadVideoメソッドで動画を呼び出さない限り動画データをロードしなくなるようで、キャプチャ画像が表示されなくなりました。

APIのドキュメントを見ると、どうもこの他にもいろいろパラメータはあるようです

BrightcovePlayerWrapperインスタンスの生成

wrapper = new BrightcovePlayerWrapper(player);
wrapper.addEventListener(ExperienceEvent.TEMPLATE_LOADED, onTemplateLoaded, false, 0, true);
this.addChild(wrapper);

実は前項で生成したBrightcovePlayerインスタンスをステージにaddChildするだけでも動画は表示されます。ただ、それだと動画の開始や終了などのイベントを拾って操作することができません。なので、表示オブジェクトとしてはBrightcovePlayerWrapperクラスを使います。

BrightcovePlayerWrapperの生成時には、引数としてBrightcovePlayerインスタンスを指定します。

BrightcovePlayerWrapperが生成されると、プレイヤーのデータを自動的にブライトコーブから取得するようです。データがロードされると、ExperienceEvent.TEMPLATE_LOADEDイベントが発生します。

【注】
ブライトコーブ側の管理画面で設定するプレイヤーの設定次第によっては、このイベントが発生しない場合があるようです。

プレーヤの設定を編集する | Brightcove Support

上記ページ「[グローバル] タブの設定」の[Web 設定]の中にある[ActionScript/JavaScript API を有効にする]がチェックされていることを確認してください(してもらってください)。

モジュールへの参照の取得

playerModule = wrapper.getModule(APIModules.VIDEO_PLAYER) as VideoPlayerModule;
expModule = wrapper.getModule(APIModules.EXPERIENCE) as ExperienceModule;

プレイヤーのデータがロードされたら、今後の処理のためにモジュールへの参照を取得します。APIドキュメントによると、10種類ほどのモジュールがあるようですが、今回はVideoPlayerModuleExperienceModuleで事足りました。

イベントハンドラの設定と動画の読み込み

playerModule.addEventListener(MediaEvent.PLAY, onMediaPlay, false, 0, true);
playerModule.addEventListener(MediaEvent.BUFFER_BEGIN, onMediaBufferBegin, false, 0, true);
playerModule.addEventListener(MediaEvent.BUFFER_COMPLETE, onMediaBufferComplete, false, 0, true);
playerModule.addEventListener(MediaEvent.BEGIN, onMediaBegin, false, 0, true);
playerModule.addEventListener(MediaEvent.STOP, onMediaStop, false, 0, true);
playerModule.addEventListener(MediaEvent.COMPLETE, onMediaComplete, false, 0, true);
this.stage.addEventListener(FullScreenEvent.FULL_SCREEN, onFullScreen, false, 0, true);

this.stage.dispatchEvent(new FullScreenEvent(FullScreenEvent.FULL_SCREEN));

playerModule.loadVideo("14459790001");

動画の再生状態などに関するイベントハンドラは全てVideoPlayerModuleに設定します。やはりAPIドキュメントを見ると多数のイベントがありますが、今回は6種類ほど使ってみました。意味はそれぞれ多分以下のような感じ・・・?

イベント名 多分こんな内容
mediaPlay (MediaEvent.PLAY) メディアの再生命令発動イベント?
mediaBufferBegin (MediaEvent.BUFFER_BEGIN) メディアのバッファ開始イベント?
mediaBufferComplete (MediaEvent.BUFFER_COMPLETE) メディアのバッファ終了イベント?
mediaBegin (MediaEvent.BEGIN) メディアの再生開始イベント?
mediaStop (MediaEvent.STOP) メディアの再生停止イベント?
mediaComplete (MediaEvent.COMPLETE) メディアの再生終了イベント?

また、プレイヤーの外観によっては、再生中の動画をフルスクリーン表示させるボタンが付いてる場合があります。その場合に備えて、フルスクリーンの起動/終了時のイベントについても、念の為にイベントハンドラの末尾に記述しておきました。同時に、初期化のために、フルスクリーンイベントを一回手動で発生させています。

VideoPlayerModuleloadVideoメソッドに、引数として動画IDを指定することで、実際の動画の読み込みと再生が始まります。BrightcovePlayerインスタンスの生成時にも動画IDを設定してるので、なんか二度手間な感がありますよね。ひょっとしたらどちらか省略可能なのかもしれませんが、とりあえず今回はこのようにしました。

プレイヤーの削除

今回のサンプルでは、動画の再生が終了したら、プレイヤーを非表示にすることを想定しています。この時にポイントとなるのは、動画の再生終了と同時にプレイヤーを破棄するとエラーが起こるということです。どうも再生終了後に何らかの処理を行ってるようなので、Timerを使ってちょっとだけタイミングをずらしてからプレイヤーの破棄を行ってます。

また、これは動画の再生途中にSKIPさせて次の処理を行う場合などに関連してくるのですが、単にBrightcovePlayerWrapperを削除しただけだと、背後で動画の音声などが流れたままになってしまいます。試行錯誤したところ、ExperienceModuleインスタンスをunloadするといいようでした。

SSL下での運用

通常のHTTPでの運用であれば多分これで問題ありません。ただ、SSLサーバ内で運用する場合、以下の通信設定が必要なようでした。

Security.allowDomain("https://sadmin.brightcove.co.jp");
Security.allowInsecureDomain("http://admin.brightcove.co.jp");

スクリプトのサンプル

以下が、今回作成したサンプルクラス(Example.as)のソース全文です。

package  {
	import BrightcovePlayer;
	import com.brightcove.api.APIModules;
	import com.brightcove.api.BrightcovePlayerWrapper;
	import com.brightcove.api.events.ExperienceEvent;
	import com.brightcove.api.events.MediaEvent;
	import com.brightcove.api.modules.ExperienceModule;
	import com.brightcove.api.modules.VideoPlayerModule;
	import flash.display.Sprite;
	import flash.display.StageDisplayState;
	import flash.events.Event;
	import flash.events.FullScreenEvent;
	import flash.events.TimerEvent;
	import flash.system.Security;
	import flash.utils.Timer;
	
	public final class Example extends Sprite {
		private var player:BrightcovePlayer;
		private var wrapper:BrightcovePlayerWrapper;
		private var playerModule:VideoPlayerModule;
		private var expModule:ExperienceModule;
		private var completeTimer:Timer;
		
		public function Example() {
			addEventListener(Event.ADDED_TO_STAGE, onAddedToStage, false, 0, true);
		}
		
		
		private function onAddedToStage(e:Event):void {
			removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
			addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage, false, 0, true);
			
			//SSL下での通信用にドメイン通信設定
			Security.allowDomain("https://sadmin.brightcove.co.jp");
			Security.allowInsecureDomain("http://admin.brightcove.co.jp");
			
			//BrightcovePlayerインスタンスの初期値設定
			var config:Object = { };
			config["@videoPlayer"] = "14459790001";	//動画ID
			config["playerId"] = "441686777001";	//プレイヤーID
			config["playerKey"] = "441686777001";	//プレイヤーID
			config["width"] = 400;	//表示領域の横幅
			config["height"] = 200;	//表示領域の高さ
			config["isVid"] = true;	//お約束
			config["isUI"] = true;	//お約束
			config["skipContentCall"] = true;	//キャプチャ画像非表示化
			
			//BrightcovePlayerインスタンスの生成
			player = new BrightcovePlayer(config);
			
			//BrightcovePlayerWrapperインスタンスの生成
			wrapper = new BrightcovePlayerWrapper(player);
			wrapper.addEventListener(ExperienceEvent.TEMPLATE_LOADED, onTemplateLoaded, false, 0, true);
			this.addChild(wrapper);
		}
		
		private function onTemplateLoaded(e:ExperienceEvent):void {
			//不要なイベントハンドラの削除
			wrapper.removeEventListener(ExperienceEvent.TEMPLATE_LOADED, onTemplateLoaded);
			
			//モジュールへの参照の取得
			playerModule = wrapper.getModule(APIModules.VIDEO_PLAYER) as VideoPlayerModule;
			expModule = wrapper.getModule(APIModules.EXPERIENCE) as ExperienceModule;
			
			//イベントハンドラの設定
			playerModule.addEventListener(MediaEvent.PLAY, onMediaPlay, false, 0, true);
			playerModule.addEventListener(MediaEvent.BUFFER_BEGIN, onMediaBufferBegin, false, 0, true);
			playerModule.addEventListener(MediaEvent.BUFFER_COMPLETE, onMediaBufferComplete, false, 0, true);
			playerModule.addEventListener(MediaEvent.BEGIN, onMediaBegin, false, 0, true);
			playerModule.addEventListener(MediaEvent.STOP, onMediaStop, false, 0, true);
			playerModule.addEventListener(MediaEvent.COMPLETE, onMediaComplete, false, 0, true);
			this.stage.addEventListener(FullScreenEvent.FULL_SCREEN, onFullScreen, false, 0, true);
			
			//初期化のためにフルスクリーンイベントを発生
			this.stage.dispatchEvent(new FullScreenEvent(FullScreenEvent.FULL_SCREEN));
			
			//所定の動画IDの動画の読み込み開始
			playerModule.loadVideo("14459790001");
		}
		
		//メディアの再生命令発動時のイベントハンドラ
		private function onMediaPlay(e:MediaEvent):void {
			trace("================onMediaPlay");
		}
		//メディアのバッファ開始時のイベントハンドラ
		private function onMediaBufferBegin(e:MediaEvent):void {
			trace("================onMediaBufferBegin");
		}
		//メディアのバッファ終了時のイベントハンドラ
		private function onMediaBufferComplete(e:MediaEvent):void {
			trace("================onMediaBufferComplete");
		}
		//メディアの再生開始時のイベントハンドラ
		private function onMediaBegin(e:MediaEvent):void {
			trace("================onMediaBegin");
		}
		//メディアの再生停止時のイベントハンドラ
		private function onMediaStop(e:MediaEvent):void {
			trace("================onMediaStop");
		}
		//メディアの再生終了時のイベントハンドラ
		private function onMediaComplete(e:MediaEvent):void {
			trace("================onMediaComplete");
			
			completeTimer = new Timer(100, 1);
			completeTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete, false, 0, true);
			completeTimer.start();
		}
		//フルスクリーン起動・終了時のイベントハンドラ
		private function onFullScreen(e:FullScreenEvent):void {
			switch(stage.displayState) {
				case StageDisplayState.FULL_SCREEN:
					
					// 必要に応じてフルスクリーン起動時の処理を記述
					
					break;
				case StageDisplayState.NORMAL:
					
					// 必要に応じてフルスクリーン終了時の処理を記述
					
					break;
			}
		}
		
		private function onTimerComplete(e:TimerEvent):void {
			//イベントリスナを削除
			completeTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);
			playerModule.removeEventListener(MediaEvent.PLAY, onMediaPlay);
			playerModule.removeEventListener(MediaEvent.BUFFER_BEGIN, onMediaBufferBegin);
			playerModule.removeEventListener(MediaEvent.BUFFER_COMPLETE, onMediaBufferComplete);
			playerModule.removeEventListener(MediaEvent.BEGIN, onMediaBegin);
			playerModule.removeEventListener(MediaEvent.STOP, onMediaStop);
			playerModule.removeEventListener(MediaEvent.COMPLETE, onMediaComplete);
			this.stage.removeEventListener(FullScreenEvent.FULL_SCREEN, onFullScreen);
			
			//プレイヤーの破棄
			expModule.unload();
			this.removeChild(wrapper);
		}
		
		private function onRemovedFromStage(e:Event):void {
			removeEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
		}
		
	}
	
}
星虹思械BRICOLEUR

関連コンテンツ