availableCameras method
Completes with a list of available cameras.
This method returns an empty list when no cameras are available.
Implementation
@override
Future<List<CameraDescription>> availableCameras() async {
try {
final web.MediaDevices mediaDevices = window.navigator.mediaDevices;
final List<CameraDescription> cameras = <CameraDescription>[];
// Request video permissions only.
final web.MediaStream cameraStream =
await _cameraService.getMediaStreamForOptions(const CameraOptions());
// Release the camera stream used to request video permissions.
cameraStream
.getVideoTracks()
.toDart
.forEach((web.MediaStreamTrack videoTrack) => videoTrack.stop());
// Request available media devices.
final List<web.MediaDeviceInfo> devices =
(await mediaDevices.enumerateDevices().toDart).toDart;
// Filter video input devices.
final Iterable<web.MediaDeviceInfo> videoInputDevices = devices
.where(
(web.MediaDeviceInfo device) =>
device.kind == MediaDeviceKind.videoInput,
)
/// The device id property is currently not supported on Internet Explorer:
/// https://developer.mozilla.org/en-US/docs/Web/API/MediaDeviceInfo/deviceId#browser_compatibility
.where((web.MediaDeviceInfo device) => device.deviceId.isNotEmpty);
// Map video input devices to camera descriptions.
for (final web.MediaDeviceInfo videoInputDevice in videoInputDevices) {
// Get the video stream for the current video input device
// to later use for the available video tracks.
final web.MediaStream videoStream =
await _getVideoStreamForDevice(videoInputDevice.deviceId);
// Get all video tracks in the video stream
// to later extract the lens direction from the first track.
final List<web.MediaStreamTrack> videoTracks =
videoStream.getVideoTracks().toDart;
if (videoTracks.isNotEmpty) {
// Get the facing mode from the first available video track.
final String? facingMode =
_cameraService.getFacingModeForVideoTrack(videoTracks.first);
// Get the lens direction based on the facing mode.
// Fallback to the external lens direction
// if the facing mode is not available.
final CameraLensDirection lensDirection = facingMode != null
? _cameraService.mapFacingModeToLensDirection(facingMode)
: CameraLensDirection.external;
// Create a camera description.
//
// The name is a camera label which might be empty
// if no permissions to media devices have been granted.
//
// MediaDeviceInfo.label:
// https://developer.mozilla.org/en-US/docs/Web/API/MediaDeviceInfo/label
//
// Sensor orientation is currently not supported.
final CameraDescription camera = CameraDescription(
name: videoInputDevice.label,
lensDirection: lensDirection,
sensorOrientation: 0,
);
final CameraMetadata cameraMetadata = CameraMetadata(
deviceId: videoInputDevice.deviceId,
facingMode: facingMode,
);
cameras.add(camera);
camerasMetadata[camera] = cameraMetadata;
// Release the camera stream of the current video input device.
for (final web.MediaStreamTrack videoTrack in videoTracks) {
videoTrack.stop();
}
} else {
// Ignore as no video tracks exist in the current video input device.
continue;
}
}
return cameras;
} on web.DOMException catch (e) {
throw CameraException(e.name, e.message);
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
} on CameraWebException catch (e) {
_addCameraErrorEvent(e);
throw CameraException(e.code.toString(), e.description);
}
}