ActionScript 3: 外部mp4ファイルの読み込み・再生、そしてストリーミング | ベンチャー企業 CIO: 池谷 義則ブログ&経営、ビジネス、プログラミング技術や便利なオープンソースの紹介

ベンチャー企業 CIO: 池谷 義則ブログ&経営、ビジネス、プログラミング技術や便利なオープンソースの紹介

SKYAVY, INC. CIOの池谷義則のブログ & ベンチャー企業 & 経営、ビジネス、プログラミング技術や便利なオープンソースの紹介

慣れないフラッシュの仕事をすることになった。
で、少々面倒な事になって、色々調べたら解決したので、それについて書こうと思う。

今回の仕様は以下の通り:

  1. 外部のmp4ファイルの読み込み

  2. ブラウザのサイズが変わっても、動画をセンターポジションに固定。

  3. ストリーミング再生
    要は、動画ファイルを全部読み込んでからの再生ではなく、データをロードしながらのストリーミング


で、どこで問題になったのかというと、#3のシームレスなストリーミング。
動画の専門ではないために、半日近い時間を要してしまった・・・我ながら恥ずかしい限りだ。

 

さてさて、まずは#1から解決していこうか。
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;

/*** Video ***/
var video:Video;
var connect_nc:NetConnection = new NetConnection();
connect_nc.connect(null);
var stream_ns:NetStream = new NetStream(connect_nc);
stream_ns.client = this;

function netStatusHandler(p_evt:NetStatusEvent):void {
if(p_evt.info.code == "NetStream.FileStructureInvalid") {
trace("The MP4's file structure is invalid.");
}
else if(p_evt.info.code == "NetStream.NoSupportedTrackFound") {
trace("The MP4 doesn't contain any supported tracks");
}
}

stream_ns.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);

video = new Video();
video.smoothing = true;

// set video size to browser size
video.width = 2240;
video.height = 1260;

addChild(video);
stream_ns.play("test.mp4");
video.attachNetStream(stream_ns);
//stream_ns.play("backcountry_bombshells_4min_HD_H264.mp4");

/*** / video ***/

/*** Content ***/
var mc_content = getChildByName("mc_content");
mc_content.y = (stage.stageHeight / 2);
addChild(mc_content);

/*** / Content ***/

/*** Common ***/

// change position to center
function positionHandler(e:Event):void {
// content
mc_content.y = (stage.stageHeight / 2);

// video
video.x = (video.stage.stageWidth / 2) - (video.width / 2);
video.y = (video.stage.stageHeight / 2) - (video.height / 2);
}
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.addEventListener(Event.RESIZE, positionHandler);
stage.dispatchEvent(new Event(Event.RESIZE));

/*** / Common ***/

簡単に解説すると、

/*** Video ***/
/*** / Video ***/



で囲まれたコードで動画の設置と再生を行っている。
基本的には上記のコードをコピペしてくれば問題はないのだが、
// set video size to browser size
video.width = 2240;
video.height = 1260;

でビデオのサイズを固定している。
なので、ブラウザサイズが上記サイズより小さい場合は、上下左右のtrimされた様に切り取られる。

あと、
stream_ns.play("test.mp4");

で、動画ファイルの指定をしている。この場合、.swfファイルと同じ階層にtest.mp4という動画ファイルを設置している。

 

/*** Content ***/
/*** / Content ***/



で囲まれた部分は、動画以外のフラッシュ内のコンテンツの設置を行っている。
このコンテンツ部分をビデオ設置コードより上に持ってくると、コンテンツがビデオの下階層に設置されてしまい、見えなくなってしまう。
addChild();

が読まれた順に、配置される階層が決まるので、上に表示させたいコンテンツは、AS3の下に持ってくる必要があるとのこと。

 

さて、で「#2 ブラウザのサイズが変わっても、動画をセンターポジションに固定。」は、

/*** Common ***/
/*** / Common ***/



で囲まれたコードで行っている。
stage.addEventListener(Event.RESIZE, positionHandler);

が、ブラウザサイズが変更になったときにアクションをトリガーするメソッドだ。サイズが変更されると、positionHandler()が呼ばれる。
で、positionHandler()では、ビデオとコンテンツの配置を変更している。

 

さて、問題となったのは、「#3 ストリーミング再生」だ。

最初、顧客から貰ったmp4では一旦mp4データを全て読み込んでからでないと、ビデオが再生されなかった。
色々調べていると、Flash Playerにおける高解像度H.264ビデオおよびAACオーディオのサポートについての説明にて記されていた。
注:H.264ビデオファイルをプログレッシブダウンロードとして再生する場合に重要なのは、moov atomをファイルの先頭に配置することです。このように配置しないと、ファイル全体をダウンロードしてから再生を開始する必要があります。 moov atomは、ファイル全体のインデックス情報を保持しているファイルの一部です。 Adobe PremiereやAfter Effectsなどのツールでは、この情報はファイルの末尾に配置されてしまいますが、アドビは、CS3ビデオ作成ツールの将来のアップデートでこの問題 を修正するよう作業を進めています。 ただし、これはH.264ビデオファイルのストリーミングに関する問題ではないため、Flash Media Serverのユーザには影響ありません。

で、想定されるのは貰ったmp4のこの「moov atom」データがファイルの先頭にないのだろう・・・と。

で、やっぱりこの「moov atom」を先頭に持ってくることはできるのか・・・と色々海外サイトを調べていると、YAMBという無料ソフトが可能らしい。早速ダウンロードを実行。
対応言語も日本語があるので、安心かな。(今回は英語でインストール)

ダウンロードページへ: http://yamb.unite-video.com/download.html

インストール後、ソフトウェアを起動して、「Creation」の「Click to create an MP4 file with multiple audio, video, subtitle and chapters streams.」をクリック。



 

そうすると、ビデオ選択をする事ができるウィンドウになり、変換したいビデオを選択。

ウィンドウ下にある「Output」を変更して、書き出し先を変更しよう。変更しないと、オリジナルファイルを上書いてしまうので注意。

 

 

 

 

あとは「Next」をクリックすると処理が開始される。



 

で、変換されたファイルを.swfで読み込んでみると、無事にストリーミングされながらビデオ再生が直ぐに開始された。
これにて作業終了です。