몇 년 동안 캡쳐를 하기 위해서 Flash나 Silverlight 같은 플러그인들을 사용할 수 밖에 없었다. HTML5의 등장으로 인해 위치정보 (GPS), Orientation API (가속도계), WebGL (GPU), Web Audio API (오디오 장비) 등 하드웨어 장치 접근에 대한 큰 파장을 가지고 왔다.
여기에서는 사용자의 카메라와 마이크를 웹앱에서 접근할 수 있게 해주는 새로운 API인 navigator.getUserMedia()를 소개한다.
getUserMedia()로 가는 길
지난 몇 년 동안 Media Capture APIs의 여러 변종들이 발달해왔고 많은 사람들이 웹에서 기본 하드웨어 장치에 접근해야 한다는 것을 깨달았지만, 그것은 새로운 사양에다 온갖 것을 다 집어 넣는 방향이 되어버렸다. 모든 것들이 지저분해져서 결국 W3C가 엄청난 양의 제안들을 통합하고 정리하는 워킹그룹을 만들기로 결정했다.
Round 1: HTML Media Capture
HTML Media Capture는 웹에서의 미디어 캡쳐 표준으로 <input type="file">를 오버로딩하여 accept에 새로운 값을 추가하는 것으로 진행되었다. <input type="file" accept="image/*;capture=camera">: 웹캠으로 캡쳐를 하려면, capture=camera을 설정하면 된다.
비디오 또는 오디오를 녹화하는 것도 비슷하다. <input type="file" accept="video/*;capture=camcorder"> <input type="file" accept="audio/*;capture=microphone">
하지만 이 특별한 API는 실시간 효과를 처리하기에는 부족했고 HTML Media Capture는 단지 미디어 파일을 녹화하거나 그 순간 사진을 찍는 것만 가능하다.
Round 2: device element
HTML Media Capture에 대한 많은 의견들은 너무 제한적이었다는 것이다. 그래서 (향후에 나올) 어떤 종류의 기기에서도 지원되는 새로운 스펙이 등장했고, getUserMedia()의 조상이 되는 <device> element라는 형태로 설계된다.
<script> var errorCallback = function(e) { console.log("Reeeejected!", e); };
// Not showing vendor prefixes. navigator.getUserMedia({ video: true, audio: true }, function(localMediaStream) { var video = document.querySelector("video"); video.src = window.URL.createObjectURL(localMediaStream);
// Note: onloadedmetadata doesn't fire in Chrome when using it with getUserMedia. // See crbug.com/110938. video.onloadedmetadata = function(e) { // Ready to go. Do some stuff. }; }, errorCallback ); </script>
여기에서 <video>요소에 src 속성을 설정하거나 <source> 요소들을 포함하고 있지 않는다. 미디어 파일의 비디오 URL을 삽입하는 대신에, 웹캠의 LocalMediaStream에서 얻은 Blob URL을 삽입한다.
미디어 제약조건 설정하기 (해상도, 높이, 너비)
getUserMedia()의 첫번째 인자는 얻게될 미디어 스트림에 대해 더 많은 요구사항들(또는 제약조건들)을 표시할 수 있다. 예를 들어, 기본적인 비디오 접근 대신에 다음과 같이 HD 화질의 스트림을 추가적으로 요청할 수 있다.
MediaStreamTrack.getSources(function(sourceInfos) { var audioSource = null; var videoSource = null;
for (var i = 0; i != sourceInfos.length; ++i) { var sourceInfo = sourceInfos[i]; if (sourceInfo.kind === 'audio') { console.log(sourceInfo.id, sourceInfo.label || 'microphone');
<videoautoplay></video> <imgsrc=""> <canvasstyle="display:none;"></canvas> <script> var video = document.querySelector('video'); var canvas = document.querySelector('canvas'); var ctx = canvas.getContext('2d'); var localMediaStream = null;
functionsnapshot() { if (localMediaStream) { ctx.drawImage(video, 0, 0); // "image/webp" works in Chrome. // Other browsers will fall back to image/png. document.querySelector('img').src = canvas.toDataURL('image/webp'); } }
// snapshot 찍기 이벤트리스너 추가 video.addEventListener('click', snapshot, false);
// Not showing vendor prefixes or code that works cross-browser. // 비디오 동작 navigator.getUserMedia({video: true}, function(stream) { video.src = window.URL.createObjectURL(stream); localMediaStream = stream; }, errorCallback); </script>
<script> var idx = 0; var filters = ['grayscale', 'sepia', 'blur', 'brightness', 'contrast', 'hue-rotate', 'hue-rotate2', 'hue-rotate3', 'saturate', 'invert', ''];
functionchangeFilter(e) { var el = e.target; el.className = ''; var effect = filters[idx++ % filters.length]; // loop through filters. if (effect) { el.classList.add(effect); } }