non vorrei lavorare

ブログ名の通りです。javascript three.js mruby rust OCaml golang julialang blender

Atom Shellでデスクトップキャプチャー(動画)アプリ

おはようございます。もうすぐ次男が誕生日です。このところ、ご機嫌な時は「パパパパー」と 父親を認識したかのように話してくれることもあります。

はじめに

Gifzoでデスクトップを動画でキャプチャーすることに興味を覚えて、あれこれ調べていたら、Chromeで WebRTC関連のAPIでデスクトップキャプチャーできることを思い出して、ちょっとやってみました。

Chormeでデスクトップキャプチャー

制約事項

  • about://flagsでの設定が必要
  • httpsでアクセスしているページでしかキャプチャー機能は使えない

方針

これらの制約の為、Atom Shell使う意味が益々でてきました。

1. Atom Shellでのデスクトップキャプチャーは諦める

ちょっと試したが、そもそも、オレオレhttpsAtom Shellのレンダープロセスは上手くアクセスできない模様。

そこで、Chromeを外部プロセスとして起動して、これと連携する。

2. Atom Shell内でkoaをhttpsで動かし、動画ファイルを保存する。

ChromeではHTML5のFile APIは使えるものの、物理ファイルは保存できないので、 Atom Shellで動かしたkoaにファイルアップロードすることで、物理ファイルを作成する。

Atom Shellでkoaを動かすには

素のv0.11系でも--harmonyオプションが必要。

Atom Shellでnode.jsを--harmonyオプション付きで動かすには

Atom Shellでkoaを動かせた参照

Atom Shellでkoaをhttpsで動かすには

オレオレ証明書を作る

オレオレ証明書のkey.pem、cert.pemの2ファイルを用意する。

自分は昔書いたブログ記事を参考したw。

Windowsだとハマるかも

オレオレ証明書の作成をWindowsでやったら、BOM付で作られ、そのままだとエラーで怒られたので、BOMなしにして、ついでに改行コードもLFに変換したら動いた。

koaをhttpsで動かす

var https = require('https');
var options = {
key: fs.readFileSync(__dirname +"/key.pem"),
cert: fs.readFileSync(__dirname +"/cert.pem")
};
https.createServer(options, app.callback()).listen(4430);

Atom ShellからChromeを起動する

Chromeコマンドラインオプションを使用することで、

が可能となる。

OS毎にChromeの起動を対応

Atom ShellでOSを判定するには

process.platformを使ってみた。

Chromeをオプションを付けて起動する

var chromeRuntimes = {
win32:process.env.LOCALAPPDATA+"\\Google\\Chrome\\Application\\chrome.exe",
darwin:"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
linux:""//頑張ってください
};
var chromeRuntime=chromeRuntimes[process.platform];

var spawn = require('child_process').spawn;

spawn(chromeRuntime,
[
"--app=https://localhost:4430/webrtc.html", // シンプルなウィンドウでURLを開く
"--enable-usermedia-screen-capturing", // デスクトップキャプチャー機能を有効
"--ignore-certificate-errors", // オレオレ証明書の警告を無効
"--window-size='320,240'", // キャプチャーボタンに必要な小さ目のサイズを指定
'--user-data-dir=' + __dirname+"/chromeStuff" //
]);

注意点

Chomeがすでに起動済みの場合、コマンドライン引数が有効にならない模様

キャプチャー画像を動画にする

デスクトップキャプチャーはAPIで出来るが、保存するAPIは用意されておらず、自前で実装する必要がある。

RecordRTC.jsを使わせてもらった

今回はRecordRTC.jsを使わせてもらった。

キャプチャー開始

navigator.webkitGetUserMedia({
    audio: false,
    video: {
        mandatory: {
            chromeMediaSource: 'screen',
            minWidth: 1280,
            maxWidth: 2560,
            minHeight: 720,
            maxHeight: 1440
        }
    }
}, function (stream) {
    localStream = stream;
    window.recordRTC = RecordRTC(localStream, {
        type: "video",
        video: {
            width: 640,
            height: 480
        },
        canvas: {
            width: 640,
            height: 480
        }
    });
    recordRTC.startRecording();
}, function (error) {});

キャプチャー終了

recordRTC.stopRecording();

動画を物理ファイルに保存

Chrome側のWebアプリからkoaにファイルをアップロードすることで実現する。

var blob = recordRTC.getBlob();

var req = new XMLHttpRequest();

req.open("POST", "https://localhost:4430/", true);
req.onreadystatechange = function () {
    //readyState値は4で受信完了
    if (req.readyState == 4) {
        //コールバック
        //on_loaded(http);
        console.log("responseText" + req.responseText);
        var out = document.getElementById("out");
        out.innerHTML = "File Uploaded.!";
    }
};

var formData = new FormData();
formData.enctype = "multipart/form-data";
formData.append("theFile", blob, "capture.webm");
req.send(formData);

まとめ

Atom Shellで利用しているlibchromiumcontentがデスクトップキャプチャーに対応したら Atom Shellで完結できるのですが、デスクトップキャプチャーがChromeの機能拡張での実装に 一本化されそうな未来なので、期待薄です。

ChromeブラウザからのAtom ShellへのデータはWebSocket使った方が今風だったかも。

今回の作業を通して、

  • Atom Shellで内部のnode.jsの力を引き出す方法
  • koaをhttpsで動かす事
  • koaでのファイルアップロード
  • Chromeコマンドラインオプション
  • Chromeのabout://flagsによるデスクトップキャプチャーは廃止予定

等幅広く学ぶことが出来ました。

Link

関連記事