[Sendbird Calls] 비디오 렌더링 뷰를 SwiftUI로 다루기

J_sung_0o0
7 min readSep 26, 2020

--

VideoCall view in SwiftUI & SendBirdCalls

SendBirdVideoView 변환하기

! 현재 글에서 다루는 내용은 빠른 이해를 위한 간략한 예시 입니다. 실제 사용시에는 예시코드를 앱 구현 내용에 알맞게 수정해서 사용하시길 바랍니다.

import SwiftUIimport SendBirdCallsstruct VideoView: UIViewRepresentable {    enum VideoType {        case local        case remote    }    let call: DirectCall?    let type: VideoType    func makeUIView(context: Context) -> SendBirdVideoView {        return SendBirdVideoView(frame: UIScreen.main.bounds)    }
func updateUIView(_ uiView: SendBirdVideoView, context: Context) { switch self.type { case .local: uiView.transform = CGAffineTransform(scaleX: -1.0, y: 1.0) call?.updateLocalVideoView(uiView) case .remote: call?.updateRemoteVideoView(uiView) } }}

SwiftUISendBirdCalls 프레임워크를 가져옵니다.

import SwiftUIimport SendBirdCalls

SendBirdCalls 에서 영상통화 시 비디오를 렌더링 해주는 SendBirdVideoView를 SwiftUI에서 쓸 수 있도록 UIViewRepresentable 을 사용하여 VideoView 를 만듭니다. makeUIView(context:) 메소드 안에서 SendBirdVideoView 를 생성해서 리턴하도록 합니다.

struct VideoView: UIViewRepresentable {    func makeUIView(context: Context) -> SendBirdVideoView {        return SendBirdVideoView(frame: UIScreen.main.bounds)    }    func updateUIView(_ uiView: SendBirdVideoView, context: Context)   
{
}
}

생성된 비디오뷰를 DirectCall 객체에 주입하기 위해 아래와 같이 DirectCall 타입의 프로퍼티를 선언하고 현재 비디오 뷰를 local 로 쓸 지 remote 로 쓸지 정하는 enum 도 내부에 정의해주도록 합니다.

struct VideoView: UIViewRepresentable {    enum VideoType {        case local        case remote    }    let call: DirectCall?    let type: VideoType

// ...
}

DirectCall 은 영상통화에 사용되는 비디오뷰를 전화하기전에 SendBirdCall.dial 메소드에서SendBirdVideoView 객체를 파라미터로 주입하여 세팅을 할 수 있지만, 전화를 건 이후에 생성된 DirectCall 객체에 updateLocalVideoView(_:) , updateRemoteVideoView(_:) 메소드를 사용하여 세팅할 수도 있습니다. 여기서는 후자의 세팅 방법을 사용하도록 하겠습니다.

updateUIView(_:context:) 메소드에서 아래와 같이 비디오뷰가 사용될 DirectCall 에 뷰를 세팅해주도록 합니다.

func updateUIView(_ uiView: SendBirdVideoView, context: Context) {    switch self.type {    case .local: call?.updateLocalVideoView(uiView)    case .remote: call?.updateRemoteVideoView(uiView)    }}

만약 로컬 비디오 뷰를 거울처럼 미러링된 화면을 보여주도록 하고 싶다면 .local 의 경우를 아래와 같이 수정하면 됩니다.

case .local:    uiView.transform = CGAffineTransform(scaleX: -1.0, y: 1.0)    call?.updateLocalVideoView(uiView)

비디오콜 화면 구현하기

! 현재 글에서 다루는 내용은 빠른 이해를 위한 간략한 예시 입니다. 실제 사용시에는 예시코드를 앱 구현 내용에 알맞게 수정해서 사용하시길 바랍니다.

위에서 생성한 VideoView 를 사용해서 비디오콜 UI 를 구현해보도록 하겠습니다.

우선 SendBirdCall.dial 을 했을 때 생성된 객체를 CallManager 라는 ObservableObject 를 준수하는 뷰모델 클래스에서 관리한다고 가정을 하겠습니다.

import Combine
import SendBirdCall
class CallManger: ObservableObject {
@Published var currentCall: DirectCall?
...
}

VideoCallView 구조체를 선언하고 View 프로토콜을 준수하도록 합니다. 그리고 ObservedObject 속성과 함께 callManager 프로퍼티를 선언하여 CallManager로부터 currentCall의 변화 이벤트를 받을 수 있도록 합니다.

import SwiftUIstruct VideoCallView: View {    @ObservedObject var callManager: CallManager    var body: some View {    
}
}

body안에 CallManagercurrentCall 을 사용하여 VideoView객체를 아래와 같이 local 용 과 remote 용 두가지를 생성하도록 합니다. ZStack을 사용하여 remote 비디오뷰 위에 local 비디오 뷰가 올라오도록 할 것입니다.

ZStack {
VideoView(call: user.currentCall, type: .remote)
.ignoresSafeArea()
// local 뷰가 좌측 상단에 위치하도록 함
VStack {
HStack {
VideoView(call: user.currentCall, type: .local)
.frame(width: 96, height: 160)
Spacer()
}
Spacer()
}
}

음소거, 화면끄기, 통화종료 등 비디오콜에 필요한 버튼들을 추가하면 끝!

참고

--

--

J_sung_0o0

Apple WWDC 19 & 20 Winner (The 1st two-time winner of all time from South Korea)