Javascript Developer Guide - Video Conference

Omnitalk·2023년 5월 24일
0

안녕하세요 옴니톡입니다 :)

옴니톡은 간편하게 자사의 통신 서비스를 개발할 수 있도록 잘 갖추어진 SDK를 제공합니다. npm, cdn으로 간편하게 이용 가능 합니다. 아울러 매일 1시간 동안 무료로 사용 가능한 testkey도 발급해 드리고 있습니다.

오늘은 옴니톡 SDK를 이용해서 어떻게 영상회의실을 구현할 수 있는지 설명해 보고자 합니다. Javascript로 구현된 데모는 이곳에서 바로 체험해 볼 수 있습니다. 아래의 글에서 설명하는 예제에 대한 전체 소스 코드는 이곳에서 확인 가능합니다.

그럼 쉽고 간단하게 비디오 컨퍼런스를 구현하러 가보실까요?

*참고 *

아래의 글은 영상 컨퍼런스 기능 개발에 대한 레퍼런스를 제공하며, 4인이 참여하는 예제를 제공합니다. 옴니톡의 영상 컨퍼런스 최대 참여 인원은 서버의 물리적 인스턴스에 따라 Scale In/Out이 가능한 구조이며, 클라이언트가 동시에 시청 가능한 영상 최대 개수는 32개로 제한됩니다. 이는 클라이언트의 접속 환경(cpu, memory, network)을 고려한 최대 수치이며, 일반적인 경우 10개 내외로 동시 시청 범위를 제한할 것을 권장합니다. 전체적으로 코드를 작성한 후, 코드에 대한 설명을 진행합니다.

feature: html, vanila js

1. 전체 코드 작성

1-1.HTML 문서 작성하기

index.html 문서를 작성하고 Omnitalk SDK CDN 주소를 추가합니다.

https://cdn.jsdelivr.net/npm/omnitalk-js-sdk@latest/omnitalk.min.js

설명의 편의성을 위해 javascript 파일은 conference.js에 정의합니다. 로컬 영상(사용자 자신)을 출력하기 위해 'Omnitalk-LocalVideo-0' 값으로 video id를 설정하고, 상대방의 영상을 시청하기 위해 'Omnitalk-RemoteVideo-0'부터 'Omnitalk-RemoteVideo-2'번까지 video id를 설정합니다. video id 생성 규칙은 Api Reference를 참조하시기 바랍니다.

영상회의실을 만들 수 있는 버튼, 참여할 수 있는 버튼 및 종료 버튼을 추가합니다. 각각의 참여자의 화면을 보여줄 video 태그 역시 추가합니다.

예제 | index.html

<!DOCTYPE html>
<html>
  <head> 
    <meta charset="utf-8" />
    //omnitalk import
    <script src="https://cdn.jsdelivr.net/npm/omnitalk-js-sdk@latest/omnitalk.min.js"></script>
    <script src="video-conference/conference.js"></script>
    <style>
        video {
            max-width:35%;
            background:black;
        }
    </style>
  </head>
  <body>
    <input type="text" id="roomName" />
    <button type="button" id="regiBtn">영상 회의실 생성</Button>
    <input type="text" id="roomId" />
    <button type="button" id="joinBtn">회의실 참여</Button>
    <br>
    <br>
    <button type="button" id="leaveBtn">종료 click</Button>
    <div id=videoDisplay style="margin-top:15px;display:none;">
        <video id="Omnitalk-LocalVideo-0" autoplay playsinline></video>
        <video id="Omnitalk-RemoteVideo-0" autoplay playsinline></video>
        <video id="Omnitalk-RemoteVideo-1" autoplay playsinline></video>
        <video id="Omnitalk-RemoteVideo-2" autoplay playsinline></video>
    </div>
    <div id=log></div>
  </body>
</html>

1-2. js 문서 작성하기

전체 코드를 살펴보고 세부적인 기능을 설명합니다.

예제 | conference.js

'use strict'
 
window.onload = async function(){
 
    // pass argument(s)
    // service id for web
    // service id, service key for app
    const omnitalk = new Omnitalk("service_id","service_key");
    omnitalk.onmessage = async (evt) => {
        const log = document.querySelector("#log");
        switch (evt.cmd) {
            case "SESSION_EVENT":
                log.insertAdjacentHTML('beforeend', `<p>Session: ${evt.session}</p>`);
                break;
            case "BROADCASTING_EVENT":
                log.insertAdjacentHTML('beforeend', `<p>Join: ${evt.user_id}</p>`);
                omnitalk?.subscribe(evt["publish_idx"]);
                break;
            case "LEAVE_EVENT":
                log.insertAdjacentHTML('beforeend', `<p>Bye: ${evt.session}</p>`);
                break;
        }
    }
    
    // start session. create web socket
    const sessionId = await omnitalk.createSession();
 
    const regiBtn = document.querySelector("#regiBtn");
    const joinBtn = document.querySelector("#joinBtn");
 
    regiBtn.addEventListener("click", async function() {
        const roomName = document.getElementById('roomName').value;
        const roomObj = await omnitalk.createRoom("videoroom", roomName);
        const roomlist = await omnitalk.roomList("videoroom");
        log.insertAdjacentHTML('beforeend', `<p>Video RoomId: ${roomObj.room_id}</p>`);
 
        roomlist.map((item, index) => {
            log.insertAdjacentHTML('beforeend', `<p>Roomlist-${index}: ${item.subject}, ${item.room_id}</p>`);
        })
        regiBtn.disabled = true;
        document.getElementById("roomId").value = roomObj.room_id;
    });
 
    joinBtn.addEventListener("click", async function() {
        document.getElementById('videoDisplay').style.display = "block";
        const roomId = document.getElementById('roomId').value;
        const joinResult = await omnitalk.joinRoom(roomId);
        const partilist = await omnitalk.partiList(roomId);
        const publishResult = await omnitalk.publish("videocall", false);
 
        partilist.map((item, index) => {
            log.insertAdjacentHTML('beforeend', `<p>Participant-${index}: ${item.user_id}</p>`);
            omnitalk?.subscribe(item.publish_idx);
        })
    });
 
    leaveBtn.addEventListener('click', async function(){
        await omnitalk.leave(sessionId.session);
    });
}

2. 전체 코드 설명

2-0. 선행 작업: 서비스 키 발급

옴니톡의 통신 서비스를 사용하기 위해서는 서비스 키가 반드시 필요합니다. 회원가입이 승인된 후 발급 받거나, 1시간동안 사용가능한 임시 테스트키를 발급받아 주세요. 임시 테스트키 발급은 https://omnitalk.io/demo/video 에서 진행할 수 있습니다.

2-1. 옴니톡 객체 생성과 이벤트 메시지

옴니톡 SDK는 통신 서비스를 제공하기 위해 Offer-Answer 구조로 설계되어 있으며, 이를 위해 반드시 async, await 구조를 지원하여야 합니다. 옴니톡객체가 정상적으로 생성되고 세션이 초기화 되면 이벤트 메시지를 통해서 통신에 대한 모든 응답을 받을 수 있습니다.

발급받은 Service ID로 Omnitalk 객체를 생성합니다. 객체가 생성된 후 createSession() 메소드를 호출하여 사용자의 세션을 만듭니다. 세션이 정상적으로 생성되면 자동으로 옴니톡 서버와의 통신이 시작됩니다. createSession() 메소드를 호출할 때, 인수로 사용자를 구분하는 값(user_name: optional)을 전달할 수 있습니다.

세션이 생성되었다면 어플리케이션에서 수신할 이벤트 메시지를 등록합니다. onmessage내에 특정 이벤트가 발생했을 때 처리하고 싶은 내용을 작성하면 됩니다. 이 예제에서는 BROADCASTING_EVENT를 수신하도록 하였습니다.

BROADCASTING_EVENT 메시지는 다른 사용자가 방송을 시작하는 경우 수신됩니다. 만약 다른 사용자의 영상을 시청하고 싶다면 subscribe() 메서드에 해당 방송의 인덱스번호를 인수로 전달하면 됩니다.

옴니톡의 모든 이벤트 메시지는 Api Reference에서 확인 가능합니다.

예제 | conference.js

//omnitalk 객체 생성 (웹용은 서비스 아이디만 넣으셔도 무방합니다. app은 모두 필요)
const omnitalk = new Omnitalk("service_id","service_key"); 
    omnitalk.onmessage = async (evt) => {
        const log = document.querySelector("#log");
        switch (evt.cmd) {
            case "BROADCASTING_EVENT":
                log.insertAdjacentHTML('beforeend', `<p>Join: ${evt.user_id}</p>`);
                omnitalk?.subscribe(evt["publish_idx"]);
                break;
      }
    }
 
const sessionId = await omnitalk.createSession();

2-2. 방 만들기: createRoom()

createRoom() 메소드는 인수로 room_type을 전달 받습니다. 예를 들어 "videoroom"를 전달하면 영상 회의실이 "audioroom"을 전달하면 음성 회의실이 생성됩니다. 방을 만든 후에는 해당 방의 ID가 담긴 객체를 반환합니다. 또한 모든 방의 ID는 roomList() 메소드를 통해서 조회가 가능합니다.

예제 | createRoom()

 regiBtn.addEventListener("click", async function() {
        const roomName = document.getElementById('roomName').value;
        const roomObj = await omnitalk.createRoom("videoroom", roomName);
        const roomlist = await omnitalk.roomList("videoroom");
        log.insertAdjacentHTML('beforeend', `<p>Video RoomId: ${roomObj.room_id}</p>`);
 
        roomlist.map((item, index) => {
            log.insertAdjacentHTML('beforeend', `<p>Roomlist-${index}: ${item.subject}, ${item.room_id}</p>`);
        })
        regiBtn.disabled = true;
        document.getElementById("roomId").value = roomObj.room_id;
    });

2-3. 방 참여하기: joinRoom()

회의실에 참여할 수 있는 joinRoom() 메서드를 제공하며, 이때 방의 ID를 인수로 전달합니다. 해당 회의실에 참여중인 사용자의 목록을 조회하고 싶다면 partiList() 메서드를 호출하면 됩니다. partiList()를 통해서 방송중인 사용자의 publish_idx를 subscribe() 메서드의 인수로 전달하면 상대방의 방송을 시청할 수 있습니다.

정상적으로 참여가 완료되면 publish('videocall') 메소드를 통해 로컬의 영상 방송을 시작합니다.

예제 | joinRoom()

joinBtn.addEventListener("click", async function() {
        document.getElementById('videoDisplay').style.display = "block";
        const roomId = document.getElementById('roomId').value;
        const joinResult = await omnitalk.joinRoom(roomId);
        const partilist = await omnitalk.partiList(roomId);
                                                   //call_type record (default:false)
        const publishResult = await omnitalk.publish("videocall", false);
 
        partilist.map((item, index) => {
            log.insertAdjacentHTML('beforeend', `<p>Participant-${index}: ${item.user_id}</p>`);
            omnitalk?.subscribe(item.publish_idx);
        })
    });

정리😃

  1. 서비스 키를 발급받는다.

  2. 발급 받은 서비스 키로 옴니톡 객체를 생성한다.

  3. omnitalk.createSession()을 통해서 세션을 초기화한다.

  4. 세션이 초기화 되면 자동으로 옴니톡 서버와 통신이 이루어지며

    omnitalk 라이브러리가 제공하는 모든 함수의 사용이 가능하다.

  5. 옴니톡의 모든 함수는 async - await 구조이며, 응답은 onmessage 내에서 이벤트 메시지로 전달 받는다.

  6. omnitalk.createRoom()을 통해서 영상 회의실을 생성할 수 있다. 인수로는 room_type을 전달한다.

    생성된 방의 ID를 리턴한다.

  7. omnitalk.roomList()를 통해서 생성된 모든 방의 목록을 조회할 수 있다. 모든 방의 ID를 리턴한다.

  8. omnitalk.joinRoom()을 통해서 특정 방에 참여할 수 있다. 인수로 참여하고 싶은 방의ID를 전달한다.

  9. omnitalk.partiList()를 통해서 방에 참여한 모든 사용자을 조회할 수 있다. 참여중인 사용자의 정보를 리턴한다.

    (publish_idx 포함)

  10. 로컬사용자의 방송을 시작하고 싶을때는 omnitalk.publish()를 호출하면 서버에 로컬 사용자의 영상이 전달된다.

    인수로 call_type을 전달한다. 로컬 사용자의 publish_idx를 리턴한다.

  11. omnitalk.subscribe()를 통해서 원격에 있는 사용자의 영상을 시청한다. 인수로 반드시 구독하고 싶은

    사용자의 publish_idx를 전달한다.

여기까지 옴니톡 SDK와 자바스크립트를 활용하여

영상 회의실을 만드는 예제를 설명해 보았습니다.

글을 읽으시면서 궁금한 점이 있거나 구현 시 어려운 부분이 있다면

언제든지 댓글 남겨주세요 친절하게 설명해 드리겠습니다.

#WebRTC

profile
옴니톡의 기술 블로그입니다.

0개의 댓글