Javascript Developer Guide - Audio Call

Omnitalk·2023년 5월 31일
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가지 버튼을 만듭니다.

예제 | 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="audiocall/call.js"></script>
  </head>
    
  <body>
    <input type="text" id="regiNum" />
    <button type="button" id="regiBtn">번호 등록</Button>
    
    <input type="text" id="callNum" />
    <button type="button" id="callBtn">전화 걸기</Button>
    
    <button type="button" id="callListBtn">발신가능목록</Button>
    <div id="callList"> </div>
    
    <div id="log"> </div>
  </body>
</html>

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

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

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



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('Ringing');
            // 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 audio call after 30 seconds
            setTimeout(async function(){
                await omnitalk.leave();
            }, 1000*30);
            break;
        case 'CONNECTED_EVENT':
            console.log('Connected');
            break;
        case 'LEAVE_EVENT':
            console.log('Disconnected');
            break;
    }
}
 
window.onload = function(){
    const regiBtn = document.querySelector('#regiBtn');
    const callBtn = document.querySelector('#callBtn');
    const callListBtn = document.querySelector('#callListBtn');
 
    regiBtn.addEventListener('click', async function() {
        const regiNum = document.getElementById('regiNum').value;
 
        // start session. create web socket
        const session = await omnitalk.createSession(regiNum);
    });
 
    callBtn.addEventListener('click', async function() {
        const callNum = document.getElementById('callNum').value;
 
        // offer outgoing call
        // pair with answerCall()
        const offerCall = await omnitalk.offerCall('audiocall', callNum, false);
    });
 
    callListBtn.addEventListener('click', async function(){
        const regiNum = document.getElementById('regiNum').value;
        const callList = await omnitalk.callList('audiocall');
        console.log(callList);
        const list = document.getElementById('callList');
        callList.map((item, index)=> {
            list.insertAdjacentHTML('beforeend', `<p>CallList - ${index} : ${item.state}, ${item.user_id}</p>`)
        })
    })
}


전체 코드 설명

선행 작업: 서비스 키 발급

옴니톡의 통신 서비스를 사용하기 위해서는 서비스 키가 반드시 필요합니다. 회원가입이 승인된 후 발급 받거나, 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("audiocall");
  • 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("audiocall", 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;

Summary

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

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

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

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

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

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

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



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

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

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

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

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


Omnitalk 홈페이지 바로가기

대표번호: 1533-5251

email: omnitalk@omnistory.net

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

0개의 댓글