我正在用Angular开发一个应用程序,根据设备的摄像头,以尽可能高的质量捕获照片。
目前,我有这个代码:
HTML:
<video #video id="video" autoplay muted playsinline></video>
角TS:
_requestCameraStream(width: number, height: number, secondTry: boolean) {
if (navigator.mediaDevices.getUserMedia)
{
navigator.mediaDevices
.getUserMedia({
video: {
facingMode: 'environment',
width: { ideal: width },
height: { ideal: height },
frameRate: { ideal: 30 },
},
})
.then(stream => {
console.log('_getUserMedia -> stream loaded');
this.loadStream(stream);
})
.catch(err => {
console.log(err);
if (!secondTry)
{
console.log('Started second try');
this._requestCameraStream(2560, 1440, true);
}
else
{
this.router.navigateByUrl('id-document/camera-error');
}
});
}
}
private loadStream(stream: MediaStream) {
const videoDevices = stream.getVideoTracks();
this.lastStream = stream;
this.video!.nativeElement.srcObject = stream;
this.video!.nativeElement.play();
this.ref.detectChanges();
}
基本上,我检查设备是否有可用的相机,并尝试用函数接收的宽度和高度值加载它。在第一次尝试中,我像下面这样调用函数:
this._requestCameraStream(4096, 2160, false);
如果流加载失败(可能是因为相机不支持4k质量),那么它会再次尝试使用值this._requestCameraStream(2560, 1440, true);
这实际上在大多数设备上运行得很好,但在Galaxy Note 10 Plus上,流无法加载,但如果我点击拍照按钮,相机确实可以捕捉到4k质量的图像。
我怀疑相机的分辨率比屏幕高,所以相机可以捕捉4k图像,但屏幕无法加载4k视频作为预览。问题是:系统没有触发我可以捕获的任何警告或错误。好像预览加载成功了。
如何检测和处理这个错误?或者,是否有其他方法可以让我要求相机在正确加载预览的情况下捕获最高质量的图像?
你可以尝试定义一个分辨率范围,而不是只尝试两个
async _requestCameraStream() {
if (!navigator.mediaDevices.getUserMedia) return;
try {
const stream = await navigator.mediaDevices
.getUserMedia({
video: {
facingMode: {
exact: "environment"
},
width: { min: 2288, ideal: 4096, max: 4096 },
height: { min: 1080, ideal: 2160, max: 2160 },
frameRate: { ideal: 30 },
},
});
if(stream) {
console.log('_getUserMedia -> stream loaded');
this.loadStream(stream);
}
}catch (err) {
console.log(err);
this.router.navigateByUrl('id-document/camera-error');
}
}
我认为你目前的方法是正确的,可以捕捉到最高质量的图像。我在我的一个项目中使用了类似的方法。我想问题出在视频回放上。在浏览器中有一个自动播放策略,它在不同的浏览器中表现不同。此浏览器策略不允许在没有任何用户干预的情况下播放视频内容。查看此URL, https://developer.chrome.com/blog/autoplay/
我认为你应该在视频元素中添加一个静音属性,如果你让用户在捕捉相机流之前点击会更好。也许这并不能解决你所面临的问题,但这个问题会在某些浏览器中存在,比如iPhone。苹果设备不允许任何视频内容,除非用户干预。
问候,尾身茂
<div class="row justify-content-center">
<video class="col-11 col-lg-8 sbordure" [class.show]="!isCaptured" [class.hide]="isCaptured" #video
id="video" [width]="640" autoplay></video>
<canvas class="col-11 col-lg-8 sbordure" [class.show]="isCaptured" [class.hide]="!isCaptured" #canvas
id="canvas" [width]="WIDTH" [height]="HEIGHT"></canvas>
</div>
<div class="row justify-content-center">
<button class="col-8 col-md-4 mt-3 photo-bouton" mat-raised-button
*ngIf="!isCaptured" color="primary" (click)="capture()">Prendre une photo</button>
<button class="col-8 col-md-4 mt-3 photo-bouton" mat-raised-button *ngIf="isCaptured" color="primary"
(click)="removeCurrent()">Prendre une autre photo</button>
</div>