Camera does not stop even after component is destroyed
Opened this issue · 5 comments
I am facing issue in angular v14. I have a component where in the ngx-webcam is used. I have hidden camera using css so that webcam is not visible on screen (video should not be visible to user as I am conducting there test). So when the user submits the test I am destroying the component and redirecting to other route. But the camera indicator does switch off.
component.html
<div class="hidden">
<webcam [height]="400" [width]="400" [trigger]="triggerObservable" (imageCapture)="handleImage($event)"
*ngIf="showWebcam" [allowCameraSwitch]="allowCameraSwitch" [switchCamera]="nextWebcamObservable" [imageQuality]="1"
(initError)="handleInitError($event)" mirrorImage="never">
</webcam>
</div>
component.css
.hidden {
display: none;
}
I have used showWebcam flag and when componet is destroyed I have toggled it to false so that ngx-webcam component is destroyed.
ngOnDestroy(): void {
this.showWebcam = false
}
I need to know if there is something wrong with the code or is there something that I am missing.
Thank you!
Hi @shaileshSwabhav I have the same issue, did you find a way to handle it?
Thank you!
Problem is the way the library is written, if you stop the component before it fully initialises (_video.play() is async and should be treated as a promise) it will continue to initialise after the close on destroy.
I get the feeling the library is not being maintained.
I had the same issue and believe I've come across a workaround.
Implement OnDestroy
, assign the WebcamComponent
and the video element to private properties, and in ngOnDestroy
, pause and stop the media stream.
In my limited testing, it seems to work. We only use this component on one single page, but if we were going to reuse it I'd probably wrap the WebcamComponent
in custom component to do this.
private _webcamComponent: WebcamComponent;
private _webcamVideoElement: HTMLVideoElement;
@ViewChild(WebcamComponent) set webcamComponent(webcamComponent: WebcamComponent) {
if (!webcamComponent && this._webcamComponent) {
this.disableWebcam(); // if the webcam is destroyed via ngIf or other means then disable it here as well.
}
this._webcamComponent = webcamComponent;
this._webcamVideoElement = webcamComponent?.nativeVideoElement?.nativeElement;
}
ngOnDestroy(): void {
this.disableWebcam();
}
private disableWebcam() {
if (this._webcamComponent) {
if (this._webcamVideoElement) {
this._webcamVideoElement.pause();
this._webcamVideoElement.srcObject = null;
}
// hack: mediaStream is private, but we need to manually destroy it because it isn't being handled by the component;
const mediaStream: MediaStream = (this._webcamComponent as any).mediaStream;
mediaStream?.getTracks().forEach(track => track.stop());
this._webcamComponent = null;
}
}
I suspect if your OnDestroy runs before the camera has completed initialising it will still be active after the OnDestroy completes, it's a race condition because the _video.play() should be treated as async by the library and notify you.
Thanks for the comment. It's probably not a robust workaround, but probably catches the majority of use cases. I'll update this thread if I have any obvious issues or updates to the workaround.