Nagrywanie filmu wideo przez użytkownika

Wagi mat

Wiele przeglądarek ma teraz możliwość uzyskania dostępu do wejścia wideo i audio od użytkownika. Jednak w zależności od przeglądarki może on być w pełni dynamiczny lub wbudowany lub może zostać przekazany do innej aplikacji na urządzeniu użytkownika.

Zacznij od prostego i stopniowo

Najłatwiej jest poprosić użytkownika o udostępnienie nagranego wcześniej pliku. W tym celu utwórz prosty element wejściowego pliku i dodaj filtr accept, który wskaże, że akceptujemy tylko pliki wideo, oraz atrybut capture, który wskazuje, że chcemy uzyskać film bezpośrednio z kamery.

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

Ta metoda działa na wszystkich platformach. Na komputerze wyświetli się prośba o przesłanie pliku z systemu plików (atrybut capture zostanie zignorowany). W Safari na iOS otwiera się aplikacja kamery, dzięki czemu można nagrać film, a potem przesłać go z powrotem na stronę internetową. Na Androidzie użytkownik będzie mógł wybrać aplikację, w której chce nagrać film, zanim prześle go z powrotem na stronę internetową.

Wiele urządzeń mobilnych ma więcej niż jedną kamerę. Jeśli chcesz, możesz ustawić atrybut capture na user, jeśli chcesz, aby kamera była skierowana w stronę użytkownika, lub environment, jeśli kamera ma być skierowana na zewnątrz.

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

Pamiętaj, że to tylko wskazówka – jeśli przeglądarka nie obsługuje tej opcji lub nie jest dostępny żądany typ kamery, przeglądarka może wybrać inną.

Gdy użytkownik skończy nagrywać i wróci do witryny, trzeba będzie jakoś uchwycić dane pliku. Aby uzyskać szybki dostęp, dołącz zdarzenie onchange do elementu wejściowego, a potem odczytaj właściwość files obiektu zdarzenia.

<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>

Kiedy masz już dostęp do pliku, możesz z nim korzystać w dowolny sposób. Możesz na przykład:

  • Dołącz je bezpośrednio do elementu <video>, aby móc go odtworzyć
  • Pobierz aplikację na urządzenie użytkownika
  • Prześlij go na serwer, podłączając do: XMLHttpRequest
  • Rysuj ramki w obszarze roboczym i stosuj do nich filtry

Chociaż metoda uzyskiwania dostępu do danych wideo za pomocą elementów wejściowych jest wszechstronna, jest najmniej atrakcyjna. Chcemy mieć dostęp do aparatu i zapewnić użytkownikom dobre wrażenia bezpośrednio z poziomu strony.

Interaktywny dostęp do aparatu

Nowoczesne przeglądarki mogą mieć bezpośrednią linię do kamery, co pozwala nam tworzyć środowisko w pełni zintegrowane ze stroną internetową, a użytkownik nigdy nie opuszcza przeglądarki.

Uzyskaj dostęp do aparatu

Możemy uzyskać bezpośredni dostęp do kamery za pomocą interfejsu API w specyfikacji WebRTC o nazwie getUserMedia(). getUserMedia() poprosi użytkownika o dostęp do podłączonych mikrofonów i kamer.

Jeśli interfejs API się powiedzie, interfejs API zwróci obiekt Stream zawierający dane z kamery lub mikrofonu. Następnie możemy dołączyć go do elementu <video>, dołączyć do strumienia WebRTC lub zapisać go za pomocą interfejsu API MediaRecorder.

Aby pobrać dane z kamery, wystarczy, że ustawimy video: true w obiekcie ograniczeń, który jest przekazywany do interfejsu API getUserMedia().

<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>

Jeśli chcesz wybrać konkretną kamerę, musisz najpierw wyliczyć dostępne kamery.

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

Następnie możesz przekazać identyfikator urządzenia, którego chcesz używać podczas połączenia z firmą getUserMedia.

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

To nie jest zbyt przydatne. Możemy tylko odtworzyć dane filmu.

Dostęp do nieprzetworzonych danych z aparatu

Aby uzyskać dostęp do nieprzetworzonych danych wideo z kamery, możesz narysować każdą klatkę w elemencie <canvas> i bezpośrednio manipulować pikselami.

W przypadku kanwy 2D możesz użyć metody drawImage kontekstu, aby narysować w obszarze roboczym bieżącą ramkę elementu <video>.

context.drawImage(myVideoElement, 0, 0);

W przypadku kanwy WebGL możesz użyć elementu <video> jako źródła tekstury.

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

Pamiętaj, że w obu przypadkach zostanie użyta bieżąca klatka odtwarzanego filmu. Aby przetworzyć wiele klatek, trzeba za każdym razem ponownie narysować film w obszarze roboczym.

Więcej informacji na ten temat znajdziesz w artykule o stosowaniu efektów w czasie rzeczywistym do obrazów i filmów.

Zapisz dane z kamery

Najprostszym sposobem zapisania danych z aparatu jest użycie interfejsu API MediaRecorder.

Interfejs MediaRecorder API pobierze strumień utworzony przez użytkownika getUserMedia, a następnie będzie stopniowo zapisywać dane ze strumienia w preferowanym miejscu docelowym.

<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>

W naszym przypadku zapisujemy dane bezpośrednio w tablicy, którą możemy później przekształcić w tablicę Blob, której można używać do zapisywania na naszym serwerze WWW lub bezpośrednio w pamięci urządzenia użytkownika.

Poproś o pozwolenie na odpowiedzialne korzystanie z kamery

Jeśli użytkownik nie przyznał Twojej witrynie wcześniej dostępu do kamery, natychmiast po wywołaniu funkcji getUserMedia przeglądarka poprosi użytkownika o udzielenie dostępu do kamery.

Użytkownicy nienawidzą próśb o dostęp do zaawansowanych urządzeń na swoim komputerze, dlatego często je blokują lub zignorują, jeśli nie zrozumieją kontekstu, z którego pochodzi prośba. Sprawdzoną metodą jest proszenie o dostęp do aparatu tylko wtedy, gdy jest to konieczne. Gdy użytkownik udzieli dostępu, nie będzie on już pytany ponownie. Jeśli jednak odrzuci dostęp, nie będzie można go już uzyskać z prośbą o zgodę.

Użyj interfejsu IAM API, aby sprawdzić, czy masz już dostęp.

Interfejs getUserMedia API nie informuje Cię o tym, czy masz już dostęp do kamery. Pojawia się problem. Aby użytkownik miał ładny interfejs, aby dał Ci dostęp do kamery, musisz poprosić o dostęp do kamery.

W niektórych przeglądarkach można rozwiązać ten problem przy użyciu interfejsu Permission API. Interfejs navigator.permission API pozwala wysyłać zapytania o stan możliwości dostępu do konkretnych interfejsów API bez konieczności ponownego wysyłania zapytań.

Aby przesłać zapytanie o dostęp do kamery użytkownika, przekaż do metody zapytania parametr {name: 'camera'}, który zwróci:

  • granted – użytkownik przyznał Ci dostęp do aparatu;
  • prompt – użytkownik nie udzielił Ci dostępu i zostanie poproszony, gdy zadzwonisz pod numer getUserMedia;
  • denied – system lub użytkownik wyraźnie zablokował dostęp do aparatu i nie będziesz mieć do niego dostępu.

Możesz też szybko sprawdzić, czy trzeba zmienić interfejs użytkownika, aby dostosować go do działań, które musi on wykonać.

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 () {};
});

Prześlij opinię