Skip to content

Commit 5ca7dc8

Browse files
authored
feat: 스트림 외에 오디오, 비디오 상태를 제공하는 훅 추가 (#294)
1 parent fece485 commit 5ca7dc8

File tree

2 files changed

+98
-0
lines changed

2 files changed

+98
-0
lines changed

client/src/hooks/useMeetingMediaStreams.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// DEPRECATED.
2+
// use 'useMeetingMediaStreamsV2' instead
3+
14
import { useEffect, useState } from 'react';
25
import { Socket } from 'socket.io-client';
36
import { STUN_SERVER } from 'src/constants/rtc';
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { useEffect, useState } from 'react';
2+
import { Socket, io } from 'socket.io-client';
3+
import { STUN_SERVER } from 'src/constants/rtc';
4+
import RTC from 'src/utils/rtc';
5+
import { setTrack, TrackKind } from 'src/utils/trackSetter';
6+
7+
export interface MeetingMediaStream {
8+
stream: MediaStream;
9+
id: string;
10+
type: 'local' | 'remote';
11+
audioOn: boolean;
12+
videoOn: boolean;
13+
}
14+
15+
export type SetLocalAudio = (audioOn: boolean) => void;
16+
export type SetLocalVideo = (videoOn: boolean) => void;
17+
18+
export function useMeetingMediaStreamsV2(
19+
socket: Socket,
20+
): [MeetingMediaStream[], SetLocalAudio, SetLocalVideo] {
21+
const [meetingMediaStreams, setMeetingMediaStreams] = useState<
22+
MeetingMediaStream[]
23+
>([]);
24+
const [localStream, setLocalStream] = useState<MediaStream>();
25+
26+
const initRTC = async () => {
27+
const userMediaConstraints = { video: true, audio: true };
28+
const userStream = await navigator.mediaDevices.getUserMedia(
29+
userMediaConstraints,
30+
);
31+
setLocalStream(userStream);
32+
33+
// note: local MeetingMediaStream has empty id
34+
const localMeetingMediaStream: MeetingMediaStream = {
35+
stream: userStream,
36+
id: '',
37+
type: 'local',
38+
audioOn: true,
39+
videoOn: true,
40+
};
41+
setMeetingMediaStreams((prev) => [...prev, localMeetingMediaStream]);
42+
43+
const rtc = new RTC(socket, STUN_SERVER, userStream);
44+
rtc.onMediaConnected((socketId, remoteStream) => {
45+
const remoteMeetingMediaStream: MeetingMediaStream = {
46+
stream: remoteStream,
47+
id: socketId,
48+
type: 'remote',
49+
audioOn: true,
50+
videoOn: true,
51+
};
52+
setMeetingMediaStreams((prev) => [...prev, remoteMeetingMediaStream]);
53+
});
54+
55+
rtc.onMediaDisconnected((socketId) => {
56+
setMeetingMediaStreams((prev) => prev.filter((_) => _.id !== socketId));
57+
});
58+
59+
rtc.connect();
60+
};
61+
62+
useEffect(() => {
63+
initRTC();
64+
}, []);
65+
66+
const setLocalAudio: SetLocalAudio = async (audioOn) => {
67+
if (!localStream) {
68+
return;
69+
}
70+
setTrack(localStream, 'audio', audioOn);
71+
socket.emit('audio_state_changed', audioOn);
72+
};
73+
74+
const setLocalVideo: SetLocalVideo = async (videoOn) => {
75+
if (!localStream) {
76+
return;
77+
}
78+
setTrack(localStream, 'video', videoOn);
79+
socket.emit('video_state_changed', videoOn);
80+
};
81+
82+
socket.on('audio_state_changed', (socketId, audioOn) => {
83+
setMeetingMediaStreams((prev) =>
84+
prev.map((_) => (_.id === socketId ? { ..._, audioOn } : _)),
85+
);
86+
});
87+
88+
socket.on('video_state_changed', (socketId, videoOn) => {
89+
setMeetingMediaStreams((prev) =>
90+
prev.map((_) => (_.id === socketId ? { ..._, videoOn } : _)),
91+
);
92+
});
93+
94+
return [meetingMediaStreams, setLocalAudio, setLocalVideo];
95+
}

0 commit comments

Comments
 (0)