댄서블(춤을 연습하는 사람)이 춤을 추고 다음 구간 영상으로 넘어갈 때 POST요청을 보내는데, 댄서블이 춤을 춘 모습을 담기 위해서 react-wecam의 녹화할 필요가 있었습니다. 이를 구간 연습이 끝나거나, 한 번 더 연습하거나, 다음 구간으로 넘어가거나 여러 상황에 따라서 녹화를 시작하고 끝내야 하는 로직이 생각보다 복잡했습니다.
hook 사용은 옳은 방법이 아닐 수 있습니다. 녹화 로직만 참고하시길 바랍니다.
구현 과정
Navigator.mediaDevices는 읽기 전용 속성은 카메라, 마이크, 화면 공유와 같이 현재 연결된 미디어 입력 장치에 접근할 수 있는 MediaDevices 객체를 반환합니다. - mdn web docs
// 녹화 시작 함수
const startRecording = useCallback(() => {
const constraints = { video: true, audio: false };
console.log("💛 recording started");
navigator.mediaDevices
.getUserMedia(constraints)
.then((stream) => {
// 녹화 준비
const mediaRecorderInstance = new MediaRecorder(stream);
const chunks: Blob[] = [];
// 녹화 중일 때 실행
mediaRecorderInstance.addEventListener("dataavailable", (event) => {
if (event.data && event.data.size > 0) {
chunks.push(event.data); // chuck들을 이어붙여서 녹화
}
});
// 녹화가 끝났을 때 실행
mediaRecorderInstance.addEventListener("stop", () => {
const recordedBlob = new Blob(chunks, { type: "video/mp4" }); // Blob으로 생성
webcamCurrentRecord.current = recordedBlob; // MutableRefObject에 저장
});
// 녹화 시작
mediaRecorderInstance.start();
mediaRecorder.current = mediaRecorderInstance;
})
// 녹화 에러
.catch((error) => {
console.error("Error accessing webcam:", error);
});
}, [webcamCurrentRecord]);
MutableRefObject에 녹화 영상을 Blob으로 만들어서 할당했습니다.
// 녹화 종료 함수
const stopRecording = useCallback(async () => {
if (mediaRecorder.current && mediaRecorder.current.state !== "inactive") {
console.log("💛 recording ended");
mediaRecorder.current.stop();
}
}, []);
녹화 종료시 medaRecoder가 확실히 멈추도록 설정했습니다.
useEffect(() => {
if (isPlaying) startRecording();
if (isFinished) stopRecording();
}, [isPlaying, isFinished, startRecording, stopRecording]);
RTK에 isPlaying, isFinished를 만들어서 의존성 배열에 의해 트리거가 되도록 했습니다.
후기
navigator.mediaDevices를 통해 쉽게 웹캠 영상을 녹화할 수 있어서 놀랐습니다. 그리고 dataavailable 일 때마다 chuck를 이어붙이는 방식으로 녹화하는 것이 신기했습니다. 이제는 익숙해졌지만 Blob으로 만들어서 폼데이터로 요청을 보낼 수 있도록 하는 것은 익숙해졌습니다.
useCallback과 useEffect의 의존성 배열 설정이 옳은 선택이었는지는 다시 고민하게 되었습니다. useCallback은 함수 자체를 메모리에 저장해두는 것인데, 컴포넌트가 다시 마운트 될 때 녹화 시작에 대한 딜레이를 고려한다고 했으나, 큰 고민 없이 진행을 했었습니다.
Dancify v2를 만들어볼 생각인데 그때는 성능을 고려해서 hook을 제대로 사용해볼 예정입니다.
'Experience > - KT AIVLE School' 카테고리의 다른 글
KT AIVLE School 빅프로젝트 - SpeechRecognition (0) | 2023.07.20 |
---|---|
KT AIVLE School 빅프로젝트 - 텍스트 입력 Debounce 처리 (0) | 2023.07.20 |
KT AIVLE School 빅프로젝트 - shadcn/ui 사용 후기 (0) | 2023.07.20 |
KT AIVLE School 빅프로젝트 - 웹캠 영상 녹화 시 에러 경험 (0) | 2023.07.19 |
KT AIVLE School 빅프로젝트 - 프론트에서 S3의 GET요청을 대기하는 로직 (0) | 2023.07.19 |
KT AIVLE School 빅프로젝트 - 배포 과정 정리 (0) | 2023.07.19 |
댓글