본문으로 건너뛰기
Version: 5.3

1대1 영상 통화

1대1 영상 통화를 구현하는 예제 코드입니다.

필수 조건

시작하기 전에 다음 작업을 수행해야 합니다.

1대1 영상 통화 구현 시 고려 사항

착신자 측에서 통화 알림을 받으려면 알림용 시스템을 구현하거나 APNs(Apple Push Notification service) 또는 FCM(Firebase Cloud Messaging) 같은 외부 푸시 알림 시스템을 연동해야 합니다.

또한 착신자에게 어떤 정보를 전달해야 하는지도 알아야 합니다. 앱 서버의 역할에서 애플리케이션이 전달해야 하는 데이터인 cc_param에 관해 볼 수 있습니다.

오디오 및 비디오 엘리먼트 구현

발신자와 착신자는 각각 상대방 음성을 재생하기 위한 오디오 엘리먼트와 비디오 영상을 재생하기 위한 비디오 엘리먼트를 준비합니다.

<html>
<div>
<video id="my-video" muted autoplay playsinline></video>
</div>
<div>
<audio id="peer-audio" autoplay></audio>
<video id="peer-video" muted autoplay playsinline></video>
</div>
</html>

<script>
const myVideoElement = document.getElementById('my-video');
const peerAudioElement = document.getElementById('peer-audio');
const peerVideoElement = document.getElementById('peer-video');
</script>

로컬 사용자의 비디오 미리보기(선택 사항)

WebPlanetKit에서는 사용자가 MediaStream을 쉽게 생성하고 관리할 수 있는 MediaStreamManager를 제공합니다. 이 MediaStreamManager를 이용하면 로컬 사용자가 통화 세션과 관계없이 자신의 비디오를 미리 볼 수 있는 비디오 미리보기 기능을 제공할 수 있습니다.

MediaStreamManager를 활용한 비디오 미리보기 예제 코드를 살펴보겠습니다. 먼저 비디오 미리보기 영상을 재생할 비디오 엘리먼트를 준비합니다.

<html>
<div>
<video id="preview-video" muted autoplay playsinline></video>
</div>
</html>

MediaStreamManager를 사용해 'preview-video' 비디오 엘리먼트에 영상을 재생합니다.

// Init MediaStreamManager
import { MediaStreamManager } from "@line/planetKit";

const mediaStreamManager = new MediaStreamManager();
const previewVideoElement = document.getElementById('preview-video');

// Create media stream with param
const mediaStreamParam = {
videoElement: previewVideoElement
};
const mediaStream = await mediaStreamManager.createMediaStream(mediaStreamParam);

비디오 미리보기 기능에서 사용한 MediaStreamManagermakeCall()MakeCallParams 또는 verifyCall()VerifyCallParams에 추가하면 비디오 미리보기를 위해 생성한 MediaStream을 통화에도 사용할 수 있습니다.

만약 생성한 MediaStreamManager를 통화에 사용하지 않는다면 MediaStreamManagerreleaseMediaStream()을 사용해 정리합니다.

통화 생성(발신 측)

MakeCallParams 객체를 만듭니다. 이 예제에서는 앞서 비디오 미리보기 기능에서 생성한 MediaStreamManager를 사용합니다. 만약 MediaStreamManager로 만든 MediaStream을 사용하지 않는다면 mediaStreamManager는 생략합니다.

const makeCallParams = {
myId: 'MY_ID',
myServiceId: 'MY_SERVICE_ID',
peerId: 'PEER_ID',
peerServiceId: 'PEER_SERVICE_ID',
accessToken: 'ACCESS_TOKEN',
mediaType: 'video',
mediaHtmlElement: {
my: {
video: myVideoElement
},
peer: {
audio: peerAudioElement,
video: peerVideoElement
}
},
delegate: {
// For each of the following, add your own implementation or
// assign an event handler that matches the signature
evtWaitConnected: () => {},
evtConnected: () => {},
evtDisconnected: (disconnectedParam) => {}
},
mediaStreamManager: mediaStreamManager // Optional
};

통화를 생성하려면 MakeCallParams 객체를 인자로 makeCall()을 호출하세요. makeCall() 호출에 실패한 경우, 아래 두 경우로 나눠 실패 원인을 확인할 수 있습니다.

  • 통화 연결 시도 시 실패하는 경우
    • Promise.reject()로 반환되는 MakeCallError에서 START_FAIL_REASON을 확인해 실패 원인을 파악할 수 있습니다.
  • 통화 연결 후 실패하는 경우
    • 통화 연결 후에는 MakeCallParams.delegateevtDisconnected 이벤트를 통해 실패 원인을 확인할 수 있습니다. 통화 종료 이유와 관련된 자세한 내용은 통화 종료 이유를 참고하세요.
planetKit.makeCall(makeCallParams)
.then(() => {
// Successfully made a call
})
.catch((makeCallError) => {
// Failed to make a call
// makeCallError.reason: START_FAIL_REASON
// makeCallError.message: A descriptive message about the failure.
});

통화 알림 수신(착신 측)

FCM은 웹 푸시 알림 방식 중 하나입니다. 다음은 CDN을 이용한 FCM 설정 예시입니다.

<html>
<script src="https://www.gstatic.com/firebasejs/7.24.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.24.0/firebase-messaging.js"></script>
</html>
<script>
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: 'SAMPLE_API_KEY',
authDomain: 'SAMPLE_AUTH_DOMAIN',
databaseURL: 'SAMPLE_DATABASE_URL',
projectId: 'SAMPLE_PROJECT_ID',
storageBucket: 'SAMPLE_STORAGE_BUCKET',
messagingSenderId: 'SAMPLE_MESSAGING_SENDER_ID',
appId: 'SAMPLE_APP_ID'
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);

// Retrieve a Firebase Messaging object
fcmSample = firebase.messaging();
fcmSample.usePublicVapidKey('SAMPLE_VAPID_KEY');

// Get a web push notification event
fcmSample.onMessage((payload) => {
callVerify(payload.data); // See the next step, "Callee side - Respond to a call"
});
</script>

통화 수신(착신 측)

착신자는 푸시 알림을 통해 새로운 전화가 왔음을 알게 됩니다. 착신자가 푸시 메시지를 받으면 앱 서버에서 수신한 정보를 기반으로 VerifyCallParams 객체를 생성하세요. 메시지에서 cc_param을 파싱해 VerifyCallParams 객체의 ccParam으로 설정해야 합니다.

통화를 수신하려면 VerifyCallParams 객체를 인자로 verifyCall()을 호출하세요. verifyCall() 호출에 실패한 경우 아래 두 경우로 나눠 실패 원인을 확인할 수 있습니다.

  • 통화 연결 시도 시 실패하는 경우
    • Promise.reject()로 반환되는 VerifyCallError에서 START_FAIL_REASON을 확인해 실패 원인을 파악할 수 있습니다.
  • 통화 연결 후 실패하는 경우
    • 통화 연결 후에는 VerifyCallParams.delegateevtDisconnected 이벤트를 통해 실패 원인을 확인할 수 있습니다. 통화 종료 이유와 관련된 자세한 내용은 통화 종료 이유를 참고하세요.
function callVerify(notifyParams) {
// Set verifyCallParams based on information of notifyParams received from the app server
const verifyCallParams = {
myId: notifyParams.app_callee_uid,
myServiceId: notifyParams.app_callee_sid,
mediaType: notifyParams.app_call_type, // 'video'
ccParam: notifyParams.cc_param,
mediaHtmlElement: {
my: {
video: myVideoElement
},
peer: {
audio: peerAudioElement,
video: peerVideoElement
}
},
delegate: {
// For each of the following, add your own implementation or
// assign an event handler that matches the signature
evtVerified: (callVerifiedParams) => {},
evtConnected: () => {},
evtDisconnected: (disconnectedParam) => {},
}
}
planetKit.verifyCall(verifyCallParams)
.then(() => {
// Successfully verified a call
})
.catch((verifyCallError) => {
// Failed to verify a call
// verifyCallError.reason: START_FAIL_REASON
// verifyCallError.message: A descriptive message about the failure.
});
}

통화 응답(착신 측)

피어와의 세션 연결에 성공하면 웹 클라이언트는 VerifyCallParamsdelegate에 설정된 evtVerified를 실행합니다. evtVerified 이벤트를 받은 후 acceptCall()을 호출해 전화를 받습니다.

planetKit.acceptCall()
.then(() => {
// Successfully accepted a call
})
.catch((error) => {
// Failed to accept a call
});

통화 종료

통화를 종료하려면 endCall()을 호출하세요.

planetKit.endCall();

관련 예제 코드

관련 문서