Web画面経由でコマンドを操作する
Web画面経由でコマンドを操作してみました。
Node.jsでExpressを利用しています。
今回の実装時のポイントは以下の通りです。
Node.jsでコマンドを実行する
Node.jsの標準APIであるchild_process
を使用します。
以下のようにexec
メソッドでコマンドを実行することができます。
const { exec } = require('child_process'); exec('echo "The \\$HOME variable is $HOME"', (error, stdout, stderr) => { console.log(stdout); });
画面を描画する
画面の描画にはejsを使いました。
ejsファイルではありますが、内容はHTMLそのものです。
ejs.renderFile('./views/index.ejs', (err, str) => { if (err) { res.send(err.message); } res.send(str); });
感想
簡単なWebアプリケーションを作るのにExpressは楽だと思います。
今回の方法を使ってラズパイで作成した赤外線リモコンをWeb画面経由で操作しています。
参考情報
ラズパイの赤外線リモコンを高性能にした
以前に作成したラズパイの赤外線リモコンを高性能なものにするために改良しました。
遠距離でも赤外線が届くようにするのと複数のリモコンに対応しました。
配線を変更
赤外線LEDを高出力なものに変更しました。
赤外線LEDを2つ付けて、広範囲に赤外線を出力するようにしました。
複数のリモコンに対応
リモコンの数だけ以下のコマンドで赤外線のデータを記録します。
irrecord -f -d /dev/lirc0 --driver default ~/lircd.conf
記録したlircd.conf
全てを/etc/lirc/lircd.conf.d/
に配置します。
/etc/lirc/lircd.conf
は以下の内容にします。
include "lircd.conf.d/*.conf"
これによって、/etc/lirc/lircd.conf.d/
にある全ての赤外線のデータが読み込まれます。
感想
LEDを変えたことで、2mくらい離れていても反応するようになり、便利になりました。
赤外線を広範囲にし、複数のリモコンの赤外線データを扱えるようにしたことで、複数の機器を操作できるようになりました。
参考情報
複数のリモコンに対応
LIRC - Linux Infrared Remote Control
Electronでデスクトップを録画するアプリが簡単に作れました
ElectronはAtomに使われていたり、VSCodeに使われていたりとPCネイティブなアプリを作るために最近よく使われているライブラリです。
今まで使ったことがなかったので使ってみました。今回作ったアプリのリポジトリはこちらです。
アプリ作成のポイントを紹介します。
題材
デスクトップのウィンドウやスクリーンを録画するアプリを作ります。
作り方
環境構築
Electronアプリを作るにあたってのテンプレートにはelectron-vueを使用します。
導入 · electron-vue
コマンド操作だけでElectron製のアプリを起動するところまで準備してくれます。
デスクトップの録画処理
Electronに用意されているAPIであるdesktopCapturerを使用すると、ウィンドウやスクリーンの動画を取得することができます。
desktopCapturer | Electron
// In the renderer process. const {desktopCapturer} = require('electron') desktopCapturer.getSources({types: ['window', 'screen']}, (error, sources) => { if (error) throw error for (let i = 0; i < sources.length; ++i) { if (sources[i].name === 'Electron') { navigator.mediaDevices.getUserMedia({ audio: false, video: { mandatory: { chromeMediaSource: 'desktop', chromeMediaSourceId: sources[i].id, minWidth: 1280, maxWidth: 1280, minHeight: 720, maxHeight: 720 } } }, handleStream) return } } }) function handleStream (stream) { document.querySelector('video').src = URL.createObjectURL(stream) }
desktopCapturer.getSources
でウィンドウやスクリーンを取得することができます。
navigator.mediaDevices.getUserMedia
のchromeMediaSourceId
に取得したsourceのidを指定することで各ウィンドウやスクリーンのStreamデータを取得することができます。
minWidth
、maxWidth
、minHeight
、maxHeight
を変更することで動画のサイズを変更することができます。
maxWidth
、maxHeight
に指定した値のサイズまでの動画になります。
動画の保存にはWeb標準APIのMediaStream Recording APIを使用します。
MediaStream Recording API - Web APIs | MDN
<a id="download">Download</a> <script> const downloadLink = document.getElementById('download'); var handleSuccess = function(stream) { const options = {mimeType: 'video/webm'}; const recordedChunks = []; const mediaRecorder = new MediaRecorder(stream, options); mediaRecorder.ondataavailable = (e) => { recordedChunks.push(e.data); }; mediaRecorder.onstop = (e) => { downloadLink.href = URL.createObjectURL(new Blob(recordedChunks)); downloadLink.download = 'video.webm'; }; mediaRecorder.start(); }; navigator.mediaDevices.getUserMedia({ audio: true, video: true }) .then(handleSuccess); </script>
navigator.mediaDevices.getUserMedia
で取得したStreamデータでMediaRecorder
のインスタンスを作成することで、Streamデータを動画として保存することができます。
工夫したところ
録画開始や録画停止の際にショートカットキーを使えるようにしました。
Electronでは、ショートカットキーの設定にいくつかのアプローチがあります。
Keyboard Shortcuts | Electron
今回は、Local ShortcutsとGlobal Shortcutsを使いました。
Local Shortcuts
アプリのメニューを作り、メニュー項目を実行するショートカットキーを設定する方法です。
まずはメニューを作る必要があります。
Menu | Electron
メニューを作る場合、通常はMain processというElectronアプリのエントリーポイントとなるプロセスでメニューを作成する必要があります。
今回はメニュー項目の設定変更を画面描画を担当するプロセスであるRender process上で行う必要があったため、Render processでメニューを作成しました。
Electronのremoteモジュールを使用することでRender processでもメニューを作成することができます。
// In the renderer process. import * as electron from 'electron' const {Menu} = electron.remote const template = [ { label: '画面', submenu: [ { label: '画面収録を開始', accelerator: 'CmdOrCtrl+P', click: function (menuItem, browserWindow, event) { browserWindow.webContents.send('startRecord') } } ] } ] const menu = Menu.buildFromTemplate(template) Menu.setApplicationMenu(menu)
メニューの作成は、buildFromTemplate
メソッドを使用すると簡単です。
メニューの仕様に準拠したJavaScriptオブジェクトを渡すことで、オブジェクトの値に応じたメニューを作成してくれます。
accelerator
プロパティでショートカットキーを設定することができます。
Accelerator | Electron
click
プロパティでメニュー項目が選択された時の動作を記述することができます。
引数のbrowserWindow
がRender processが動作するウィンドウなので、browserWindow.webContents
を介することで、Render processに処理を渡すことができます。
webContents | Electron
アプリのウィンドウがスクリーン上に存在しない場合、browserWindow
がnull
になるため注意が必要です。
今回のアプリでは、browserWindow
がnull
の場合、Main processからRender processに処理が流れるようにしています。
ElectronではIPCのAPIでプロセス間の通信を行うことが可能です。
ipcMain | Electron
Global Shortcuts
ショートカットキーのみを設定する方法です。アプリにフォーカスがなくても機能します。
Keyboard Shortcuts | Electron
// In the main process. import { BrowserWindow, globalShortcut } from 'electron' let mainWindow = new BrowserWindow({ height: 563, useContentSize: true, width: 1000 }) globalShortcut.register('CommandOrControl+E', () => { mainWindow.webContents.send('stopRecord') })
globalShortcut
でショートカットキーを設定することができます。
感想
Webの技術でPCネイティブなアプリを作ることができました。
Webの技術でネイティブなアプリというとモバイル向けのCordovaが思い浮かびます。
Cordovaは複雑というイメージだったので、Electronもそんな感じかなというイメージでした。
触ってみると、Electronはシンプルで分かりやすかったですし、electron-vueのファイル構成もそんな感じでした。
Electronを使うとメニューを作るといったネイティブな機能が簡単に実現できるのが驚きでした。
アプリを使って実際に録画した動画です。
youtu.be
参考
MediaStream Recording APIの使い方を参考にしました
Recording Video from the User | Web | Google Developers
アプリの画面デザインを参考にしました
デスクトップを録画するアプリを書いた - Qiita