Javascript Developer Guide - Video Call

Omnitalk·2023년 5월 30일
0

옴니톡은 WebRTC 기반의 통신 플랫폼을 제공합니다. 자사의 서비스로 간편하게 통신 서비스를 개발 할 수 있도록 잘 갖추어진 SDK를 제공합니다. 매일 1시간 동안 무료로 사용 가능한 테스트키도 발급해 드리니 많은 이용 부탁드립니다. 감사합니다 :D


안녕하세요 😀 옴니톡 입니다. 오늘은 옴니톡 SDK를 이용해서 어떻게 영상 통화를 구현할 수 있는지 설명해 보고자 합니다. Javascript로 구현 된 영상 통화 이 곳에서 예제 코드는 이 곳에서 확인 가능합니다.


그럼 쉽고 간단하게 영상 통화를 구현하러 가보실까요?


*참고 아래의 글은 웹브라우저간에 영상 통화를 발신하고 착신할 수 있는 영상 통화 기능 개발에 대한 레퍼런스를 제공합니다. 통화 발신자를 Caller, 통화 착신자는 Callee라는 통신 용어로 구분합니다.

전체 코드 작성


HTML 문서 작성

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

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

그 후 자신의 번호를 등록하고 상대방의 착신 번호를 입력할 수 있는 버튼, 발신 가능 목록을 조회하는 버튼 총 3가지 버튼을 만듭니다. caller와 calle에게는 각자 서로 다른 id가 주어집니다. 해당 id를 사용하여 <video> 태그를 만들어 발신자와 착신자의 영상이 각각 출력 되도록 합니다.

예제 | index.html

<!DOCTYPE html>
<html>
  <head> 
    <meta charset="utf-8" />
    <script src="https://cdn.jsdelivr.net/npm/omnitalk-js-sdk@latest/omnitalk.min.js"></script>  
  <script src="videocall/call.js"></script>
  <style >
     video  { 
       max-width:35%;
       background:black; 
      }
  </style>
  </head>
    
  <body>
    <input type="text" id="regiNum" />
    <button type="button" id="regiBtn">번호 등록</Button>
    
    <input type="text" id="callNum" />
    <button type="button" id="callBtn">전화 걸기</Button>
    
    <div style="margin-top:15px;">  
        <video id="Omnitalk-LocalVideo-0" autoplay playsinline ></video>
        <video id="Omnitalk-RemoteVideo-0" autoplay playsinline ></video>
    </div>
    
    <button type="button" id="callListBtn">발신가능목록</Button>
    <div id="callList"> </div>
    
    <div id="log"> </div>
  </body>
</html>

HTML문서에서 필수 구현 요소는 4가지 입니다.
  1. 번호등록 버튼 : local의 번호를 등록합니다. 이벤트 타겟의 value값이 call.js의 createSession()의 인수가 됩니다.

  2. 발신가능 버튼 : 통화 가능한 목록을 불러 옵니다. 번호 등록 이후 callList()를 호출 하여 발신 가능 번호를 받아오기 위한 버튼입니다.

  3. 전화걸기 버튼 : 통화 가능한 상대에게 전화를 연결 합니다. callList()에서 받은 번호를 선택하여 해당 번호로 전화 걸기가 가능합니다.

  4. video : 각각의 해당 id 값으로 영상을 출력받습니다. (발신자 : Omnitalk-LocalVideo-0 , 착신자 : Omnitalk-RemoteVideo-0)



JS 문서 작성

전체 코드를 살펴보고 세부적인 기능을 설명합니다. 설명의 편의성을 위해 javascript 파일은 call.js에 정의합니다.

예제 | call.js

// 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");
    log.insertAdjacentHTML('beforeend', `<p>${evt.cmd}</p>`);
 
    switch (evt.cmd) {
        case "SESSION_EVENT":
            console.log(`Create session,${evt.user_id}, ${evt.result}`);
            break;
        case 'TRYING_EVENT':
            console.log('trying');
            break;
        case "RINGING_EVENT":
            console.log("Ring~ Ring~");
 
            / In this sample, automatically answer call after 3 seconds
            setTimeout(async function(){
                let sessionId = await omnitalk.answerCall();
                console.log(sessionId);
            }, 1000*3);
 
            / In this sample, automatically close video call after 30 seconds
            setTimeout(async function(){
                await omnitalk.leave();
            }, 1000*30);
            break;
        case "BROADCASTING_EVENT":
            omnitalk.subscribe(evt["publish_idx"]);
            break;
        case "CONNECTED_EVENT":
            console.log("Connected");
            break;
        case "LEAVE_EVENT":
            console.log("Disconnected");
            setTimeout(function(){
                window.location.reload(true);
            },2000);
            break;
    }
}
 
window.onload = function(){
    const regiBtn = document.querySelector("#regiBtn");
    const callBtn = document.querySelector("#callBtn");
 
    regiBtn.addEventListener("click", async function() {
        const regiNum = document.getElementById('regiNum').value;
 
        / start session. create web socket
        await omnitalk.createSession(regiNum);
    });
 
    callBtn.addEventListener("click", async function() {
        const callNum = document.getElementById('callNum').value;
 
        / offer outgoing call
        / pair with answerCall()
        await omnitalk.offerCall("videocall", callNum, false);
    });
}


전체 코드 설명

선행 작업: 서비스 키 발급

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


옴니톡 객체 생성과 이벤트 메시지

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

예제 | call.js

//omnitalk 객체 생성 (웹용은 서비스 아이디만 넣으셔도 무방합니다. app은 모두 필요)
const omnitalk = new Omnitalk("service_id","service_key");

omnitalk.onmessage = async (evt) => {

//... Event message
}

발급받은 Service ID로 Omnitalk 객체를 생성합니다.

객체가 생성되었다면 omnitalk.onmessage에 특정 이벤트가 발생했을 때 처리하고 싶은 내용을 작성하면 됩니다. 옴니톡에서 응답하는 메시지의 목록들은 API reference에 정리되어 있습니다.


세션 생성: createSession()

우선 번호를 등록하는 과정을 살펴봅니다. regiBtn에 클릭 이벤트를 추가합니다. 예제에서는 사용자가 등록한 번호(regiNum)를 createSession() 메서드에게 전달하도록 하였습니다. regiNum에는 이메일, 전화번호, 아이디 등 서비스 개발에 필요한 값을 넣도록 하면 됩니다. 만약 아무런 값도 넣어주지 않으면 옴니톡에서 임의의 랜덤 값을 배정합니다.

createSession()의 인수로 전달되는 값은 서비스 개발 시 사용자를 구분하는 용도와 특정 사용자를 호출하는 용도로 사용됩니다.

createSession()의 리턴 값은 세션 아이디이며, 세션이 정상적으로 생성되면 자동으로 옴니톡 서버와의 통신이 시작되며 onmessage에 "SESSION_EVENT"메시지가 전달됩니다.

const regiBtn = document.querySelector("#regiBtn");

regiBtn.addEventListener("click", async function() {
		const regiNum = document.getElementById('regiNum').value;

		// start session create web socket
		await omnitalk.createSession(regiNum);
	}
  • 위 예시에서 클릭이벤트 생성시 createSession()의 인수 regiNum은 새로 만들어지는 session 객체의 user_id 프로퍼티 값으로 사용됩니다.

방 조회하기: callList()

const callList = await omnitalk.callList("videocall");
  • call_type을 지정하여 발신 가능 상태와 발신 가능번호를 포함한 목록을 Json 배열로 리턴합니다.
const list = document.getElementById('callList'); 
callList.map((item, index)=> { list.insertAdjacentHTML('beforeend', 
                              `<p>CallList - ${index} : ${item.state},
                                ${item.user_id}</p>`)
                              })
  • 사용자가 선택한 발신번호가 이후 offerCall()의 두번째 인수가 됩니다.

전화 걸기: offerCall()

전화를 거는 사람은 Caller, 전화를 받는 사람은 Callee가 됩니다. 전화 걸기 버튼을 클릭하면 착신 번호를 읽고 offerCall() 메소드를 호출합니다. 첫 번째 매개변수는 call_type으로 음성 통화(audiocall), 영상 통화(videocall) 두 가지가 있습니다. 두 번째 매개변수는 착신 번호(상대방), 세 번째 매개변수는 녹화 유무입니다. 착신 번호가 등록된 상태이면 착신자는 RINGING_EVENT 메시지를 확인할 수 있습니다. 발신자는 착신자의 응답을 기다립니다.

callBtn.addEventListener("click", async function() {
        const callNum = document.getElementById('callNum').value;
        const offerCall = await omnitalk.offerCall("videocall", callNum, false);
    });

전화 받기: answerCall()

offerCall()이 호출되면 착신자(Callee)에게 RINGING_EVENT가 수신됩니다. 이 때 answerCall() 메서드를 통해 전화를 수신할 수 있습니다. 예시 코드는 설명의 편의성을 위해 RINGING_EVENT 발생시 3초 뒤에 answerCall() 메서드를 호출하여 통화를 연결하고 30초뒤 leave() 메서드를 호출하여 통화 연결을 해제합니다.


case "RINGING_EVENT":
            console.log("Ringing");
            
            setTimeout(async function(){
                let sessionId = await omnitalk.answerCall();
                console.log(sessionId);
            }, 1000*3);
 
            
            setTimeout(async function(){
                await omnitalk.leave();
            }, 1000*30);
            break;

영상 시청: subscribe()

audio call 과의 유일한 차이점은 서로 간의 영상 시청여부 이며, subscribe() 메서드의 역할이 바로 상대방의 영상을 시청하는 것입니다. BROADCASTING_EVENT 메시지에는 시청 가능한 상대방의 영상 인덱스가 수신되며, 해당 인덱스 값을 매개변수로 넣어주면 됩니다.


case "BROADCASTING_EVENT":
           await omnitalk.subscribe(evt["publish_idx"]);
            break;

Summary

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

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

  3. omnitalk.createSession()을 통해서 세션을 초기화한다. 세션을 초기화 시킬 때, 원하는 user_id값을 전달할 수 있으다.

  4. 세션이 초기화 되면 자동으로 옴니톡 서버와 통신이 이루어지며 omnitalk 라이브러리가 제공하는 모든 함수의 사용이 가능하다.

  5. omnitalk.callList()를 통해서 발신 가능한 목록을 조회할 수 있다.

  6. omnitalk.offerCall()을 통해서 전화를 걸 수 있다. 전화를 거는 사람은 caller, 받는 사람은 callee가 된다.

  7. omnitalk.answerCall()을 통해서 전화를 받을 수 있다.

  8. omnitalk.subscribe()를 통해서 상대의 영상을 시청할 수 있다.



여기까지 옴니톡 SDK와 html, vanila js만 사용하여 영상 통화 기능을 구현해 보았는데 어떠셨나요?

정말 간단하지 않나요? 서비스키를 발급 받아서 객체를 생성한 후 직관적인 함수들만 호출해주면

정말 간단하게 통신 서비스가 구현 된답니다😀

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

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


Omnitalk 홈페이지 바로가기

대표번호: 1533-5251

email: jason@omnistory.net

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

0개의 댓글