https://a.storyblok.com/f/270183/92002/83ae5bad9c/video-call_swiftui_1200x600.png

Como fazer chamadas de Video com o SwiftUI

Publicado em May 13, 2021

Tempo de leitura: 5 minutos

Este artigo foi atualizado em março de 2025

Neste tutorial, você utilizará o Vonage Client SDK for Video Client from Vonage para iOS para criar um chat de vídeo individual no SwiftUI.

Pré-requisitos

Criar um projeto da Video API da Vonage

Abra seu painel da API da Vonage e crie um novo aplicativo Vonage. Você pode dar a ele o nome que quiser, mas habilite a opção “Video” na seção de recursos e, em seguida, clique em “Gerar um novo aplicativo”. Assim que o aplicativo for criado, copie o ID do aplicativo. Em seguida, acesse o Vonage Video Playground e crie uma nova sessão:

  1. Certifique-se de que a aba “Criar uma nova sessão” esteja selecionada na parte superior.

  2. Selecione “Sim” na opção “Tem um ID de aplicativo específico?”

  3. Cole o ID do aplicativo que você gerou anteriormente na caixa “ID do aplicativo” que aparecerá.

  4. Deixe todo o resto como está e clique em “Criar sessão”.

  5. Na próxima página que aparecer, anote o “ID DA SESSÃO”.

  6. Clique no botão “Conectar”, na parte superior.

  7. Expanda a seção “Informações sobre sessão e token” na parte superior.

  8. Anote o “TOKEN” que foi gerado

Criação do aplicativo para iOS

O próximo passo é configurar o aplicativo para iOS. Depois de criar o aplicativo, é preciso instalar o Client SDK do Video Client e solicitar permissões para o microfone e a câmera.

Criar um projeto no Xcode

Para começar, abra o Xcode e crie um novo projeto selecionando Arquivo > Novo > Projeto. Selecione iOS como plataforma e App como modelo, e dê um nome ao projeto.

Xcode platform screen

Selecione SwiftUI para a interface, SwiftUI App para o ciclo de vida e Swift para a linguagem. Por fim, escolha um local para salvar seu projeto.

Xcode project creation screen

Instale o Client SDK

Agora que você criou o projeto, pode adicionar o Video Client SDK como dependência. Feche seu projeto do Xcode, acesse no terminal o local onde salvou o projeto e execute os seguintes comandos:

  1. Execute o comando `pod init` para criar um novo `Podfile` para o seu projeto.

  2. Abra o Podfile no Xcode usando o comando `open -a Xcode Podfile`.

  3. Atualize o Podfile para incluir OTXCFramework como dependência.

# Uncomment the next line to define a global platform for your project
# platform :ios, '12.0'

target 'VideoChat' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for VideoChat
  pod 'OTXCFramework'

end
  1. Instale o SDK usando pod install.

  2. Abra o novo arquivo xcworkspace no Xcode usando open VideoChat.xcworkspace.

Permissões

Como o aplicativo utilizará o microfone e a câmera para realizar videochamadas, é necessário adicionar descrições explicando por que essas permissões são necessárias; essas descrições serão exibidas em uma mensagem de aviso ao executar o aplicativo.

Edite o Info.plist arquivo. O Info.plist é um arquivo que contém todos os metadados necessários para o aplicativo. Adicione uma nova entrada ao arquivo passando o mouse sobre a última entrada da lista e clicando no pequeno + que aparece. Na lista suspensa, selecione Privacy - Microphone Usage Description e adicione Microphone access required to video chat como valor. Repita os passos para Privacy - Camera Usage Description.

O Client SDK do Video

O Client SDK do Vídeo utiliza as credenciais que você criou no painel da Video API para se conectar aos servidores da Vonage.

Conectando o Client SDK

Crie um novo arquivo chamado OpenTokManager.swift acessando Arquivo > Novo Arquivo (CMD + N) e adicione o seguinte, substituindo as sequências vazias pelas suas credenciais:

import OpenTok

final class OpenTokManager: NSObject, ObservableObject {
    // Replace with your Vonage Application ID
    private let kAppId = ""
    // Replace with your generated session ID
    private let kSessionId = ""
    // Replace with your generated token
    private let kToken = ""

    private lazy var session: OTSession = {
        return OTSession(apiKey: kAppId, sessionId: kSessionId, delegate: self)!
    }()

    private lazy var publisher: OTPublisher = {
        let settings = OTPublisherSettings()
        settings.name = UIDevice.current.name
        return OTPublisher(delegate: self, settings: settings)!
    }()
    
    private var subscriber: OTSubscriber?
    
    @Published var pubView: UIView?
    @Published var subView: UIView?
    @Published var error: OTErrorWrapper?
}

Além das credenciais, há variáveis para uma sessão, editor e assinante. Conforme mencionado anteriormente, você pode pensar em uma sessão como uma sala à qual os clientes se conectam; o SDK possui a OTSession classe para isso. Os publicadores, OTPublisher, permitem que o cliente publique áudio e Video quando conectado a uma sessão. Os assinantes, OTSubscriber, permitem que o cliente assine o áudio e o Video de outros clientes na sessão. Há também variáveis que utilizam o @Published wrapper de propriedade, que é como a OpenTokManager classe se comunicará com o código da visualização mais adiante.

Agora que as propriedades estão definidas, adicione as seguintes funções à OpenTokManager classe:

import OpenTok

final class OpenTokManager: NSObject, ObservableObject {
    ...

    public func setup() {
        doConnect()
    }
    
    private func doConnect() {
        var error: OTError?
        defer {
            processError(error)
        }
        session.connect(withToken: kToken, error: &error)
    }
    
    private func doPublish() {
        var error: OTError?
        defer {
            processError(error)
        }
        
        session.publish(publisher, error: &error)
        
        if let view = publisher.view {
            DispatchQueue.main.async {
                self.pubView = view
            }
        }
    }
    
    private func doSubscribe(_ stream: OTStream) {
        var error: OTError?
        defer {
            processError(error)
        }
        subscriber = OTSubscriber(stream: stream, delegate: self)
        session.subscribe(subscriber!, error: &error)
    }
    
    private func cleanupSubscriber() {
        DispatchQueue.main.async {
            self.subView = nil
        }
    }
    
    private func cleanupPublisher() {
        DispatchQueue.main.async {
            self.pubView = nil
        }
    }
    
    private func processError(_ error: OTError?) {
        if let err = error {
            DispatchQueue.main.async {
                self.error = OTErrorWrapper(error: err.localizedDescription)
            }
        }
    }
}

A doConnect função conecta o cliente à sessão e doPublish inicia a publicação, doSubscribe inicia a assinatura. Depois, há funções para liberar o assinante (cleanupSubscriber) e do editor (cleanupPublisher) quando o cliente se desconecta de qualquer um deles, seguida por uma função para lidar com erros (processError).

O OTSessionDelegate

É OTSessionDelegate é assim que o Client SDK do Video comunica as alterações da sessão de volta para você. Adicione uma extensão no mesmo arquivo:

extension OpenTokManager: OTSessionDelegate {
    func sessionDidConnect(_ session: OTSession) {
        print("Session connected")
        doPublish()
    }
    
    func sessionDidDisconnect(_ session: OTSession) {
        print("Session disconnected")
    }
    
    func session(_ session: OTSession, didFailWithError error: OTError) {
        print("session Failed to connect: \(error.localizedDescription)")
    }
    
    func session(_ session: OTSession, streamCreated stream: OTStream) {
        print("Session streamCreated: \(stream.streamId)")
        doSubscribe(stream)
    }
    
    func session(_ session: OTSession, streamDestroyed stream: OTStream) {
        print("Session streamDestroyed: \(stream.streamId)")
        if let subStream = subscriber?.stream, subStream.streamId == stream.streamId {
            cleanupSubscriber()
        }
    }
}

Quando a sessão se conecta, doPublish é chamado; quando um stream é criado doSubscribe é chamado e quando o fluxo é destruído cleanupSubscriber é chamado.

O OTPublisherDelegate

É OTPublisherDelegate é assim que o Client SDK de Vídeo comunica a você as alterações relacionadas à publicação em uma sessão. Adicione uma extensão no mesmo arquivo:

extension OpenTokManager: OTPublisherDelegate {
    func publisher(_ publisher: OTPublisherKit, streamCreated stream: OTStream) {
        print("Publishing")
    }
    
    func publisher(_ publisher: OTPublisherKit, streamDestroyed stream: OTStream) {
        cleanupPublisher()
        if let subStream = subscriber?.stream, subStream.streamId == stream.streamId {
            cleanupSubscriber()
        }
    }
    
    func publisher(_ publisher: OTPublisherKit, didFailWithError error: OTError) {
        print("Publisher failed: \(error.localizedDescription)")
    }
}

Da mesma forma que OTSessionDelegate quando o fluxo é destruído, cleanupPublisher é chamado, e cleanupSubscriber se houver uma assinatura ativa de um stream.

O OTSubscriberDelegate

É OTSubscriberDelegate é assim que o Client SDK do Vídeo comunica as alterações, inscrevendo-se em uma sessão para você. Adicione uma extensão no mesmo arquivo:

extension OpenTokManager: OTSubscriberDelegate {
    
    func subscriberDidConnect(toStream subscriberKit: OTSubscriberKit) {
        if let view = subscriber?.view {
            DispatchQueue.main.async {
                self.subView = view
            }
        }
    }
    
    func subscriber(_ subscriber: OTSubscriberKit, didFailWithError error: OTError) {
        print("Subscriber failed: \(error.localizedDescription)")
    }
}

Da mesma forma que ao publicar em uma sessão, se a inscrição for bem-sucedida, é retornado um UIView objeto. No caso de subscriberDidConnect o objeto de visualização retornado for destinado ao assinante.

Criação da interface do usuário do chat por vídeo

Com a OpenTokManager classe concluída, agora você pode construir a interface do usuário. O Video Client SDK fornece UIView objetos para as visualizações do editor e do assinante que não podem ser usados diretamente no SwiftUI. O UIViewRepresentable protocolo permite fazer a ponte entre um UIView objeto para um View outro objeto para o SwiftUI. No ContentView.swift arquivo, adicione as seguintes estruturas:

struct OTErrorWrapper: Identifiable {
    var id = UUID()
    let error: String
}

struct OTView: UIViewRepresentable {
    @State var view: UIView
    
    func makeUIView(context: Context) -> UIView {
        return view
    }
    
    func updateUIView(_ uiView: UIView, context: Context) {
        DispatchQueue.main.async {
            self.view = uiView
        }
    }
}

A OTView estrutura, que está em conformidade com UIViewRepresentable possui um UIView objeto como propriedade. Essa view é retornada quando o sistema chama makeUIView. Como o ciclo de vida das visualizações no SwiftUI é controlado pelo sistema, você também precisa implementarupdateUIViewpara lidar com isso. AOTErrorWrapperestrutura permite que `error` seja compatível comIdentifiable, o que é necessário para usar os alertas do SwiftUI.

Em seguida, substitua a ContentView estrutura pelo seguinte:

struct ContentView: View {
    @ObservedObject var otManager = OpenTokManager()
    
    var body: some View {
        VStack {
            otManager.pubView.flatMap { view in
                OTView(view: view)
                    .frame(width: 200, height: 200, alignment: .center)
            }.cornerRadius(5.0)
            otManager.subView.flatMap { view in
                OTView(view: view)
                    .frame(width: 200, height: 200, alignment: .center)
            }.cornerRadius(5.0)
        }
        .alert(item: $otManager.error, content: { error -> Alert in
            Alert(title: Text("OpenTok Error"), message: Text(error.error), dismissButton: .default(Text("Ok")))
        })
        .animation(.default)
        .onAppear(perform: {
            otManager.setup()
        })
    }
}

Este código adiciona uma propriedade a uma instância da OpenTokManager classe mencionada anteriormente. Como as visualizações que OpenTokManager estão sendo publicadas são opcionais, .flatmap é usado. Assim, quando as visualizações são nil, elas são ignoradas; e quando há um valor, elas são desembrulhadas. Se o OpenTokManager publicar um erro, o alerta será exibido automaticamente, já que ele está monitorando alterações no .error .

Se você compilar e executar o projeto, agora já deve conseguir iniciar um bate-papo por Video! Você pode usar outro dispositivo ou o Playground da Video API para se conectar à sessão a partir do seu laptop.

video chat ios screenshot

E agora?

O projeto concluído está disponível no GitHub, e você pode ler mais sobre a Video API da Vonage em nossa documentação.

Compartilhar:

https://a.storyblok.com/f/270183/400x400/19c02db2d3/abdul-ajetunmobi.png
Abdul AjetunmobiEx-funcionário da Vonage

Abdul é um Developer Advocate da Vonage. Ele tem experiência profissional na área de produtos de consumo como engenheiro de iOS. Em seu tempo livre, ele gosta de andar de bicicleta, ouvir música e orientar quem está dando os primeiros passos na área de tecnologia