캔버스(canvas)를 활용하여 웹캠 정보를 재생하는 내용 입니다.
웹에서의 웹캡 비디오 스트림은 navigator 객체에서 useMedia 함수를 사용하면 가져올 수 있습니다.
navigator.mediaDevices.getUserMedia({ video: true })
이렇게 getUserMedia를 통하여 콜백으로 받은 스트림 객체는 비디오(vedio) 엘리먼트의 srcObject의 값으로 대입할 수 있습니다.
getUserMedia 함수가 프로미스(Promise) 형식으로 되어 있어 then 함수를 호출하여 만나볼 수 있습니다.
navigator.mediaDevices.getUserMedia({ video: true }).then( stream=>{
//비디오 스트림 : stream
})
여기까지 실행하고나면 웹캠의 영상이 비디오 테그에 표출되는 것을 볼 수 있습니다.
그런데 굳이 비디오 테그에 잘 나오는 동영상을 캔버스(canvas)에서 나오게 하려는 이유는 무엇 일까요?
우리는 핸드폰 앱에서 동영상 촬영시 얼굴을 꾸며주고 바꾸어주는 앱을 사용하거나 들어본적이 있습니다.
또한 배경을 바꾼다던지 동영상 안에 그림을 넣는다는지 등의 기능을 보고는 합니다.
이러한 앱의 기능을 만약 웹에서 구현한다면 그때 필요한 것이 바로 웹캠의 정보를 캔버스로 가져오는 것 입니다.
웹캠의 스트림을 video 테그에 전달해 주면 이제 캔버스(canvas)에서 사용 가능한 형태로 만들어지게 됩니다.
아래 코드를 살펴봅니다.
let video = document.getElementById('video') as HTMLVideoElement;
let canvas = document.getElementById('canvas') as HTMLCanvasElement;
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D ;
navigator.mediaDevices.getUserMedia({ video: true })
.then( (stream) => {
video.srcObject = stream //비디오 테그에 웹캠 스트림을 넣습니다.
video.play() //비디오 테그 실행
video.addEventListener('play', ()=>{
setInterval(()=>{
ctx.save();
ctx.drawImage(video, 0, 0, canvas.width, canvas.height); //putImage 함수
ctx.restore();
},1)
}, false);
})
.catch( (error)=>{
console.log(error);
});
웹캠을 통해서 가져온 객체는 video변수에 담겨있습니다.
이 변수 자체를 캔버스의 drawImage 함수를 통하여 그대로 대입하여 그려주면 웹캠의 동영상의 이미지 정보가 캔버스로 전달되게 되는데, 이때 setInterval 함수를 통하여 계속해서 그려주면 이미지가 계속해서 바뀌는 효과에 따라 마치 동영상이 재생되는 것 처럼 보이게 됩니다.
그렇다면 만약에 이러한 기능에 순서를 통하여 선을 그리고 점을 찍는 기능을 넣어주면 어떻게 될까요?
웹캠에서 가져온 이미지를 가장 처음 그려주고, 사용자가 하는 행위를 정의한 내용을 그려주면 동영상 위에 각종 그림을 그리는 효과를 만들 수 있게 됩니다.
let video = document.getElementById('video') as HTMLVideoElement;
let canvas = document.getElementById('canvas') as HTMLCanvasElement;
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D ;
if (navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({ video: true })
.then( (stream) => {
//마우스 움직임 정보를 담아두는 구간 입니다.
const moveArray : Array<any> = [];
canvas.addEventListener('mousemove', function (event) {
var x = event.clientX - canvas.offsetLeft;
var y = event.clientY - canvas.offsetTop;
moveArray.push({x, y});
});
//비디오에 스트림을 넣습니다.
video.srcObject = stream
video.play()
//동영상이 재생되면 인터벌함수를 통해 캔버스에 putImage를 해 줍니다.
video.addEventListener('play', ()=>{
setInterval(()=>{
//초기화
ctx.clearRect(0,0,canvas.width, canvas.height);
ctx.save();
ctx.beginPath();
ctx.strokeStyle = 'red';
ctx.lineWidth = 4;
//비디오 이미지 먼저 그려줍니다.
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
//4각형을 한번 그려 봅니다.
ctx.strokeRect(canvas.width/4, canvas.height/4,canvas.width/2, canvas.height/2);
ctx.stroke();
ctx.closePath();
ctx.restore();
//마우스가 움직인 정보값을 점 찍어 봅니다.
moveArray.forEach( (data : any )=> {
ctx.save();
ctx.beginPath();
ctx.arc(data.x, data.y, 10, (Math.PI / 180) * 0, (Math.PI / 180) * 360, false);
ctx.fillStyle = 'blue';
ctx.fill();
ctx.closePath();
ctx.restore();
});
},1)
}, false);
})
.catch( (error)=>{
console.log(error);
});
};
이러한 방식으로 동영상에 각종 효과를 주는 기능을 만들 수 있게 됩니다.
위 방식을 좀더 구체적이고 다양한 효과를 만날 수 있는 기능이 바로 Opencv.js 입니다.
영상처리의 대명사인 오픈CV를 자바스크립트에서도 사용 할 수 있습니다.
Opencv에 대한 공부가 어느정도 되고 나면 아마 위코드도 쉽게 접근 할 수 있지 않을 까 합니다. ^^;
위 내용에 사용된 샘플 코드는 아래 제 깃허브에서 받아볼 수 있습니다.
https://github.com/TaeSeungRyu/sample/tree/main/캔버스 비디오 플레이어
실제 동작하는 코드도 아래 제 깃허브에서 확인할 수 있습니다.
https://taeseungryu.github.io/sample/sampleView/canvasVideo/index.html
위 모든 내용이 웹(web)에서 동작하는 캔버스(canvas)로 이루어진 내용 입니다.
* 플래쉬, 액션스크립트, 유니티 같은 응용 프로그램이 아닙니다~
이상으로 HTML Canvas video webcam(캔버스 비디오 웹캠)에 대해서 살펴보았습니다.
문의사항이나 궁금한 점은 언제든 댓글 또는 메일로 연락주세요~ 👻
'Html 캔버스 > Html 캔버스 에니메이션' 카테고리의 다른 글
HTML Canvas Path2D(쉬운 이벤트제어를 위한 Path2D) (0) | 2022.04.22 |
---|---|
HTML Canvas 퍼즐(puzzle) (0) | 2022.03.30 |
HTML Canvas 사다리 타기(ladder, ghost leg, Amidakuji) (7) | 2022.02.22 |
HTML Canvas 복권 긁기 효과(scratch, lottery) (2) | 2022.02.16 |
HTML Canvas 색상 선택기(color picker) (0) | 2022.02.08 |
댓글