はじめに
Gifzoでデスクトップを動画でキャプチャーすることに興味を覚えて、あれこれ調べていたら、Chromeで WebRTC関連のAPIでデスクトップキャプチャーできることを思い出して、ちょっとやってみました。
Chormeでデスクトップキャプチャー
制約事項
- about://flagsでの設定が必要
- httpsでアクセスしているページでしかキャプチャー機能は使えない
方針
これらの制約の為、Atom Shell使う意味が益々でてきました。
1. Atom Shellでのデスクトップキャプチャーは諦める
ちょっと試したが、そもそも、オレオレhttpsにAtom 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を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を起動する
- オレオレ証明書の警告を無効化
- デスクトップキャプチャー機能の有効化
が可能となる。
OS毎にChromeの起動を対応
Atom ShellでOSを判定するには
process.platformを使ってみた。
- win32
- darwin
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
- 今回の成果物(https://github.com/kjunichi/asDeskCap)
- node-chromeを一日いじくり回してわかったこと Chromeをnode.jsで起動する際に大いに参考になった。
関連記事
- デスクトップキャプチャーをChromeの機能拡張で実現
- gyazo-node-webkitを動かしてみた #OSX
- Atom Shellいじってたが、apmはビルドしないと行けなかった件 #windows