1대1 영상 통화
1대1 영상 통화를 구현하는 예제 코드입니다.
필수 조건
시작하기 전에 다음 작업을 수행해야 합니다.
- PlanetKit을 초기화하세요.
- 적절한 액세스 토큰을 획득하세요.
- 1대1 통화 흐름에서 전반적인 API 사용 과정을 확인하세요.
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);
비디오 미리보기 기능에서 사용한 MediaStreamManager
를 makeCall()
의 MakeCallParams
또는 verifyCall()
의 VerifyCallParams
에 추가하면 비디오 미리보기를 위해 생성한 MediaStream
을 통화에도 사용할 수 있습니다.
만약 생성한 MediaStreamManager
를 통화에 사용하지 않는다면 MediaStreamManager
의 releaseMediaStream()
을 사용해 정리합니다.
통화 생성(발신 측)
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.delegate
의evtDisconnected
이벤트를 통해 실패 원인을 확인할 수 있습니다. 통화 종료 이유와 관련된 자세한 내용은 통화 종료 이유를 참고하세요.
- 통화 연결 후에는
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.delegate
의evtDisconnected
이벤트를 통해 실패 원인을 확인할 수 있습니다. 통화 종료 이유와 관련된 자세한 내용은 통화 종료 이유를 참고하세요.
- 통화 연결 후에는
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.
});
}
통화 응답(착신 측)
피어와의 세션 연결에 성공하면 웹 클라이언트는 VerifyCallParams
의 delegate
에 설정된 evtVerified
를 실행합니다. evtVerified
이벤트를 받은 후 acceptCall()
을 호출해 전화를 받습니다.
planetKit.acceptCall()
.then(() => {
// Successfully accepted a call
})
.catch((error) => {
// Failed to accept a call
});
통화 종료
통화를 종료하려면 endCall()
을 호출하세요.
planetKit.endCall();