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