简体   繁体   English

Web 相机插件在 flutter 中不起作用(仅在 iOS 中)

[英]Web Camera plugin not working in flutter ( only in iOS)

Im using the 'camera.dart' package to access the web cam.我使用“camera.dart”package 来访问 web 凸轮。 It works perfectly fine on the machine browser, yet the issue arise once it comes to the mobile.它在机器浏览器上运行良好,但一旦涉及移动设备,问题就会出现。 Even on android it works.即使在 android 上它也可以工作。 But on iOS after asking the permission the camera stream is not loading.但是在 iOS 上询问许可后,相机 stream 没有加载。 Any help would much appreciate to spot the part I'm missing.任何帮助都将非常感谢您发现我缺少的部分。 My code as follows in the Camera class.我在相机 class 中的代码如下。

String getRandString() {
  var random = Random.secure();
  var values = List<int>.generate(8, (i) =>  random.nextInt(255));
  return base64UrlEncode(values);
}

Class implementation Class 实现

 class _WebcamPageState extends State<WebcamPage> {
  // VideoElement
  late final VideoElement _webcamVideoElement;

  final String videoTag = getRandString();
@override
  void initState() {
  super.initState();

     // Create an video element which will be provided with stream source
     _webcamVideoElement = VideoElement();

    // Register an webcam
    ui.platformViewRegistry.registerViewFactory(
    videoTag, (int viewId) => _webcamVideoElement);
 
    loadCameraStream();

  }

 // I suppose the issue is here
  void loadCameraStream() { 

   var constraints = {
      "audio": false,
      "video": {
              'mandatory':
                  { 'minAspectRatio': 1.333, 'maxAspectRatio': 1.334 },
              'optional':
              [{ 'minFrameRate': 60 },
              { 'maxWidth': 400 }]
      }
  };
  window.navigator.mediaDevices?.getUserMedia(constraints).then((MediaStream stream) {
   _webcamVideoElement.srcObject = stream;
   _webcamVideoElement.play();
  });
  }


@override
  Widget build(BuildContext context) =>
     Scaffold(
         body: SingleChildScrollView(
         child: Container(
                          height: 500.0,
                          child: HtmlElementView(key: UniqueKey(),
                          viewType:videoTag),
                        )
          )//SingleChildScrollView
      );//Scaffold

 }

I have my dispose method separately我有单独的处置方法

@override
  void dispose() {

   if (_webcamVideoElement.srcObject != null &&
    (_webcamVideoElement.srcObject!.active ?? false)) {
    _webcamVideoElement.pause();
    var tracks = _webcamVideoElement.srcObject?.getTracks();
    _webcamVideoElement.srcObject = null;

  tracks?.forEach((track) {
    track.stop();
  });
  }
   super.dispose();
 }

For those who are stuck as me, here a simple demo app code that works on any browser any device.对于那些像我一样被困住的人,这里有一个简单的演示应用程序代码,可以在任何浏览器任何设备上运行。

import 'package:flutter/material.dart';
import 'dart:html' as html;
import 'dart:ui' as ui;

void main() {
 runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
 Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Container(),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          await showDialog(
              context: context,
              builder: (BuildContext context) {
                return FractionallySizedBox(
                  heightFactor: 0.5,
                  widthFactor: 0.5,
                  child: WebCam(),
                );
              });
        },
        // tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

class WebCam extends StatefulWidget {
  @override
  _WebCamState createState() => _WebCamState();
}

class _WebCamState extends State<WebCam> {
  static html.VideoElement _webcamVideoElement = html.VideoElement();

  @override
  void initState() {
    super.initState();

  // Register a webcam
  // ignore: undefined_prefixed_name
    ui.platformViewRegistry.registerViewFactory('webcamVideoElement',
        (int viewId) {
      getMedia();
      return _webcamVideoElement;
    });
  }

  getMedia() {
    html.window.navigator.mediaDevices
        .getUserMedia({"video": true}).then((streamHandle) {
      _webcamVideoElement
        ..srcObject = streamHandle
        ..autoplay = true;
    }).catchError((onError) {
      print(onError);
    });
  }

  switchCameraOff() {
    if (_webcamVideoElement.srcObject != null &&
        _webcamVideoElement.srcObject.active) {
      var tracks = _webcamVideoElement.srcObject.getTracks();

      //stopping tracks and setting srcObject to null to switch camera off
      _webcamVideoElement.srcObject = null;

      tracks.forEach((track) {
        track.stop();
      });
    }
  }

  @override
  void dispose() {
    switchCameraOff();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          Container(
              child: new HtmlElementView(
            key: UniqueKey(),
            viewType: 'webcamVideoElement',
          )),
          Container(
            child: Column(
              children: [
                RaisedButton(
                  child: Text('Play/Pause'),
                  onPressed: () async {
                    if (_webcamVideoElement.paused) {
                      _webcamVideoElement.play();
                    } else {
                       _webcamVideoElement.pause();
                    }
                   },
                ),
                RaisedButton(
                  child: Text('Switch off'),
                  onPressed: () {
                    switchCameraOff();
                  },
                ),
                 RaisedButton(
                  child: Text('Switch on'),
                  onPressed: () {
                    if (_webcamVideoElement.srcObject == null) getMedia();
                  },
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

following is the the demo app code from @danu's answer, with updates to work with null safety.以下是来自@danu 答案的演示应用程序代码,其中包含与 null 安全性一起使用的更新。

import 'package:flutter/material.dart';
import 'dart:html' as html;
import 'dart:ui' as ui;

void main() {
 runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
 Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Container(),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          await showDialog(
              context: context,
              builder: (BuildContext context) {
                return FractionallySizedBox(
                  heightFactor: 0.5,
                  widthFactor: 0.5,
                  child: WebCam(),
                );
              });
        },
        // tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

class WebCam extends StatefulWidget {
  @override
  _WebCamState createState() => _WebCamState();
}

class _WebCamState extends State<WebCam> {
  static html.VideoElement _webcamVideoElement = html.VideoElement();

  @override
  void initState() {
    super.initState();

  // Register a webcam
  // ignore: undefined_prefixed_name
    ui.platformViewRegistry.registerViewFactory('webcamVideoElement',
        (int viewId) {
      getMedia();
      return _webcamVideoElement;
    });
  }

  getMedia() {
    html.window.navigator.mediaDevices!
        .getUserMedia({"video": true}).then((streamHandle) {
      _webcamVideoElement
        ..srcObject = streamHandle
        ..autoplay = true;
    }).catchError((onError) {
      print(onError);
    });
  }

  switchCameraOff() {
    if (_webcamVideoElement.srcObject != null &&
        _webcamVideoElement.srcObject!.active!) {
      var tracks = _webcamVideoElement.srcObject!.getTracks();

      //stopping tracks and setting srcObject to null to switch camera off
      _webcamVideoElement.srcObject = null;

      tracks.forEach((track) {
        track.stop();
      });
    }
  }

  @override
  void dispose() {
    switchCameraOff();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          Container(
              child: new HtmlElementView(
            key: UniqueKey(),
            viewType: 'webcamVideoElement',
          )),
          Container(
            child: Column(
              children: [
                RaisedButton(
                  child: const Text('Play/Pause'),
                  onPressed: () async {
                    if (_webcamVideoElement.paused) {
                      _webcamVideoElement.play();
                    } else {
                       _webcamVideoElement.pause();
                    }
                   },
                ),
                RaisedButton(
                  child: const Text('Switch off'),
                  onPressed: () {
                    switchCameraOff();
                  },
                ),
                 RaisedButton(
                  child: const Text('Switch on'),
                  onPressed: () {
                    if (_webcamVideoElement.srcObject == null) getMedia();
                  },
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM