twilio / video-quickstart-ios

Twilio Video Quickstart for iOS
https://www.twilio.com/docs/api/video
MIT License
457 stars 177 forks source link

Local video source not displayed on the remote side after first displaying #657

Open Robtles opened 1 year ago

Robtles commented 1 year ago

Description

Hello, I am trying to implement Twilio Video in an application, but I'm struggling with the case when a user stops his camera, and then starts it again. The local video track is correctly being published to the room the first time, but when he stops and starts again the camera, it's not displayed again on the remote side.

I am working with a web/backend team which handles the code for Twilio implementation on the web side, which is where the error occurs (the local iOS video is not displayed there), so I don't have access to this code but I wanted to know if something might be wrong with mine.

Here is what I have written so far :

Code

final class VideoViewController: UIViewController {
    /// Instance
    private var accessToken: String?
    private var cameraIsOn: Bool = true {
        didSet {
            guard oldValue != cameraIsOn else { return }
            updateLocalCameraStatus()
        }
    }
    private var roomName: String?

    /// Twilio
    private var cameraSource: CameraSource?
    private var localVideoTrack: LocalVideoTrack?
    private var room: Room?

    /// View
    @IBOutlet weak var cameraButton: UIButton!
    @IBOutlet weak var previewView: VideoView?

    /// Action
    @IBAction func tappedCamera() {
        cameraIsOn.toggle()
    }

    /// Lifecycle
    override func viewDidLoad() {
        super.viewDidLoad()
        previewView?.delegate = self
        updateLocalCameraStatus()
        connectToTheRoom()
    }

    /// Twilio
    private func connectToTheRoom() {
        guard let accessToken else { return }
        let connectOptions = ConnectOptions(
            token: accessToken
        ) { [weak self] builder in
            guard let self else { return }
            builder.videoTracks = [self.localVideoTrack].compactMap { $0 }
            builder.roomName = self.roomName
        }
        room = TwilioVideoSDK.connect(
            options: connectOptions,
            delegate: self
        )
    }

    private func startPreview() {
        guard let frontCamera = CameraSource.captureDevice(position: .front),
              let source = CameraSource(delegate: self),
              let previewView else {
            return
        }
        localVideoTrack = LocalVideoTrack(source: source, enabled: true, name: "camera")
        cameraSource = source
        cameraSource?.startCapture(device: frontCamera)
        guard let localVideoTrack else { return }
        localVideoTrack.addRenderer(previewView)
        room?.localParticipant?.publishVideoTrack(localVideoTrack)
    }

    private func stopPreview() {
        cameraSource?.stopCapture()
        if let localVideoTrack {
            room?.localParticipant?.unpublishVideoTrack(localVideoTrack)
            if let previewView {
                localVideoTrack.removeRenderer(previewView)
            }
        }
        cameraSource = nil
        localVideoTrack = nil
    }

    private func updateLocalCameraStatus() {
        cameraIsOn ? startPreview() : stopPreview()
    }
}

/// Twilio Extensions
extension VideoViewController: RoomDelegate {
    func roomDidConnect(room: Room) {
        print("roomDidConnect")
    }
}

extension VideoViewController: CameraSourceDelegate {
    func cameraSourceWasInterrupted(source: CameraSource, reason: AVCaptureSession.InterruptionReason) {
        localVideoTrack?.isEnabled = false
    }

    func cameraSourceInterruptionEnded(source: CameraSource) {
        localVideoTrack?.isEnabled = true
    }
}

extension VideoViewController: VideoViewDelegate {
    func videoViewDimensionsDidChange(view: VideoView, dimensions: CMVideoDimensions) {
        view.setNeedsLayout()
    }
}

Expected Behavior

Every time the user stops the camera (stopPreview()) then starts it again (startPreview()), the remote participant should be able to watch its track.

Actual Behavior

The video track is not displayed after the first time the user stops the preview.

Reproduces How Often

Always.

Logs

No relevant log.

Versions

Video iOS SDK

5.3.0

Xcode

14.0.1

iOS Version

16.1.1

iOS Device

iPhone XR

Thank you for your help!