簡體   English   中英

Web 相機插件在 flutter 中不起作用(僅在 iOS 中)

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

我使用“camera.dart”package 來訪問 web 凸輪。 它在機器瀏覽器上運行良好,但一旦涉及移動設備,問題就會出現。 即使在 android 上它也可以工作。 但是在 iOS 上詢問許可后,相機 stream 沒有加載。 任何幫助都將非常感謝您發現我缺少的部分。 我在相機 class 中的代碼如下。

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

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

 }

我有單獨的處置方法

@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();
 }

對於那些像我一樣被困住的人,這里有一個簡單的演示應用程序代碼,可以在任何瀏覽器任何設備上運行。

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();
                  },
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

以下是來自@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