1. 개요 및 시스템 구조
이 구현의 핵심은 브라우저 내장 API인 MediaRecorder를 Stimulus 컨트롤러 내에서 체계적으로 관리하는 것입니다. 외부 서비스에 의존하지 않고 브라우저의 역량만으로 웹캠, 화면 공유, 그리고 이 둘을 결합한 혼합 모드를 지원합니다. Rails 백엔드와는 Active Storage를 통해 연결되며, 녹화가 완료된 영상은 즉시 서버로 전송되어 저장될 수 있는 구조를 가집니다.
2. Stimulus 컨트롤러 설계 및 상태 관리
recorder_controller.js는 녹화의 전 과정을 제어합니다. 주요 특징은 다음과 같습니다.
- Targets & Values:
preview(실시간 화면),video(녹화 후 재생),videoInput(파일 업로드용 input) 등을 타겟으로 지정하고,mode값을 통해 현재 녹화 상태(webcam, screen, pip)를 추적합니다. - 연결 및 해제:
connect()에서 초기 상태를 설정하고,disconnect()에서 활성화된 모든 미디어 트랙을 정지시켜 리소스 누수를 방지합니다. - 메서드 조직화: 인터페이스 역할을 하는 공개 메서드를 상단에 배치하고, 내부 로직을 담당하는 비공개 메서드(prefix
#)를 하단에 배치하여 코드의 가독성과 전문성을 높입니다.
3. 미디어 스트림 획득 및 녹화 로직
사용자가 선택한 모드에 따라 적절한 API를 호출합니다.
- Webcam:
navigator.mediaDevices.getUserMedia를 사용하여 비디오와 오디오 권한을 획득합니다. - Screen:
navigator.mediaDevices.getDisplayMedia를 통해 화면 공유 스트림을 가져옵니다. - MediaRecorder: 획득한 스트림을
MediaRecorder객체에 전달합니다.ondataavailable이벤트를 통해 전송되는 데이터 청크(chunks)를 배열에 수집하고, 녹화 중단 시 이를 하나의Blob으로 결합합니다.
4. Canvas를 활용한 Picture-in-Picture(PiP) 구현
가장 기술적으로 흥미로운 부분은 화면 공유와 웹캠을 동시에 녹화하는 PiP 모드입니다.
- 스트림 합성: 화면 공유 스트림과 웹캠 스트림을 각각 생성합니다.
- Canvas 드로잉: 숨겨진
canvas요소를 생성하고,requestAnimationFrame루프 내에서 화면 스트림을 배경으로, 웹캠 스트림을 우측 하단에 오버레이로 그립니다. - 스트림 추출:
canvas.captureStream(30)을 호출하여 초당 30프레임의 새로운 합성 스트림을 생성하고, 이를MediaRecorder에 전달하여 녹화합니다.
5. Active Storage와의 연동 및 저장
녹화가 완료된 후 서버에 저장하는 과정은 다음과 같은 단계를 거칩니다.
- Blob to File: 수집된 데이터를
video/webm타입의Blob으로 만들고, 이를 다시File객체로 변환합니다. - DataTransfer 활용: 보안상의 이유로 파일 input의 값을 직접 수정할 수 없으므로,
DataTransferAPI를 사용하여 생성된 파일을 input에 주입합니다. - Form 제출:
form.requestSubmit()을 호출하여 Rails 서버로 영상을 전송합니다. Rails의 Active Storage는 이를 일반적인 파일 업로드와 동일하게 처리합니다.