20240617 追記
Bartender 4 で案内されてはじめて知ったのだけれども、権限周りにおいて不具合があるよう。
tccutil reset Accessibility com.surteesstudios.Bartender; tccutil reset ScreenCapture com.surteesstudios.Bartender; tccutil reset Accessibility com.surteesstudios.Bartender-setapp; tccutil reset ScreenCapture com.surteesstudios.Bartender-setapp
↑
カメラとスクリーンキャプチャは異なるけれども、(スクリーンキャプチャの Electron アプリも権限で同様におかしかった)これが原因でおかしい可能性がある。
なので、tccutil で権限をリセットして試すのもひとつかもしれない。
Bartender 4 それ自体はこの案内の通りで正常に動作するようになった。
署名されているアプリでもこの辺は関係ないぽい。
20231204 追記
以下の方法では、macOS Sonoma バージョン 14.1 でうまくいかなかったです。
権限周りであるとは思うのだけれど・・・。
別のアプリで、同じように画面収録する権限もうまくいきませんでした。
systemPreferences | Electron
systemPreferences | Electron
アプリに署名したら多分いけると思います。
はじめに
Mac で動作する Electron アプリをビルドし、 xxx.app を実行したときにカメラにアクセスできずに困った。
結論、 Mac で動作するアプリはカメラアクセスの許可を取得すれば OK でした。
探せなかっただけかもしれないけれど、
英語でもこのことずばりで書いている Issue さくっとみつけられなかったのでメモ。
環境
- OS: macOS Big Sur 11.3.1
- Architecture: arm64
- Runtime: node.js v16.15.0 (anyenv + nodenv)
- Main Framework: Vue v3.2.13, Electron v13.0.0, vue-cli-plugin-electron-builder v2.1.1
カメラへのアクセス
Web Application では、 getUserMedia
でデバイスのカメラにアクセスしてストリームオブジェクトを取得、
これを video.srcObject
あたりにいれてやれば映像にアクセスできます。
MediaDevices.getUserMedia() - Web API | MDN
Electron で WebCam にアクセスするのはこれで OK です。
npm run electron:serve
で実行したところ問題なく動作しました。
問題
じゃーこれで署名なしビルドしてとりあえず実行しているみかと思い、
npm run electron:build
でビルドしたアプリを実行しました。
DOMException: Could not start video source
↑
こんなエラーが JS ランタイムに表示され、カメラの映像が表示されません。
調べてみると getUserMedia
で deviceId を指定するとき、以前の MediaStream が開放されていないのが原因とあってこれかなーと思いやってみるもダメ。
Androidで getUserMedia() したら NotReadableError: could not start video source - console.lealog();
こちらは、 Android WebView でのはなしかな。
解決方法
JavaScript や DOM まわりの単純な不具合じゃないなーと思ったので、 Mac の権限まわりかなと思う。
Electron でカメラやマイクへのアクセス権限どうやって取得するかのドキュメントがあった。
systemPreferences | Electron
めっちゃこれっぽい。
てことで、メインプロセス(レンダラープロセスじゃない)でこれを実行してみた。
実行するタイミングあってるかは微妙だけどとりあえず、、、
(Android や iOS アプリ一般でいえば、必要になる箇所で権限取得するのがよいかも?)
import {app, systemPreferences} from 'electron'
~~~
app.on('ready', async () => {
if (isDevelopment && !process.env.IS_TEST) {
// Install Vue Devtools
try {
await installExtension(VUEJS3_DEVTOOLS)
} catch (e) {
console.error('Vue Devtools failed to install:', e.toString())
}
}
await systemPreferences.askForMediaAccess('camera').then((e) => {
console.log('success media access', e)
}).catch((e) => {
console.log('failed media access', e)
})
createWindow()
})
↑
ready イベントでウィンドウ作成前に処理を await
でブロックしてやってみた。
ドキュメントにも記載ありますが、 systemPreferences.askForMediaAccess
を使用するには、 Info.plist に NSCameraUsageDescription
や NSMicrophoneUsageDescription
のプロパティが必要です。
これがないと権限取得 API コール時にアプリが(おそらく)クラッシュします。
iOS アプリでもこのへんは同様のやつですね。
なお、 systemPreferences.getMediaAccessStatus('camera')
で現在の権限チェックもできるので、カメラアクセスが必要な Mac Electron アプリはこれをつかって権限チェックするのが適切ですね。
おわり。