Processingで動画を扱うことで、単に再生するだけでなく、再生速度や時刻、描画サイズなどを自由に操作できます。ユーザーの操作に合わせて自由に反応を作り込めるので、例えば体験型の展示作品なども手軽に作れるでしょう。
Processingで動画を扱うには、「さまざまな入力」の回でも扱った、公式のVideoライブラリの力を借りることになります。まだ準備できていない人は先にインストールしておきましょう。
ちなみに、ここで解説する機能については、ほとんど公式のリファレンスに書かれています1。適当に検索して掴んだ真偽不明の情報に振り回される前に、信頼できる情報源を参照する癖をつけておくとよいでしょう。
まずは動画再生の基本形をみていきましょう。
(→playback
)
スケッチの .pde
と同じ場所に data
ディレクトリを作成し、再生する動画ファイル(この例では sample.mp4
)を配置しておきましょう。
// 動画を扱うためのライブラリをインポート
import processing.video.*;
// 動画
Movie mv;
void setup() {
size(600, 600);
// 動画を読み込む
mv = new Movie(this, "sample.mp4");
// 再生を開始
mv.play();
}
void draw() {
// フレーム読み込みの準備ができていない場合、何もしない
if (mv.available() == false) {
return;
}
// フレームを読み込む
mv.read();
background(0);
// 動画を描く(動画は画像 PImage と同じように扱える)
image(mv, 0, 0);
}
「さまざまな入力」の回でカメラの映像を利用しましたが、 available()
で状態をチェックするなどの基本構造がよく似ていますね。
カメラの映像と同じく、 image()
で動画を描いているのがポイントです。これはつまり、通常の画像 PImage
と同じように扱えるということで、「画像」の回で学んだ知識が活きてきます。例えば描くときの大きさを変えたければ、 image()
のパラメーターを5つ指定すればOKです。
// 例:動画のフレームを幅600、高さ400で描く
image(mv, 0, 0, 600, 400);
動画周りの処理はやや複雑で、フォーマットによってはエラーが出てしまったり、ファイルサイズや画素数によっては重すぎてまともに動かなかったりします。コードは正しいのにうまく実行できない場合は、異なるフォーマットに変換してみたり、サイズを落としてみたりするとよいでしょう。
一時停止には pause()
を使います。先ほどのスケッチを、クリックしたら停止するように改良してみましょう。
// 一時停止
mv.pause();
さらに発展形として、 isPlaying()
を使うと現在再生中かどうかを取得できるので、うまく組み合わせれば再生・一時停止をトグルするように組むこともできます。
(→pause
)
再生速度の変更には speed()
を使います。何倍速にするかの指定は、パラメーターとして数値で指定します。この機能を利用して、マウスカーソルの位置に応じて再生速度を変更できるようにしてみましょう。
// 例:再生速度を1.5倍速に変更
mv.speed(1.5);
また、 play()
の代わりに loop()
を使うと、再生が終わったあとで自動的にループ再生してくれて便利です。ついでに組み込んでみましょう。
(→speed
)
さて、ここまで動画は1つのみでしたが、この数は自由に増やすことができます。ここまで学んだ知識を応用すればできるはずです。複数の動画を同時に再生するにはどうすればよいか、少し考えてみましょう。
(→dual
)
再生位置を変更するには jump()
を使います。これだけなら簡単なのですが、Processingの Movie
の操作体系はやや癖があり、処理速度に気を遣いながら調整するには少し工夫が必要になります。
(→seek
)
// 動画を扱うためのライブラリをインポート
import processing.video.*;
// 動画
Movie mv;
void setup() {
size(600, 600);
// 動画を読み込む
mv = new Movie(this, "sample.mp4");
// 再生を開始
mv.play();
}
void draw() {
// フレーム読み込みの準備ができていない場合、何もしない
if (mv.available() == false) {
return;
}
// フレームを読み込む
mv.read();
background(0);
// 動画を描く(動画は画像 PImage と同じように扱える)
image(mv, 0, 0);
// 描き終えたら一時停止
mv.pause();
}
void mouseMoved() {
// 処理が重くなるのを防ぐため、
// フレーム読み込み準備が完了している場合は書き終わるまで待つ
if (mv.available() == true) {
return;
}
// マウスカーソルの位置から再生時刻を計算
// mouseX: 0(左端) ... 0秒
// mouseX: width(右端) ... 動画の終了時刻
float t = map(mouseX, 0, width, 0, mv.duration());
// 時刻を変更して再生
mv.jump(t);
mv.play();
}
数値で再生位置が制御できることがわかりました。先の例ではシンプルにマウスカーソルに紐づけましたが、組み合わせかたは自由です。好きに組み合わせてみましょう。
例えば、以前扱った物理演算と組み合わせて、重力で落ちるボールの高さを再生時刻と同期させる…なんてことも可能なわけです。
(→gravity
)