html5で videoの任意のフレームをcanvasに描画するメモ

デブサミ2010のhtml5セッションで見たデモ(Movement tracker*1 が、
衝撃的だったので video x canvas をちょっと勉強した。

1.videoの任意のフレームをそのままcanvasに描画させてみる

htmlのbodyに書くにはこれだけ。

<video id="v" src="video.ogv" autobuffer controls></video>
<canvas id="c"></canvas>
<input type="button" value="copy frame" onclick="copyFrame()" />


copy frameボタンで呼び出されるjavascriptはこんな感じ。

function copyFrame() {
    var cEle = document.getElementById('c');
    var cCtx = cEle.getContext('2d');
    var vEle = document.getElementById('v');

    cEle.width  = vEle.videoWidth;   // canvasの幅と高さを、動画の幅と高さに合わせる
    cEle.height = vEle.videoHeight;

    cCtx.drawImage(vEle, 0, 0);  // canvasに関数実行時の動画のフレームを描画
}

これで、動画再生させながらcopy frameボタンをポチポチすると、
そのタイミングのフレームが、canvasに描画される。


とっても簡単。

2.videoから取得したフレームの情報をいじってみる

単純なグレースケール化をしてみる。


htmlはそのまま。

javascriptにちょっとだけコードを追加。

function copyFrame() {
    var cEle = document.getElementById('c');
    var cCtx = cEle.getContext('2d');
    var vEle = document.getElementById('v');

    cEle.width  = vEle.videoWidth;
    cEle.height = vEle.videoHeight;

    cCtx.drawImage(vEle, 0, 0);

    // ここから下を追加
    var imgdata = cCtx.getImageData(0, 0, vEle.videoWidth, vEle.videoHeight);  // pixelデータを取得
    for (var i=0; i<imgdata.data.length; i+=4) {  // imgdata.data: [R,G,B,alpha,R,G,B,alpha...]
        var gray = (imgdata.data[i] + imgdata.data[i+1] + imgdata.data[i+2]) / 3;  // グレースケール値計算
        imgdata.data[i] = imgdata.data[i+1] = imgdata.data[i+2] = gray;  // RGB
        imgdata.data[i+3] = 255;  // alpha
    }
    cCtx.putImageData(imgdata, 0, 0);  // 描画
}

これでcanvasに描画されるフレームが、グレースケールに。


drawImage()せずに、直接videoからpixelデータを取得したかったけど、
それっぽいメソッドが見つからなかったorz


各メソッドなどの詳細は、Canvasリファレンス - HTML5.JP を参照。

*1:firefoxでしか動かない?