Reputation: 1188
Im using the 'camera.dart' package to access the web cam. It works perfectly fine on the machine browser, yet the issue arise once it comes to the mobile. Even on android it works. But on iOS after asking the permission the camera stream is not loading. Any help would much appreciate to spot the part I'm missing. My code as follows in the Camera class.
String getRandString() {
var random = Random.secure();
var values = List<int>.generate(8, (i) => random.nextInt(255));
return base64UrlEncode(values);
}
Class implementation
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();
}
Upvotes: 3
Views: 1944
Reputation: 1530
following is the the demo app code from @danu's answer, with updates to work with null safety.
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();
},
),
],
),
),
],
),
);
}
}
Upvotes: 0
Reputation: 1188
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();
},
),
],
),
),
],
),
);
}
}
Upvotes: 2