Flutter WebでWebカメラを使う


パソコンとWebカメラを使ったちょっとしたツールのアイディアが思い浮かびました。しかし普段Androidアプリを作っていて、WindowsネイティブやJavaScript + CSSを思い出すのが大変だと思ったので、Flutter WebでWebカメラを使うことにしました。

前準備

公式のこちらの記事を参考に環境構築とプロジェクト作成を行いました。

Flutterの世界の中にWebの世界を作る

今回はブラウザで動くJavaScriptのプログラミングをDartで行い、Webカメラへの接続(getUserMedia)とプレビュー表示(videoタグ)を行います。そのためにFlutterの世界の中にWebの世界を作ります。

まず、Webの世界を作りたい箇所にHtmlElementView を貼ります。viewType パラメータで名前を設定します。

main.dart
class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: HtmlElementView(viewType: 'videoView'),
    );
  }
}

Webプログラミングを行う

こちらの2つのライブラリをインポートします。

main.dart
import 'dart:ui' as ui;
import 'dart:html';

下記のように HtmlElementView の内容をWebプログラミングします。 ui.platformViewRegistry.registerViewFactory メソッドの第1引数は HtmlElementView を貼ったときに設定した名前と同じにします。そして第2引数で渡すブロックがWebの世界になります。ブラウザで動くJavaScriptをDartで書けます。

main.dart
ui.platformViewRegistry.registerViewFactory('videoView', (int viewId) {
  // このブロックはWebの世界
  // videoタグを作る
  final video = VideoElement();
  // ソースが設定されたら自動再生
  video.autoplay = true;
  // Webカメラへの接続を要求する
  window.navigator.getUserMedia(video: true).then((stream) {
    // Webカメラへの接続が成功
    video.srcObject = stream;
  });
  // HtmlElementViewの内容を返却する
  return video;
});

全体ソースコード

GitHubリポジトリに全体ソースコードがあります。
Webカメラが無かったり許可されていなかったりしたときのエラー処理も実装しています。

注意点

Android Studioのエラー表示

dart:ui ライブラリの platformViewRegistry 変数へのアクセスはAndroid Studioではエラーを表す赤い下線が表示されました。しかし、コマンドラインではビルドできます。

公式のgetUserMediaメソッドの解説について

公式のgetUserMediaメソッドの解説では取得したMediaStreamクラスのオブジェクトに対してこのような使い方を案内しています。

video.src = Url.createObjectUrlFromStream(stream);

しかしこのやりかたは実行時エラーになりました。

html_dart2js.dart:30757 Uncaught (in promise) TypeError: Failed to execute 'createObjectURL' on 'URL': No function was found that matched the signature provided.