Video des Nutzers aufzeichnen

Mat Scales

Viele Browser können jetzt auf die Video- und Audioeingabe des Nutzers zugreifen. Je nach Browser kann es sich jedoch um eine vollständig dynamische und Inline-Ansicht handeln oder die Funktion wird an eine andere App auf dem Gerät des Nutzers delegiert.

Am einfachsten ist es, den Nutzer nach einer vorab aufgezeichneten Datei zu fragen. Erstellen Sie dazu ein einfaches Dateieingabeelement und fügen Sie einen accept-Filter hinzu, der angibt, dass nur Videodateien zulässig sind, und ein capture-Attribut, das angibt, dass die Daten direkt von der Kamera abgerufen werden sollen.

<input type="file" accept="video/*" capture />

Diese Methode funktioniert auf allen Plattformen. Auf dem Computer wird der Nutzer aufgefordert, eine Datei aus dem Dateisystem hochzuladen (wobei das Attribut capture ignoriert wird). In Safari auf iOS wird die Kamera-App geöffnet, sodass Sie ein Video aufnehmen und dann zurück an die Webseite senden können. Auf Android-Geräten kann der Nutzer auswählen, mit welcher App er das Video aufnehmen möchte, bevor es an die Webseite gesendet wird.

Viele Mobilgeräte haben mehrere Kameras. Wenn Sie eine Präferenz haben, können Sie das capture-Attribut auf user festlegen, wenn die Kamera auf den Nutzer gerichtet sein soll, oder auf environment, wenn die Kamera nach außen gerichtet sein soll.

<input type="file" accept="video/*" capture="user" />
<input type="file" accept="video/*" capture="environment" />

Hinweis: Dies ist nur ein Hinweis. Wenn der Browser die Option nicht unterstützt oder der von Ihnen angeforderte Kameratyp nicht verfügbar ist, wählt der Browser möglicherweise eine andere Kamera aus.

Sobald der Nutzer die Aufzeichnung beendet hat und sich wieder auf der Website befindet, müssen Sie die Dateidaten abrufen. Sie können schnell darauf zugreifen, indem Sie dem Eingabeelement ein onchange-Ereignis zuordnen und dann die files-Eigenschaft des Ereignisobjekts lesen.

<input type="file" accept="video/*" capture="camera" id="recorder" />
<video id="player" controls></video>
<script>
  var recorder = document.getElementById('recorder');
  var player = document.getElementById('player');

  recorder.addEventListener('change', function (e) {
    var file = e.target.files[0];
    // Do something with the video file.
    player.src = URL.createObjectURL(file);
  });
</script>

Sobald Sie Zugriff auf die Datei haben, können Sie alles tun, was Sie möchten. Beispielsweise können Sie…

  • Sie können sie direkt an ein <video>-Element anhängen, damit sie abgespielt werden kann.
  • Sie laden sie auf das Gerät des Nutzers herunter.
  • Laden Sie ihn auf einen Server hoch, indem Sie ihn an XMLHttpRequest anhängen.
  • Frames in ein Canvas zeichnen und Filter darauf anwenden

Die Methode, über ein Eingabeelement auf Videodaten zuzugreifen, ist zwar weit verbreitet, aber die am wenigsten attraktive Option. Wir möchten Zugriff auf die Kamera haben und direkt auf der Seite ein angenehmes Erlebnis bieten.

Interaktiv auf die Kamera zugreifen

Moderne Browser können eine direkte Linie zur Kamera haben, sodass wir Produkte entwickeln können, die vollständig in die Webseite integriert sind und der Nutzer den Browser niemals verlässt.

Zugriff auf die Kamera erhalten

Wir können direkt über eine API in der WebRTC-Spezifikation namens getUserMedia() auf die Kamera zugreifen. getUserMedia() fordert den Nutzer zum Zugriff auf seine verbundenen Mikrofone und Kameras auf.

Bei Erfolg gibt die API ein Stream zurück, das die Daten von der Kamera oder dem Mikrofon enthält. Wir können sie dann entweder an ein <video>-Element oder an einen WebRTC-Stream anhängen oder mit der MediaRecorder API speichern.

Um Daten von der Kamera abzurufen, legen wir einfach video: true im Objekt „constraints“ fest, das an die getUserMedia() API übergeben wird.

<video id="player" controls></video>
<script>
  var player = document.getElementById('player');

  var handleSuccess = function (stream) {
    player.srcObject = stream;
  };

  navigator.mediaDevices
    .getUserMedia({audio: true, video: true})
    .then(handleSuccess);
</script>

Wenn Sie eine bestimmte Kamera auswählen möchten, können Sie zuerst die verfügbaren Kameras auflisten.

navigator.mediaDevices.enumerateDevices().then((devices) => {
  devices = devices.filter((d) => d.kind === 'videoinput');
});

Du kannst dann die gewünschte deviceId übergeben, wenn du getUserMedia aufrufst.

navigator.mediaDevices.getUserMedia({
  audio: true,
  video: {
    deviceId: devices[0].deviceId,
  },
});

Das ist an sich nicht besonders nützlich. Wir können nur die Videodaten abrufen und wiedergeben.

Auf die Rohdaten der Kamera zugreifen

Wenn Sie auf die Rohvideodaten der Kamera zugreifen möchten, können Sie jeden Frame in ein <canvas> zeichnen und die Pixel direkt bearbeiten.

Bei einem 2D-Canvas können Sie die Methode drawImage des Kontexts verwenden, um den aktuellen Frame eines <video>-Elements in den Canvas zu zeichnen.

context.drawImage(myVideoElement, 0, 0);

Bei einem WebGL-Canvas können Sie ein <video>-Element als Quelle für eine Textur verwenden.

gl.texImage2D(
  gl.TEXTURE_2D,
  0,
  gl.RGBA,
  gl.RGBA,
  gl.UNSIGNED_BYTE,
  myVideoElement,
);

In beiden Fällen wird der aktuelle Frame eines abgespielten Videos verwendet. Wenn Sie mehrere Frames verarbeiten möchten, müssen Sie das Video jedes Mal neu auf dem Canvas zeichnen.

Weitere Informationen dazu finden Sie in unserem Artikel zum Anwenden von Echtzeiteffekten auf Bilder und Videos.

Daten von der Kamera speichern

Die Daten von der Kamera lassen sich am einfachsten mit der MediaRecorder API speichern.

Die MediaRecorder API nimmt den von getUserMedia erstellten Stream und speichert die Daten aus dem Stream dann progressiv in Ihrem bevorzugten Ziel.

<a id="download">Download</a>
<button id="stop">Stop</button>
<script>
  let shouldStop = false;
  let stopped = false;
  const downloadLink = document.getElementById('download');
  const stopButton = document.getElementById('stop');

  stopButton.addEventListener('click', function() {
    shouldStop = true;
  })

  var handleSuccess = function(stream) {
    const options = {mimeType: 'video/webm'};
    const recordedChunks = [];
    const mediaRecorder = new MediaRecorder(stream, options);

    mediaRecorder.addEventListener('dataavailable', function(e) {
      if (e.data.size > 0) {
        recordedChunks.push(e.data);
      }

      if(shouldStop === true && stopped === false) {
        mediaRecorder.stop();
        stopped = true;
      }
    });

    mediaRecorder.addEventListener('stop', function() {
      downloadLink.href = URL.createObjectURL(new Blob(recordedChunks));
      downloadLink.download = 'acetest.webm';
    });

    mediaRecorder.start();
  };

  navigator.mediaDevices.getUserMedia({ audio: true, video: true })
      .then(handleSuccess);
</script>

In unserem Fall speichern wir die Daten direkt in einem Array, das wir später in eine Blob umwandeln können, die dann auf unserem Webserver oder direkt im Speicher des Geräts des Nutzers gespeichert werden kann.

Erlaubnis zur verantwortungsvollen Nutzung der Kamera einholen

Wenn der Nutzer Ihrer Website noch nicht die Berechtigung zur Kameranutzung erteilt hat, wird er vom Browser aufgefordert, dies zu tun, sobald Sie getUserMedia aufrufen.

Nutzer mögen es nicht, wenn sie aufgefordert werden, auf leistungsstarke Geräte auf ihrem Computer zuzugreifen. Sie blockieren die Anfrage häufig oder ignorieren sie, wenn sie den Kontext der Aufforderung nicht verstehen. Es hat sich bewährt, den Zugriff auf die Kamera nur dann anzufragen, wenn sie zum ersten Mal benötigt wird. Sobald der Nutzer den Zugriff gewährt hat, wird er nicht noch einmal gefragt. Wenn er den Zugriff jedoch ablehnt, können Sie nicht noch einmal auf den Zugriff zugreifen, um den Nutzer um Erlaubnis zu bitten.

Mit der Berechtigungs-API prüfen, ob Sie bereits Zugriff haben

Die getUserMedia API gibt Ihnen keine Auskunft darüber, ob Sie bereits Zugriff auf die Kamera haben. Das stellt Sie vor ein Problem: Wenn Sie eine ansprechende Benutzeroberfläche bereitstellen möchten, damit Nutzer Ihnen Zugriff auf die Kamera gewähren, müssen Sie um Zugriff auf die Kamera bitten.

In einigen Browsern kann dieses Problem mithilfe der Permission API behoben werden. Mit der navigator.permission API können Sie den Status des Zugriffs auf bestimmte APIs abfragen, ohne dass Sie noch einmal aufgefordert werden müssen.

Wenn Sie prüfen möchten, ob Sie Zugriff auf die Kamera des Nutzers haben, können Sie {name: 'camera'} in die Abfragemethode übergeben. Es wird dann entweder Folgendes zurückgegeben:

  • granted: Der Nutzer hat dir zuvor Zugriff auf die Kamera gewährt
  • prompt: Der Nutzer hat dir keinen Zugriff gewährt und wird aufgefordert, wenn du getUserMedia aufrufst.
  • denied: Der Zugriff auf die Kamera wurde vom System oder vom Nutzer explizit blockiert und Sie können nicht darauf zugreifen.

Außerdem können Sie jetzt schnell prüfen, ob Sie Ihre Benutzeroberfläche an die Aktionen anpassen müssen, die der Nutzer ausführen muss.

navigator.permissions.query({name: 'camera'}).then(function (result) {
  if (result.state == 'granted') {
  } else if (result.state == 'prompt') {
  } else if (result.state == 'denied') {
  }
  result.onchange = function () {};
});

Feedback