-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[NDD-87] Interview 페이지 camera 컴포넌트 기능 부여 (7h/8h) #30
Conversation
6c27fb9
to
313d4d0
Compare
Deploying with Cloudflare Pages
|
setSelectedMimeType(mimeTypes[0]); | ||
} | ||
}, []); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[p-1] 해당 로직은 필요가 없다고 생각합니다. selectedMineType 함수를 사용하고 있는데 이제 초기값을 받기 위해서 사용하는 로직이라면 state를 사용하지 않고 변수로 사용하는 방법으로 적용해도 똑같이 사용이 가능하다고 생각합니다.
const getSupportedMimeTypes = () => {
const types = [
'video/webm; codecs=vp8',
'video/webm; codecs=vp9',
'video/webm; codecs=h264',
'video/mp4; codecs=h264',
];
return types.filter((type) => MediaRecorder.isTypeSupported(type));
};
const selectedMimeType = getSupportedMimeTypes();
이런식으로요
useLayoutEffect는 랜더링 사이클에서 많은 비용을 소모하고 있어서 사용을 지양하는것이 좋으니 한번 확인해 보시고 수정하는건 어떤가요?
const handleStartRecording = () => { | ||
setRecordedBlobs([]); | ||
try { | ||
mediaRecorderRef.current = new MediaRecorder(stream as MediaStream, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/MediaRecorder
해당 코드에 오디오, 비디오 bitrate option을 설정해줄 수 있습니다.
v:3mbps, a: 128kbps
const option = {
audioBitsPerSecond: 128000,
videoBitsPerSecond: 3000000,
mimeType: "video/mp4",
}
new MediaRecorder(stream, options);
useEffect(() => { | ||
if (!stream) { | ||
void getMedia(); | ||
} | ||
|
||
return () => { | ||
if (stream) { | ||
stream.getTracks().forEach((track) => track.stop()); | ||
} | ||
}; | ||
}, [stream]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(구두로 이야기했지만 메모해둔 내용!)
useEffect의 return에 있는 로직이 컴포넌트가 언마운트 될 때만 실행되는 것이 아니라 종속성 배열에 있는 상태에 대한 사이클이 변경될 때 실행되는 것이라서 위 코드에서 stream이 변경될 때 마다 useEffect가 실행되는 사이클이 일어날 것이라고 생각했습니다.
하지만 현재 로직에서 stream은 두번의 변경이 일어나고, 이마저도 if문으로 막혀있어서 계속해서 실행되는 문제는 없을 것이라고 판단했습니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
web api는 너무 어려운것 같아요 ㅠㅠ 고생 많으셨습니다
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
제일 까다로운 작업 하시느냐고 고생하셨습니다!
web api에서 이렇게까지 많이 지원해주는지 몰랐네요
덕분에 많이 배워갑니다~
* [NDD-103] Member API E2E 테스트 (1h / 1h) (#29) * test: Member API E2E 테스트 코드 작성 1. /api/member GET API 에 대한 성공 테스트 2. /api/member GET API에서 유효하지 않은 토큰 사용으로 인한 실패 테스트 위의 2가지의 경우에 대한 테스트 코드 작성 * style: lint 적용 * test: 인수 테스트 코드 로직 변경 완료 GET /api/member에 대한 E2E 테스트 완료 * style: Window 개행문자 관련 에러 해결을 위한 lint 설정 추가 * feat: TestingModule을 생성하는 Util 메서드 구현 * [NDD-87] Interview 페이지 camera 컴포넌트 기능 부여 (7h/8h) (#30) * feat: InterviewCamera 내부 state 정의 * feat: 현재 브라우저에서 지원가능 한 MimeType을 명시 * feat: 현재 Media에 연결 기능 구현 * feat: 마운트시 바로 stream 연결 * feat: Record 시작함수 구현 * feat: record stop 함수 구현 * feat: Record Download 함수 구현 * feat: InterviewCamera 내부 state 정의 * feat: 현재 브라우저에서 지원가능 한 MimeType을 명시 * feat: 현재 Media에 연결 기능 구현 * feat: 마운트시 바로 stream 연결 * feat: Record 시작함수 구현 * feat: record stop 함수 구현 * feat: Record Download 함수 구현 * feat: InterviewCamera 내부 state 정의 * feat: 현재 브라우저에서 지원가능 한 MimeType을 명시 * feat: 현재 Media에 연결 기능 구현 * feat: 마운트시 바로 stream 연결 * feat: Record 시작함수 구현 * feat: record stop 함수 구현 * feat: Record Download 함수 구현 * feat: InterviewCamera 내부 state 정의 * feat: 현재 브라우저에서 지원가능 한 MimeType을 명시 * feat: 현재 Media에 연결 기능 구현 * feat: 마운트시 바로 stream 연결 * feat: Record 시작함수 구현 * feat: record stop 함수 구현 * feat: Record Download 함수 구현 * feat: InterviewCamera 내부 state 정의 * feat: 현재 브라우저에서 지원가능 한 MimeType을 명시 * feat: 현재 Media에 연결 기능 구현 * feat: 마운트시 바로 stream 연결 * feat: Record 시작함수 구현 * feat: record stop 함수 구현 * feat: Record Download 함수 구현 * feat: InterviewCamera 내부 state 정의 * feat: 현재 브라우저에서 지원가능 한 MimeType을 명시 * feat: 현재 Media에 연결 기능 구현 * feat: 마운트시 바로 stream 연결 * feat: Record 시작함수 구현 * feat: record stop 함수 구현 * feat: Record Download 함수 구현 * feat: InterviewCamera 내부 state 정의 * feat: 현재 브라우저에서 지원가능 한 MimeType을 명시 * feat: 현재 Media에 연결 기능 구현 * feat: 마운트시 바로 stream 연결 * feat: Record 시작함수 구현 * feat: record stop 함수 구현 * feat: Record Download 함수 구현 * feat: InterviewCamera 내부 state 정의 * feat: 현재 브라우저에서 지원가능 한 MimeType을 명시 * feat: 현재 Media에 연결 기능 구현 * feat: 마운트시 바로 stream 연결 * feat: Record 시작함수 구현 * feat: record stop 함수 구현 * feat: Record Download 함수 구현 * feat: video UI 기능 구현 * fix: log 문제 * fix: InterviewCamera 파일시스템 문제 해결 * chore: 상대경로 수정 * chore: CameraRef 이름 변경 --------- Co-authored-by: quiet-honey <99426344+quiet-honey@users.noreply.github.com>
Why
Interview 페이지를 작업하기 위해서 Interview 페이지의 Camera 최소 기능을 구현합니다.
Camera 기능에는 다음과 같은 기능을 최소 기능으로 선정합니다.
How
stream 요소 관리
현재 stream되는 요소를 state로서 관리합니다.
화면에서 바로 보이는 미디어에 대한 stream 을 관리할 수 있습니다.
해당 stream은 getMedia 함수의 useState를 통해서 관리됩니다.
recording 요소 관리
해당 컴포넌트 내부에서 "녹화" 상태를 확인합니다. 현재 컴포넌트의 가장 높은 상태에서 관리해야하며, 전역적으로 관리될 예정입니다.
recordedBlobs 요소 관리
녹화가 되는 요소를 관리할 state입니다.
startRecord를 통해서 관리됩니다.
selectedMimeType 요소 관리
현재 디바이스환경에서 사용할 수 있는 MimeType에 대해서 관리합니다.
getMedia 기능 (현재 컴포넌트에서 media 를 연결하는 기능)
Media를 셋팅할 수 있는 constraits에 대해서 명시합니다.
비동기로 미디어의 연결을 받습니다.
try-catch로 확인하여 현재 미디어 연결을 받습니다.
handleStartRecording (현재 녹화를 시작하는 기능)
녹화를 시작하는 기능입니다.
처음 녹화를 시작할때, RecordBlobs를 초기화합니다,
그 후 선언한 mediaRecordRef에 새롭게 초기화 하며, MediaRecorder(Web Api) 생성자를 선언합니다.
handleStopRecording (녹화 종료)
현재 녹화중인 mediaRecordRef에 대해서 정리합니다.
여기서 중요한 점은 gumVideoRef 현 시점에서 송출하고 있는 Media는 접근하지 않습니다.
handleDownload (현재 녹화된 결과를 저장 - 변경될 가능성이 있습니다.)
Media 타입을 선정
Result
recorded.2.webm
Reference
https://medium.com/watcha/%EC%9B%B9%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%97%90%EC%84%9C-%EB%8F%99%EC%9E%91%ED%95%98%EB%8A%94-%EB%85%B9%ED%99%94%EC%95%B1-%EB%A7%8C%EB%93%A4%EA%B8%B0-70142ce28994