Basj
Basj

Reputation: 46183

Event triggered when the video stream is started, with getUserMedia

I'm using the ZXing JS barcode scanner library https://github.com/zxing-js/library/ with a video stream input (webcam or phone camera), as detailed in the following code.

In general, how to add an event listener to a <video> to do an action when a video stream has just started? (a video using the MediaDevices.getUserMedia video stream API, started from ZXing's decodeFromInputVideoDevice)?

const codeReader = new ZXing.BrowserQRCodeReader();

codeReader
  .decodeFromInputVideoDevice(undefined, 'video')  // uses the default input
  .then(result => console.log(result.text))  // this happens when the barcode is found / recognized
  .catch(err => console.error(err));
<script src="https://unpkg.com/@zxing/[email protected]/umd/index.min.js"></script>
<video id="video"></video>

Note: for now I'm using setTimeout(..., 2000) when the user has clicked on the button to start the video, but obviously this fails in the case there is a dialog box "Do you want to allow this website to use the camera device?", then 2 seconds is not enough. A listener on event "VideoHasJustStarted" would be better.

Edit:
Here is a jsFiddle showing the issue: not working with various events: started, devicechange.

Upvotes: 2

Views: 3604

Answers (1)

Oliver
Oliver

Reputation: 3138

There are a few ways to detect if a video is playing, or can be played, using event listeners:

let video = document.querySelector('video');

// Video has been started/unpaused
video.addEventListener('play', function() {
    ...
})

// Video has resumed play/started/unpaused/finished buffering/finished seeking, etc
video.addEventListener('playing', function() {
    ...
})

// Video can start playing (but might not be playing)
video.addEventListener('canplay', function() {
    ...
})

// Video can be played without buffering (but might not be playing)
video.addEventListener('canplaythrough', function() {
    ...
})

Most similar to VideoHasJustStarted is probably playing. But depending on how you want to execute your function, one of the above methods should fit your needs.

More info on video events: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Media_events

Example

// Get video
var video = document.querySelector('video');

// Add event listener to monitor events
video.addEventListener('playing', () => {
  console.log('Video is now streaming!')
});

// Add stream
navigator.mediaDevices.getUserMedia({
    video: true
  })
  .then(function(stream) {
    var videoTracks = stream.getVideoTracks();

    stream.onremovetrack = function() {
      console.log('Stream ended');
    };
    window.stream = stream;
    video.srcObject = stream;
  })
  .catch(function(error) {

    console.log(error);
  });
<video id="video" autoplay muted></video>

Tested on Firefox on laptop - permission is requested to use webcam and the console.log fires when the video starts. As StackOverflow blocks the above from running inline, link to working fiddle

Upvotes: 4

Related Questions