영상채팅 구현하기
영상채팅을 구현하려면 vChatCloud와 channel 객체를 준비해야 해요. 자세한 준비 과정은 시작하기를 참고해 주세요.
영상채팅 동작 흐름
VChatCloud에서 영상채팅이 어떻게 동작하는지 알아볼게요. 아래 그림을 보면 영상채팅이 진행되는 순서와 필요한 코드를 더 쉽게 이해할 수 있어요.
- 내가 영상채팅방에 입장해요.
vChatCloud.joinChannel({ roomId, clientKey, nickName }, callback)
함수나 예제코드의joinRoom(roomId, clientKey, nickName, callback)
함수를 사용해서 서버에 접속해요.
나의 입장 이벤트
가 발생해요.- 입장하기 (내 영상 추가 이벤트)가 발생하면서 비디오 태그와 스트림 설정 등의 로직을 작성하면 돼요.
- 나의
마이크, 카메라 ON/OFF 이벤트
가 발생해요.- 내 카메라 ON/OFF 이벤트, 내 마이크 ON/OFF 이벤트가 발생하면서 영상이 꺼졌을 때 대체 이미지 표시, 음소거 아이콘 표시 등의 로직을 작성하면 돼요.
- 다른 참여자가 채팅방에 입장해요.
참여자 입장 이벤트
가 발생해요.- 참여자 입장하기 (참여자 영상 추가 이벤트)가 발생하면서 참여자의 비디오 태그 생성과 스트림 설정 등의 로직을 작성하면 돼요.
- 참여자의
마이크, 카메라 ON/OFF 이벤트
가 발생해요.- 참여자 카메라 ON/OFF 이벤트, 참여자 마이크 ON/OFF 이벤트가 발생하면서 영상이 꺼졌을 때 대체 이미지 표시, 음소거 아이콘 표시 등의 로직을 작성하면 돼요.
- 참여자가 채팅방을 나가요.
참여자 나가기 이벤트
가 발생해요.- 참여자 나가기 (참여자 영상 제거 이벤트)가 발생하면서 나간 참여자의 비디오 태그 삭제 등의 로직을 작성하면 돼요.
- 내가 영상채팅방을 나가요.
vChatCloud.disconnect()
함수나 예제코드의exit(p)
함수를 사용해서 영상채팅방 연결을 종료해요.
- 나의
나가기 이벤트
가 발생해요.- 나가기 (내 영상 제거 이벤트)가 발생하면서 내 비디오 태그 삭제 등의 로직을 작성하면 돼요.
입장하기 (내 영상 추가 이벤트)
내가 영상채팅방에 처음 입장했을 때 발생하는 이벤트예요. 이 이벤트가 발생하면 내 영상을 화면에 보여주기 위해 미디어 스트림을 video
태그의 srcObject
에 설정해야 해요. 아래 예제 코드를 보면 내 비디오가 나올 video 태그를 만들고, 이벤트에서 받은 target(MediaStream) 값을 srcObject 속성에 설정했어요. 그 다음 video의 자동재생을 켜고 화면에 보이도록 video 태그를 삽입했어요. 동작을 확인하려면 아래 Run Pen을 클릭해 보세요. 실행한 후 코드를 수정하면 바로 결과를 확인할 수 있고, 다시 시작하려면 Rerun을 클릭하면 돼요.
코드내용 상세 보기
function videoInit() {
channel.on("rtcLocalStreamAppend", function (event) {
// 입장하기 이벤트 발생
myVideo = document.createElement("video"); // video 태그 생성
let stream = event.target; // event.target에 들어있는 미디어 스트림 정보 획득
myVideo.srcObject = stream; // video의 srcObject 속성에 미디어 스트림 정보 입력
myVideo.setAttribute("autoplay", true); // video에 자동재생 설정 (기본값이 멈춘 상태에서 시작함)
myCam.append(myVideo); // cam
});
}
let myCam;
window.addEventListener("load", function () {
...
// 닉네임 입력 후 등록 버튼 클릭했을 때
$('.login').submit(function (e) {
myCam = $(".my_cam");
...
joinRoom(
channelKey, // CMS에서 발급받은 키 값
clientKey, // 사용자의 고유 키 값
userNick, // 유저 닉네임
// 채널 생성 후 실행할 콜백 함수
function (err, history) {
if (err) {
openError(err.code, function () {
vChatCloud.disconnect(); // 오류 발생으로 인한 연결 종료
});
} else {
videoInit(); // videoInit(); 실행
}
}
);
});
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
WARNING
실행 후 종료 버튼을 클릭해서 연결을 끊지 않으면 페이지를 이동하거나 닫기 전까지 사용자의 카메라와 마이크가 공유될 수 있습니다.
아직 카메라와 마이크 제어 로직을 작성하지 않았기 때문에 카메라 끄기 버튼을 누르면 화면이 멈추고, 마이크 끄기 버튼을 눌러도 변화를 확인하기 어려워요. 이 부분은 내 카메라 ON/OFF 이벤트에서 자세히 다룰 예정이에요. 또한 현재는 종료 후 재접속하면 비디오 영역이 여러 개 생기는데, 이는 나가기 (내 영상 제거 이벤트)에서 해결할 예정이에요.
이벤트 발생 시 데이터
{
"type": "rtcLocalStreamAppend",
"target": {...},
"clientKey": "xxxxxxxx",
"client": {
"clientKey": "xxxxxxxx",
"nickName": "e7works",
"grade": "user"
}
}
2
3
4
5
6
7
8
9
10
- 이벤트 값
값 | 식별자 | 설명 |
---|---|---|
type | String | 발생한 이벤트 타입 |
target | MediaStream | 추가된 미디어 스트림 |
clientKey | String | 접속 단말 설정 고유키 (여러 참여자 중 1명을 특정하기 위해 필요함) |
client | Object | 접속 단말에 관한 정보 (clientKey , nickName , grade 에 관한 정보) |
나가기 (내 영상 제거 이벤트)
내가 영상채팅방에서 나갈 때 발생하는 이벤트예요. 나간 후에는 채팅방을 초기화하거나 다른 페이지로 이동하는 등의 로직을 작성하면 돼요. 아래 예제 코드에서는 채팅방을 초기화하고 다시 로그인 화면을 보여주도록 했어요. 동작을 확인하려면 아래 Run Pen을 클릭해 보세요.
코드내용 상세 보기
function videoInit() {
// 로컬 접속 종료 시
channel.on("rtcLocalStreamRemove", function (event) {
let html = $(".my_cam > video"); // 로컬 접속자를 표시하는 video태그를 감싸고 있는 태그
html.remove(); // 태그를 삭제한다(움직이지 않는 비디오 태그 삭제)
});
// 로컬 접속 시
channel.on("rtcLocalStreamAppend", function (event) {
myVideo = document.createElement("video");
let stream = event.target;
myVideo.srcObject = stream;
myVideo.setAttribute("autoplay", true);
myCam.append(myVideo);
channel.setRTCLocalMedia(myVideo);
});
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
WARNING
실행 후 종료 버튼을 클릭해서 연결을 끊지 않으면 페이지를 이동하거나 닫기 전까지 사용자의 카메라와 마이크가 공유될 수 있습니다.
이벤트 발생 시 데이터
{
"type": "rtcLocalStreamRemove",
"target": null,
"clientKey": "xxxxxxxxx",
"client": {
"clientKey": "xxxxxxxxx",
"nickName": "e7works",
"grade": "user"
}
}
2
3
4
5
6
7
8
9
10
- 이벤트 값
값 | 식별자 | 설명 |
---|---|---|
type | String | 발생한 이벤트 타입 |
target | MediaStream | 추가된 미디어 스트림 |
clientKey | String | 접속 단말 설정 고유키 (여러 참여자 중 1명을 특정하기 위해 필요함) |
client | Object | 접속 단말에 관한 정보 (clientKey , nickName , grade 에 관한 정보) |
참여자 입장하기 (참여자 영상 추가 이벤트)
다른 참여자가 영상채팅방에 입장했을 때 발생하는 이벤트예요. 이 순간부터 1:1 영상채팅이 아닌 다자간 영상채팅이 시작돼요.
주요 작업
- 새로 입장한 참여자의 영상을 화면에 표시하기 위해 video 태그 생성
- 이벤트에서 받은 미디어 스트림을 video 태그에 연결
- 참여자 닉네임과 함께 화면에 배치
예제에서는 참여자들의 비디오를 내 비디오 옆에 작은 크기로 나란히 보여주도록 구현했어요.
코드내용 상세 보기
function videoInit() {
// 리모트 유저 접속 이벤트
channel.on("rtcRemoteStreamAppend", function (event) {
let stream = event.target;
// 1. 참여자별 컨테이너 div 생성 (clientKey로 구분)
let html = $(`<div>`, {
name: event.clientKey, // 나중에 이 참여자를 찾기 위한 식별자
class: "remote_cam",
});
remoteCamList.append(html);
// 2. 참여자의 비디오 태그 생성 및 스트림 연결
let remoteVideo = document.createElement("video");
remoteVideo.srcObject = stream; // 참여자의 영상 스트림 연결
remoteVideo.setAttribute("autoplay", true); // 자동 재생 설정
$(html).append(remoteVideo);
// 3. 참여자 닉네임 표시
let userNick = $("<p>").text(event.client.nickName);
$(html).append(userNick);
// 4. 카메라/마이크 상태에 따른 UI 업데이트
$(".nocam").toggleClass("active", stream.getVideoTracks().length == 0);
$(".nomic").toggleClass("active", stream.getAudioTracks().length == 0);
// 5. VChatCloud에 참여자 미디어 등록
channel.setRTCRemoteMedia(remoteVideo, event.clientKey);
});
// 로컬 접속 종료 시
channel.on("rtcLocalStreamRemove", function (event) {
let html = $(".my_cam > video"); // 로컬 접속자를 표시하는 video태그를 감싸고 있는 태그
html.remove(); // 태그를 삭제한다(움직이지 않는 비디오 태그 삭제)
});
// 로컬 접속 시
channel.on("rtcLocalStreamAppend", function (event) {
myVideo = document.createElement("video");
let stream = event.target;
myVideo.srcObject = stream;
myVideo.setAttribute("autoplay", true);
myCam.append(myVideo);
channel.setRTCLocalMedia(myVideo);
});
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
WARNING
실행 후 종료 버튼을 클릭해서 연결을 끊지 않으면 페이지를 이동하거나 닫기 전까지 사용자의 카메라와 마이크가 공유될 수 있습니다.
현재 예제의 한계점
- 카메라/마이크 ON/OFF 기능이 아직 구현되지 않아 버튼이 제대로 동작하지 않아요
- 참여자가 나가도 화면에서 자동으로 사라지지 않아요
이런 문제들은 다음 섹션들에서 해결할 예정이에요
- 카메라/마이크 제어: 참여자 카메라 ON/OFF 이벤트
- 참여자 나가기 처리: 참여자 나가기
이벤트 발생 시 데이터
{
"client": undefined,
"type": "rtcRemoteStreamRemove",
"target": null,
"clientKey": "xxxxxxxx"
}
2
3
4
5
6
- 이벤트 값
값 | 식별자 | 설명 |
---|---|---|
client | undefined | - |
type | String | 발생한 이벤트 타입 |
target | null | - |
clientKey | String | 접속 단말 설정 고유키 (여러 참여자 중 1명을 특정하기 위해 필요함) |
내 카메라 ON/OFF 이벤트
내가 카메라를 켜거나 끌 때 발생하는 이벤트예요. 카메라를 끄면 검은 화면이 보이는 대신 대체 이미지를 표시해서 더 자연스러운 UI를 만들 수 있어요.
주요 작업
- 카메라 상태에 따라 video 태그 표시/숨김 처리
- 카메라가 꺼졌을 때 대체 이미지 표시
- 카메라 ON/OFF 버튼 상태 업데이트
동작을 확인하려면 아래 Run Pen
을 클릭해 보세요.
코드내용 상세 보기
function videoInit() {
// 로컬 유저 비디오 소스 변경 이벤트
channel.on("rtcLocalVideoChanged", function (event) {
let is_cam = event.enable; // 로컬 접속자의 카메라 상태 체크
$(".my_cam video").css("display", is_cam ? "" : "none"); // 로컬 접속자의 카메라가 비활성화이면 video태그 숨김
$(".my_cam .camera_off").css("display", !is_cam ? "block" : "none"); // 로컬 접속자의 카메라가 비활성화이면 대체 이미지 표시
// 카메라 on/off버튼 상태를 재설정한다.
$(".cam-footer .cam-btn .cam")
.toggleClass("btn_on", is_cam)
.toggleClass("btn_off", !is_cam);
// is_cam 상태에 따라 on_cam.png를 보여줄 지 off_cam.png를 보여줄 지 설정한다.
$(".cam-footer .cam-btn .cam img").attr(
"src",
is_cam
? "/img/webRTC/on_cam.png" // 카메라 on 아이콘 주소
: "/img/webRTC/off_cam.png" // 카메라 off 아이콘 주소
);
});
// 리모트 유저 접속 종료 이벤트
channel.on("rtcRemoteStreamRemove", function (event) {
let html = $(`.remote_cam_wrap div[name=${event.clientKey}]`); // 리모트 접속자를 표시하는 video태그를 감싸고 있는 태그
if (html.length) {
html.remove(); // 태그를 삭제한다 (비활성화)
}
});
// 리모트 유저 접속 이벤트
channel.on("rtcRemoteStreamAppend", function (event) {
let stream = event.target;
// 이벤트에서 받은 접속 단말 설정 고유키 데이터를 이용하여 새 div 생성
let html = $(`<div>`, {
name: event.clientKey,
class: "remote_cam",
});
remoteCamList.append(html); // 감싸고 있는 태그에 html소스를 삽입
let remoteVideo = document.createElement("video");
remoteVideo.srcObject = stream; // HTMLVideoElement에 미디어소스 설정
remoteVideo.setAttribute("autoplay", true); // 자동 재생
$(html).append(remoteVideo);
let userNick = $("<p>").text(event.client.nickName);
$(html).append(userNick); // 리모트 접속자의 닉네임 설정
$(".nocam").toggleClass("active", stream.getVideoTracks().length == 0); // 카메라의 상태에 따라 화면 변경
$(".nomic").toggleClass("active", stream.getAudioTracks().length == 0); // 마이크의 상태에 따라 화면 변경
channel.setRTCRemoteMedia(remoteVideo, event.clientKey); // 채널에 리모트 미디어 설정
});
// 로컬 접속 종료 시
channel.on("rtcLocalStreamRemove", function (event) {
let html = $(".my_cam"); // 로컬 접속자를 표시하는 video태그를 감싸고 있는 태그
html.html(""); // 태그를 삭제한다(움직이지 않는 비디오 태그 삭제)
});
// 로컬 접속 시
channel.on("rtcLocalStreamAppend", function (event) {
myVideo = document.createElement("video");
let stream = event.target;
myVideo.srcObject = stream;
myVideo.setAttribute("autoplay", true);
myCam.append(myVideo);
channel.setRTCLocalMedia(myVideo);
});
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
WARNING
실행 후 종료 버튼을 클릭해서 연결을 끊지 않으면 페이지를 이동하거나 닫기 전까지 사용자의 카메라와 마이크가 공유될 수 있습니다.
이벤트 발생 시 데이터
{
"type": "rtcLocalVideoChanged",
"target": {
"kind": "video", // video: 카메라, audio: 마이크
"enabled": true
},
"stream": MediaStream,
"clientKey": "my_client_123",
"enable": true // true: 카메라 켜짐, false: 카메라 꺼짐
}
2
3
4
5
6
7
8
9
10
파라미터
파라미터 | 타입 | 설명 |
---|---|---|
type | String | 발생한 이벤트 타입 (rtcLocalVideoChanged ) |
target | MediaStreamTrack | 변경된 미디어 트랙 (카메라는 video , 마이크는 audio ) |
stream | MediaStream | 내 전체 미디어 스트림 (영상+음성) |
clientKey | String | 내 고유 식별키 |
enable | Boolean | 카메라 상태 (true : 켜짐, false : 꺼짐) |
내 카메라 ON/OFF (로컬 미디어 비디오 켜기/끄기)
내 카메라를 ON/OFF하는 함수로 파라미터 값으로 true
나 false
를 입력 시, 보여지고 있는 카메라를 ON/OFF할 수 있습니다.
function cam_on_off(item) {
if (channel) {
var chk = $(item).attr("class");
var img = $(item).children("img")[0];
var video = $("div[name=my_cam]").children("div.camvideo")[0];
if (chk == "cam btn_on") {
// 카메라가 ON일 때
$(item).attr("class", "cam btn_off"); // 클래스를 btn_off로 바꾸고
$(img).attr("src", "img/webRTC/off_cam.png"); // OFF아이콘으로 바꾼다.
channel.toggleRTCVideoControl(false); // 카메라를 OFF한다.
} else {
$(item).attr("class", "cam btn_on"); // 클래스를 btn_on으로 바꾸고
$(img).attr("src", "img/webRTC/on_cam.png"); // ON아이콘으로 바꾼다.
channel.toggleRTCVideoControl(true); // 카메라를 ON한다.
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- 파라미터 값
파라미터 | 식별자 | 설명 |
---|---|---|
control | Boolean | 설정할 카메라 상태 (켜기: true , 끄기: false ) |
내 마이크 ON/OFF 이벤트
내가 마이크를 켜거나 끌 때 발생하는 이벤트예요. 마이크를 끄면 상대방에게 내 음성이 전달되지 않으니까, 마이크가 꺼진 상태라는 걸 시각적으로 표시해 주는 게 좋아요.
주요 작업
- 마이크 상태에 따라 음소거 아이콘 표시/숨김
- 마이크 ON/OFF 버튼 상태 업데이트
- 마이크가 꺼졌을 때 사용자에게 명확한 피드백 제공
동작을 확인하려면 아래 Run Pen
을 클릭해 보세요.
코드내용 상세 보기
function videoInit() {
// 로컬 마이크 상태 변경 이벤트
channel.on("rtcLocalAudioChanged", function (event) {
let is_mic = event.enable; // 마이크 켜짐/꺼짐 상태 확인
// 1. 마이크가 꺼졌을 때 음소거 아이콘 표시
$(".mic_off").css("display", !is_mic ? "block" : "none");
// 2. 마이크 ON/OFF 버튼 스타일 업데이트
$(".cam-footer .cam-btn .mic")
.toggleClass("btn_on", is_mic)
.toggleClass("btn_off", !is_mic);
// 3. 버튼 아이콘 변경
$(".cam-footer .cam-btn .mic img").attr(
"src",
is_mic
? "/img/webRTC/on_mic.png" // 마이크 켜짐 아이콘
: "/img/webRTC/off_mic.png" // 마이크 꺼짐 아이콘
);
});
// 로컬 유저 비디오 소스 변경 이벤트
channel.on("rtcLocalVideoChanged", function (event) {
let is_cam = event.enable; // 로컬 접속자의 카메라 상태 체크
$(".my_cam video").css("display", is_cam ? "" : "none"); // 로컬 접속자의 카메라가 비활성화이면 video태그 숨김
$(".my_cam .camera_off").css("display", !is_cam ? "block" : "none"); // 로컬 접속자의 카메라가 비활성화이면 대체 이미지 표시
// 카메라 on/off버튼 상태를 재설정한다.
$(".cam-footer .cam-btn .cam")
.toggleClass("btn_on", is_cam)
.toggleClass("btn_off", !is_cam);
// is_cam 상태에 따라 on_cam.png를 보여줄 지 off_cam.png를 보여줄 지 설정한다.
$(".cam-footer .cam-btn .cam img").attr(
"src",
is_cam
? "/img/webRTC/on_cam.png" // 카메라 on 아이콘 주소
: "/img/webRTC/off_cam.png" // 카메라 off 아이콘 주소
);
});
// 리모트 유저 접속 종료 이벤트
channel.on("rtcRemoteStreamRemove", function (event) {
let html = $(`.remote_cam_wrap div[name=${event.clientKey}]`); // 리모트 접속자를 표시하는 video태그를 감싸고 있는 태그
if (html.length) {
html.remove(); // 태그를 삭제한다 (비활성화)
}
});
// 리모트 유저 접속 이벤트
channel.on("rtcRemoteStreamAppend", function (event) {
let stream = event.target;
// 이벤트에서 받은 접속 단말 설정 고유키 데이터를 이용하여 새 div 생성
let html = $(`<div>`, {
name: event.clientKey,
class: "remote_cam",
});
remoteCamList.append(html); // 감싸고 있는 태그에 html소스를 삽입
let remoteVideo = document.createElement("video");
remoteVideo.srcObject = stream; // HTMLVideoElement에 미디어소스 설정
remoteVideo.setAttribute("autoplay", true); // 자동 재생
$(html).append(remoteVideo);
let userNick = $("<p>").text(event.client.nickName);
$(html).append(userNick); // 리모트 접속자의 닉네임 설정
$(".nocam").toggleClass("active", stream.getVideoTracks().length == 0); // 카메라의 상태에 따라 화면 변경
$(".nomic").toggleClass("active", stream.getAudioTracks().length == 0); // 마이크의 상태에 따라 화면 변경
channel.setRTCRemoteMedia(remoteVideo, event.clientKey); // 채널에 리모트 미디어 설정
});
// 로컬 접속 종료 시
channel.on("rtcLocalStreamRemove", function (event) {
let html = $(".my_cam"); // 로컬 접속자를 표시하는 video태그를 감싸고 있는 태그
html.html(""); // 태그를 삭제한다(움직이지 않는 비디오 태그 삭제)
});
// 로컬 접속 시
channel.on("rtcLocalStreamAppend", function (event) {
myVideo = document.createElement("video");
let stream = event.target;
myVideo.srcObject = stream;
myVideo.setAttribute("autoplay", true);
myCam.append(myVideo);
channel.setRTCLocalMedia(myVideo);
});
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
WARNING
실행 후 종료 버튼을 클릭해서 연결을 끊지 않으면 페이지를 이동하거나 닫기 전까지 사용자의 카메라와 마이크가 공유될 수 있습니다.
이벤트 발생 시 데이터
{
"type": "rtcLocalAudioChanged",
"target": {
"kind": "audio", // audio: 마이크, video: 카메라
...
},
"stream": MediaStream,
"clientKey": "my_client_123",
"enable": false // true: 마이크 켜짐, false: 마이크 꺼짐
}
2
3
4
5
6
7
8
9
10
파라미터
파라미터 | 타입 | 설명 |
---|---|---|
type | String | 발생한 이벤트 타입 (rtcLocalAudioChanged ) |
target | MediaStreamTrack | 변경된 미디어 트랙 (마이크는 audio , 카메라는 video ) |
stream | MediaStream | 내 전체 미디어 스트림 (영상+음성) |
clientKey | String | 내 고유 식별키 |
enable | Boolean | 마이크 상태 (true : 켜짐, false : 꺼짐) |
내 마이크 ON/OFF 제어하기
마이크를 켜거나 끄는 함수예요. true
나 false
값을 전달해서 마이크 상태를 제어할 수 있어요.
function mic_on_off(item) {
if (channel) {
var chk = $(item).attr("class");
var img = $(item).children("img")[0];
if (chk == "mic btn_on") {
// 마이크가 켜져있을 때 → 끄기
$(item).attr("class", "mic btn_off");
$(img).attr("src", "img/webRTC/off_mic.png");
channel.toggleRTCAudioControl(false); // 마이크 끄기
} else {
// 마이크가 꺼져있을 때 → 켜기
$(item).attr("class", "mic btn_on");
$(img).attr("src", "img/webRTC/on_mic.png");
channel.toggleRTCAudioControl(true); // 마이크 켜기
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
파라미터
파라미터 | 타입 | 설명 |
---|---|---|
control | Boolean | 설정할 마이크 상태 (켜기: true , 끄기: false ) |
참여자 카메라 ON/OFF 이벤트
다른 참여자가 카메라를 켜거나 끌 때 발생하는 이벤트예요. 참여자가 카메라를 끄면 검은 화면이나 멈춘 화면이 보이는 대신 대체 이미지를 표시해서 더 자연스러운 UI를 만들 수 있어요.
주요 작업
- 참여자 카메라 상태에 따라 video 태그 표시/숨김 처리
- 카메라가 꺼졌을 때 대체 이미지 표시
- 각 참여자별로 개별적으로 카메라 상태 관리
동작을 확인하려면 아래 Run Pen
을 클릭해 보세요.
코드내용 상세 보기
function videoInit() {
// 리모트 카메라 상태 변경 이벤트
channel.on("rtcRemoteVideoChanged", function (event) {
let is_cam = event.enable; // 참여자의 카메라 켜짐/꺼짐 상태 확인
let clientKey = event.clientKey; // 어떤 참여자인지 식별
// 1. 해당 참여자의 video 태그 표시/숨김
$(`.remote_cam[name=${clientKey}] video`).css(
"display",
is_cam ? "" : "none"
);
// 2. 카메라가 꺼졌을 때 대체 이미지 표시
$(`.remote_cam[name=${clientKey}] .camera_off`).css(
"display",
!is_cam ? "block" : "none"
);
});
// 로컬 마이크 상태 변경 이벤트
channel.on("rtcLocalAudioChanged", function (event) {
let is_mic = event.enable;
$(".mic_off").css("display", !is_mic ? "block" : "none");
$(".cam-footer .cam-btn .mic")
.toggleClass("btn_on", is_mic)
.toggleClass("btn_off", !is_mic);
$(".cam-footer .cam-btn .mic img").attr(
"src",
is_mic
? "/img/webRTC/on_mic.png" // 마이크 ON 이미지 주소
: "/img/webRTC/off_mic.png" // 마이크 OFF 이미지 주소
);
});
// 로컬 유저 비디오 소스 변경 이벤트
channel.on("rtcLocalVideoChanged", function (event) {
let is_cam = event.enable; // 로컬 접속자의 카메라 상태 체크
$(".my_cam video").css("display", is_cam ? "" : "none"); // 로컬 접속자의 카메라가 비활성화이면 video태그 숨김
$(".my_cam .camera_off").css("display", !is_cam ? "block" : "none"); // 로컬 접속자의 카메라가 비활성화이면 대체 이미지 표시
// 카메라 on/off버튼 상태를 재설정한다.
$(".cam-footer .cam-btn .cam")
.toggleClass("btn_on", is_cam)
.toggleClass("btn_off", !is_cam);
// is_cam 상태에 따라 on_cam.png를 보여줄 지 off_cam.png를 보여줄 지 설정한다.
$(".cam-footer .cam-btn .cam img").attr(
"src",
is_cam
? "/img/webRTC/on_cam.png" // 카메라 on 아이콘 주소
: "/img/webRTC/off_cam.png" // 카메라 off 아이콘 주소
);
});
// 리모트 유저 접속 종료 이벤트
channel.on("rtcRemoteStreamRemove", function (event) {
let html = $(`.remote_cam_wrap div[name=${event.clientKey}]`); // 리모트 접속자를 표시하는 video태그를 감싸고 있는 태그
if (html.length) {
html.remove(); // 태그를 삭제한다 (비활성화)
}
});
// 리모트 유저 접속 이벤트
channel.on("rtcRemoteStreamAppend", function (event) {
let stream = event.target;
// 이벤트에서 받은 접속 단말 설정 고유키 데이터를 이용하여 새 div 생성
let html = $(`<div>`, {
name: event.clientKey,
class: "remote_cam",
});
remoteCamList.append(html); // 감싸고 있는 태그에 html소스를 삽입
let remoteVideo = document.createElement("video");
remoteVideo.srcObject = stream; // HTMLVideoElement에 미디어소스 설정
remoteVideo.setAttribute("autoplay", true); // 자동 재생
$(html).append(remoteVideo);
let userNick = $("<p>").text(event.client.nickName);
$(html).append(userNick); // 리모트 접속자의 닉네임 설정
$(".nocam").toggleClass("active", stream.getVideoTracks().length == 0); // 카메라의 상태에 따라 화면 변경
$(".nomic").toggleClass("active", stream.getAudioTracks().length == 0); // 마이크의 상태에 따라 화면 변경
channel.setRTCRemoteMedia(remoteVideo, event.clientKey); // 채널에 리모트 미디어 설정
});
// 로컬 접속 종료 시
channel.on("rtcLocalStreamRemove", function (event) {
let html = $(".my_cam"); // 로컬 접속자를 표시하는 video태그를 감싸고 있는 태그
html.html(""); // 태그를 삭제한다(움직이지 않는 비디오 태그 삭제)
});
// 로컬 접속 시
channel.on("rtcLocalStreamAppend", function (event) {
myVideo = document.createElement("video");
let stream = event.target;
myVideo.srcObject = stream;
myVideo.setAttribute("autoplay", true);
myCam.append(myVideo);
channel.setRTCLocalMedia(myVideo);
});
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
WARNING
실행 후 종료 버튼을 클릭해서 연결을 끊지 않으면 페이지를 이동하거나 닫기 전까지 사용자의 카메라와 마이크가 공유될 수 있습니다.
이벤트 발생 시 데이터
{
"type": "rtcRemoteVideoChanged",
"target": {
"kind": "video", // video: 카메라, audio: 마이크
"enabled": true
},
"stream": MediaStream,
"clientKey": "participant_456",
"enable": true // true: 카메라 켜짐, false: 카메라 꺼짐
}
2
3
4
5
6
7
8
9
10
파라미터
파라미터 | 타입 | 설명 |
---|---|---|
type | String | 발생한 이벤트 타입 (rtcRemoteVideoChanged ) |
target | MediaStreamTrack | 변경된 미디어 트랙 (카메라는 video , 마이크는 audio ) |
stream | MediaStream | 해당 참여자의 전체 미디어 스트림 (영상+음성) |
clientKey | String | 참여자 고유 식별키 (어떤 참여자인지 구분하기 위해 필요) |
enable | Boolean | 카메라 상태 (true : 켜짐, false : 꺼짐) |
참여자 마이크 ON/OFF 이벤트
다른 참여자가 마이크를 켜거나 끌 때 발생하는 이벤트예요. 참여자가 마이크를 끄면 그 사람의 음성이 들리지 않으니까, 마이크가 꺼진 상태라는 걸 시각적으로 표시해 주는 게 좋아요.
주요 작업
- 참여자 마이크 상태에 따라 음소거 아이콘 표시/숨김
- 각 참여자별로 개별적으로 마이크 상태 관리
- 마이크가 꺼진 참여자를 쉽게 식별할 수 있도록 UI 제공
동작을 확인하려면 아래 Run Pen
을 클릭해 보세요.
코드내용 상세 보기
function videoInit() {
// 리모트 마이크 상태 변경 이벤트
channel.on("rtcRemoteAudioChanged", function (event) {
let is_mic = event.enable; // 참여자의 마이크 켜짐/꺼짐 상태 확인
let clientKey = event.clientKey; // 어떤 참여자인지 식별
// 해당 참여자의 음소거 아이콘 표시/숨김
$(`.remote_cam[name=${clientKey}] .mic_off`).css(
"display",
!is_mic ? "block" : "none"
);
});
// 리모트 카메라 상태 변경 이벤트
channel.on("rtcRemoteVideoChanged", function (event) {
let is_cam = event.enable; // 리모트 접속자의 카메라 상태 체크
$(`.remote_cam[name=${event.clientKey}] video`).css(
"display",
is_cam ? "" : "none"
); // 리모트 접속자의 카메라가 비활성화이면 video태그 숨김
$(`.remote_cam[name=${event.clientKey}] .camera_off`).css(
"display",
!is_cam ? "block" : "none"
); // 리모트 접속자의 카메라가 비활성화이면 대체 이미지 표시
});
// 로컬 마이크 상태 변경 이벤트
channel.on("rtcLocalAudioChanged", function (event) {
let is_mic = event.enable;
$(".mic_off").css("display", !is_mic ? "block" : "none");
$(".cam-footer .cam-btn .mic")
.toggleClass("btn_on", is_mic)
.toggleClass("btn_off", !is_mic);
$(".cam-footer .cam-btn .mic img").attr(
"src",
is_mic
? "/img/webRTC/on_mic.png" // 마이크 ON 이미지 주소
: "/img/webRTC/off_mic.png" // 마이크 OFF 이미지 주소
);
});
// 로컬 유저 비디오 소스 변경 이벤트
channel.on("rtcLocalVideoChanged", function (event) {
let is_cam = event.enable; // 로컬 접속자의 카메라 상태 체크
$(".my_cam video").css("display", is_cam ? "" : "none"); // 로컬 접속자의 카메라가 비활성화이면 video태그 숨김
$(".my_cam .camera_off").css("display", !is_cam ? "block" : "none"); // 로컬 접속자의 카메라가 비활성화이면 대체 이미지 표시
// 카메라 on/off버튼 상태를 재설정한다.
$(".cam-footer .cam-btn .cam")
.toggleClass("btn_on", is_cam)
.toggleClass("btn_off", !is_cam);
// is_cam 상태에 따라 on_cam.png를 보여줄 지 off_cam.png를 보여줄 지 설정한다.
$(".cam-footer .cam-btn .cam img").attr(
"src",
is_cam
? "/img/webRTC/on_cam.png" // 카메라 on 아이콘 주소
: "/img/webRTC/off_cam.png" // 카메라 off 아이콘 주소
);
});
// 리모트 유저 접속 종료 이벤트
channel.on("rtcRemoteStreamRemove", function (event) {
let html = $(`.remote_cam_wrap div[name=${event.clientKey}]`); // 리모트 접속자를 표시하는 video태그를 감싸고 있는 태그
if (html.length) {
html.remove(); // 태그를 삭제한다 (비활성화)
}
});
// 리모트 유저 접속 이벤트
channel.on("rtcRemoteStreamAppend", function (event) {
let stream = event.target;
// 이벤트에서 받은 접속 단말 설정 고유키 데이터를 이용하여 새 div 생성
let html = $(`<div>`, {
name: event.clientKey,
class: "remote_cam",
});
remoteCamList.append(html); // 감싸고 있는 태그에 html소스를 삽입
let remoteVideo = document.createElement("video");
remoteVideo.srcObject = stream; // HTMLVideoElement에 미디어소스 설정
remoteVideo.setAttribute("autoplay", true); // 자동 재생
$(html).append(remoteVideo);
let userNick = $("<p>").text(event.client.nickName);
$(html).append(userNick); // 리모트 접속자의 닉네임 설정
$(".nocam").toggleClass("active", stream.getVideoTracks().length == 0); // 카메라의 상태에 따라 화면 변경
$(".nomic").toggleClass("active", stream.getAudioTracks().length == 0); // 마이크의 상태에 따라 화면 변경
channel.setRTCRemoteMedia(remoteVideo, event.clientKey); // 채널에 리모트 미디어 설정
});
// 로컬 접속 종료 시
channel.on("rtcLocalStreamRemove", function (event) {
let html = $(".my_cam"); // 로컬 접속자를 표시하는 video태그를 감싸고 있는 태그
html.html(""); // 태그를 삭제한다(움직이지 않는 비디오 태그 삭제)
});
// 로컬 접속 시
channel.on("rtcLocalStreamAppend", function (event) {
myVideo = document.createElement("video");
let stream = event.target;
myVideo.srcObject = stream;
myVideo.setAttribute("autoplay", true);
myCam.append(myVideo);
channel.setRTCLocalMedia(myVideo);
});
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
WARNING
실행 후 종료 버튼을 클릭해서 연결을 끊지 않으면 페이지를 이동하거나 닫기 전까지 사용자의 카메라와 마이크가 공유될 수 있습니다.
이벤트 발생 시 데이터
{
"type": "rtcRemoteAudioChanged",
"target": {
"kind": "audio", // audio: 마이크, video: 카메라
...
},
"stream": MediaStream,
"clientKey": "participant_456",
"enable": false // true: 마이크 켜짐, false: 마이크 꺼짐
}
2
3
4
5
6
7
8
9
10
파라미터
파라미터 | 타입 | 설명 |
---|---|---|
type | String | 발생한 이벤트 타입 (rtcRemoteAudioChanged ) |
target | MediaStreamTrack | 변경된 미디어 트랙 (마이크는 audio , 카메라는 video ) |
stream | MediaStream | 해당 참여자의 전체 미디어 스트림 (영상+음성) |
clientKey | String | 참여자 고유 식별키 (어떤 참여자인지 구분하기 위해 필요) |
enable | Boolean | 마이크 상태 (true : 켜짐, false : 꺼짐) |
참여자 나가기 (리모트 접속 종료 이벤트)
다른 참여자가 영상채팅방에서 나갔을 때 발생하는 이벤트예요. 참여자가 나가면 그 사람의 화면을 자동으로 제거해서 깔끔한 UI를 유지할 수 있어요.
주요 작업
- 나간 참여자의 video 태그와 관련 UI 요소 제거
- 화면 레이아웃 재정렬
- 남은 참여자들의 영상채팅 계속 진행
코드내용 상세 보기
function videoInit() {
// 리모트 유저 접속 종료 이벤트
channel.on("rtcRemoteStreamRemove", function (event) {
let clientKey = event.clientKey; // 나간 참여자 식별
// 해당 참여자의 video 태그와 관련 요소들 찾기
let html = $(`.remote_cam_wrap div[name=${clientKey}]`);
if (html.length) {
html.remove(); // 화면에서 완전히 제거
}
});
}
2
3
4
5
6
7
8
9
10
11
12
13
이벤트 발생 시 데이터
{
"type": "rtcRemoteStreamRemove",
"target": null,
"clientKey": "participant_456",
"client": undefined
}
2
3
4
5
6
파라미터
파라미터 | 타입 | 설명 |
---|---|---|
type | String | 발생한 이벤트 타입 (rtcRemoteStreamRemove ) |
target | null | 미디어 스트림이 제거되어 null 값 |
clientKey | String | 나간 참여자의 고유 식별키 |
client | Object | 참여자 정보 (나가기 이벤트에서는 undefined일 수 있음) |