Description
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!