유튜브 함께 보기
부관리자 이상이 고른 유튜브 영상을 채팅방의 모든 사람이 함께 보는 예제예요.
마지막 수정 2026년 10월 19일
부관리자 이상이 유튜브 주소를 넣으면 채팅방의 모든 사람에게 같은 영상이 떠요. 채널로 영상 아이디를 보내고 저장해 두므로 나중에 들어온 사람도 지금 영상을 봐요.
코드
아래 코드를 그대로 페이지에 넣으면 동작해요. 첫 줄은 uchat.js가 불러와지기 전에 이벤트를 걸어 두는 미리 등록 코드예요(비동기 로딩과 여러 채팅방).
<script>U=window.U=window.U||{},U.events=U.events||[],U.chat=function(n){return{on:function(e,t){U.events.push([n,e,t])},off:function(e){for(var t=U.events.length;t>0;)U.events[--t][0]==n&&U.events[t][1]==e&&U.events.splice(t,1)}}};</script>
<script async src="https://client.uchat.io/uchat.js"></script>
<u-chat room="my-room" style="display:inline-block;width:100%;max-width:400px;height:500px"></u-chat>
<script>
U.chat('my-room').on('after.create#youtube-demo', function (room) {
var ui = room.skin;
var channel = room.plugin.add('youtube-demo');
var removeOverlay = null;
function show(id) {
if (removeOverlay) removeOverlay();
removeOverlay = null;
if (!id) return;
removeOverlay = ui.mount.overlay({
id: 'youtube-demo.player',
layer: 'content-overlay',
scope: 'message-list',
mount: function (host) {
host.style.pointerEvents = 'none'; // 빈 곳은 아래 대화를 누를 수 있게
var frame = host.ownerDocument.createElement('iframe');
frame.src = 'https://www.youtube-nocookie.com/embed/' + id + '?autoplay=1';
frame.allow = 'autoplay; encrypted-media';
frame.style.cssText =
'position:absolute;top:8px;right:8px;width:320px;height:180px;border:0;pointer-events:auto';
host.appendChild(frame);
return function () {
frame.remove();
};
},
});
}
function videoId(text) {
var m =
/(?:youtu\.be\/|v=|embed\/|shorts\/)([A-Za-z0-9_-]{11})/.exec(text) ||
/^([A-Za-z0-9_-]{11})$/.exec(text);
return m ? m[1] : '';
}
// 받기: 부관리자 이상, 또는 서버(저장값·서버 API)가 보낸 것만
channel.onReceived(function (room, data) {
if (!data.user || data.user.auth < 2) return;
var id = String(data.data[0] || '');
if (id === '' || /^[A-Za-z0-9_-]{11}$/.test(id)) show(id);
});
ui.menu.add({
id: 'youtube-demo.open',
label: '유튜브',
condition: function (ctx) {
return ctx.room.my.auth >= 2;
},
onSelect: function () {
ui.dialog.prompt('유튜브', '영상 주소를 넣으세요. 비우면 닫습니다.').then(function (text) {
if (text === null) return; // 취소
text = text.trim();
var id = videoId(text);
if (text && !id) return ui.dialog.alert('유튜브', '올바른 유튜브 주소가 아닙니다.');
if (id) {
channel.save([id]); // 나중에 들어올 사람을 위해 저장
channel.send([id]); // 지금 있는 사람에게(나에게도 돌아온다)
} else {
channel.clear();
channel.send(['']);
}
});
},
});
});
// 입장하거나 권한이 바뀌면 버튼 표시 조건을 다시 계산한다
function refreshMenu(room) {
room.skin.menu.resolver.refresh();
}
U.chat('my-room').on('after.join#youtube-demo', refreshMenu);
U.chat('my-room').on('after.user.modi#youtube-demo', refreshMenu);
</script>
사용법
- 부관리자 이상에게 입력창 도구 모음에 유튜브 버튼이 보여요. 회원 연동을 쓰지 않는 채팅방이라면
/login 관리자비밀번호로 관리자가 되어 시험해 보세요. - 주소를 넣으면 대화 영역 오른쪽 위에 플레이어가 뜨고, 빈 값을 넣으면 모두에게서 닫혀요.
- 새로 들어온 사람에게는 저장된 값이 입장할 때 전달되어 같은 영상이 떠요.
동작 원리
| 단계 | 쓰는 API | 설명 |
|---|---|---|
| 버튼 | room.skin.menu.add |
condition으로 부관리자 이상에게만 보여요. 콜백은 동기 함수여야 해요 |
| 입력 | room.skin.dialog.prompt |
확인하면 넣은 글자, 취소하면 null을 돌려주는 Promise예요 |
| 전송 | channel.send, channel.save |
send는 지금 접속한 모두(나 포함)에게, save는 나중에 들어올 사람을 위해 저장해요 |
| 표시 | room.skin.mount.overlay |
대화 목록 위에 겹치는 영역을 붙이고, 돌려받은 함수로 떼요 |
저장된 값은 입장할 때 서버가 권한 4로 보내 주므로 받는 쪽 권한 검사를 통과해요. 각 API의 세부는 스킨 UI API와 채널 API와 한도를 보세요.
서버에서 틀기
서버 REST API로 같은 채널에 영상 아이디를 보내면 사이트 관리 화면 같은 곳에서도 틀 수 있어요. 서버가 보낸 데이터는 권한이 4라서 위 코드의 권한 검사를 통과해요.
curl -X POST https://api.uchat.io/v2/rooms/room_xxxxxxxxxxxxxxxx/events \
-H "Authorization: Bearer uchat_..." \
-H "Content-Type: application/json" \
-d '{"plugin":"youtube-demo","save":true,"data":["dQw4w9WgXcQ"]}'
"save": true로 보내면 채팅방에 저장돼서 나중에 들어온 사람도 같은 영상을 봐요. 채팅방에 아무도 없을 때 보내도 저장돼요. 닫으려면 "data":[""]를 저장해요. API 키는 관리 페이지 API 메뉴에서 발급해요.
짚어 볼 점
- 누구나 같은 채널로 데이터를 보낼 수 있어요. 받은 데이터는 보낸 사람의 권한(
data.user.auth)과 모양을 꼭 확인해요. - 겹치는 영역이 대화를 가리지 않도록 host는 클릭이 통과하게 하고, 플레이어에만
pointer-events:auto를 줘요. save는 부관리자 이상만 쓸 수 있어요. 무료 채팅방은 채널 하나에만 저장할 수 있어 다른 채널에 저장하면 기존 저장값이 지워져요.- 무료 채팅방은 채널 전송량에 한도가 있어요. 전체 전송은 접속자 수만큼 차감되며 넘으면 오류
428이 나요(채널 API와 한도).
봐도 잘 이해가 되지 않나요? 문의 게시판에 질문을 남겨 주세요.