swift - 在 iOS 中使用 Twilio 进行屏幕共享

标签 swift twilio

我正在使用 Twilio iOS 框架在群组 session 室中进行连接。 单击下面的连接房间按钮是我使用的代码

let recorder = RPScreenRecorder.shared()
recorder.isMicrophoneEnabled = false
recorder.isCameraEnabled = false

// The source produces either downscaled buffers with smoother motion, or an HD screen recording.
videoSource = ReplayKitVideoSource(isScreencast: true, telecineOptions: ReplayKitVideoSource.TelecineOptions.disabled)

screenTrack = LocalVideoTrack(source: videoSource!,
                              enabled: true,
                              name: "Screen")

recorder.startCapture(handler: { (sampleBuffer, type, error) in
    if error != nil {
        print("Capture error: ", error as Any)
        return
    }
    
    switch type {
    case RPSampleBufferType.video:
        self.videoSource?.processFrame(sampleBuffer: sampleBuffer)
        break
    case RPSampleBufferType.audioApp:
        break
    case RPSampleBufferType.audioMic:
        // We use `TVIDefaultAudioDevice` to capture and playback audio for conferencing.
        break
    }
    
}) { (error) in
    if error != nil {
        print("Screen capture error: ", error as Any)
    } else {
        print("Screen capture started.")
    }
}

if (accessToken == "TWILIO_ACCESS_TOKEN") {
    do {
        accessToken = try TokenUtils.fetchToken(url: tokenUrl)
    } catch {
        let message = "Failed to fetch access token"
        logMessage(messageText: message)
        return
    }
}

// Prepare local media which we will share with Room Participants.
self.prepareLocalMedia()

// Preparing the connect options with the access token that we fetched (or hardcoded).
let connectOptions = ConnectOptions(token: accessToken) { (builder) in
    
    // Use the local media that we prepared earlier.
    builder.audioTracks = self.localAudioTrack != nil ? [self.localAudioTrack!] : [LocalAudioTrack]()
    builder.videoTracks = self.localVideoTrack != nil ? [self.localVideoTrack!, self.screenTrack!] : [LocalVideoTrack]()
    
    // Use the preferred audio codec
    if let preferredAudioCodec = Settings.shared.audioCodec {
        builder.preferredAudioCodecs = [preferredAudioCodec]
    }
    
    // Use the preferred video codec
    if let preferredVideoCodec = Settings.shared.videoCodec {
        builder.preferredVideoCodecs = [preferredVideoCodec]
    }
    
    // Use the preferred encoding parameters
    if let encodingParameters = Settings.shared.getEncodingParameters() {
        builder.encodingParameters = encodingParameters
    }
    
    // Use the preferred signaling region
    if let signalingRegion = Settings.shared.signalingRegion {
        builder.region = signalingRegion
    }
    
    builder.roomName = self.roomTextField.text
}

// Connect to the Room using the options we provided.
room = TwilioVideoSDK.connect(options: connectOptions, delegate: self)

logMessage(messageText: "Attempting to connect to room \(String(describing: self.roomTextField.text))")

当我在群组中与远程参与者连接时,我想与远程参与者共享屏幕。
为了实现此功能,我使用应用内捕获方法引用了“ReplayKitExample”。但无法做到这一点。
远程参与者无法看到屏幕共享内容。
与屏幕共享相关的任何事情都没有发生,并且正在寻找有关实现它的输入。
我想将屏幕共享给远程参与者。

最佳答案

发生这种情况是因为您尝试同时发送“cameraSource”和“videoSource”这两个数据,因此您必须在发送“viseoSource”之前取消订阅“cameraSource”。 这是我的代码,您可以引用:

//MARK: - Screen Sharing via replaykit

extension CallRoomViewController: RPScreenRecorderDelegate {

func broadCastButtonTapped(){
    guard screenRecorder.isAvailable else {
        print("Not able to Broadcast")
     

    return
    }
    print("Can Broadcast")

    if self.videoSource != nil {
        self.stopConference()
    } else {
        self.startConference()
    }
}
func publishVideoTrack(){
    if let participant = self.room?.localParticipant,
            let videoTrack = self.localVideoTrack {
            participant.publishVideoTrack(videoTrack)
        }
}

func unpublishVideoTrack(){
    if let participant = self.room?.localParticipant,
        let videoTrack = self.localVideoTrack {
        participant.unpublishVideoTrack(videoTrack)
    }
}

func stopConference() {
    self.unpublishVideoTrack()
    self.localVideoTrack = nil
    self.videoSource = nil
    self.localVideoTrack = LocalVideoTrack(source: cameraSource!, enabled: true, name: "Camera")

    screenRecorder.stopCapture{ (captureError) in
        if let error = captureError {
            print("Screen capture stop error: ", error as Any)
        } else {
            print("Screen capture stopped.")
            self.publishVideoTrack()
        }
    }
}

func startConference() {

    self.unpublishVideoTrack()
    self.localVideoTrack = nil

    // We are only using ReplayKit to capture the screen.

    // Use a LocalAudioTrack to capture the microphone for sharing audio in the room.
    screenRecorder.isMicrophoneEnabled = false
    // Use a LocalVideoTrack with a CameraSource to capture the camera for sharing camera video in the room.
    screenRecorder.isCameraEnabled = false

    // The source produces either downscaled buffers with smoother motion, or an HD screen recording.
    self.videoSource = ReplayKitVideoSource(isScreencast: true,
                                       telecineOptions: ReplayKitVideoSource.TelecineOptions.p60to24or25or30)

    self.localVideoTrack = LocalVideoTrack(source: videoSource!,
                                  enabled: true,
                                  name: "Screen")

    let videoCodec = Settings.shared.videoCodec ?? Vp8Codec()!
    let (_, outputFormat) = ReplayKitVideoSource.getParametersForUseCase(codec: videoCodec,
                                                                                      isScreencast: true,
                                                                                   telecineOptions:ReplayKitVideoSource.TelecineOptions.p60to24or25or30)
    self.videoSource?.requestOutputFormat(outputFormat)

    screenRecorder.startCapture(handler: { (sampleBuffer, type, error) in
        if error != nil {
            print("Capture error: ", error as Any)
            return
        }

        switch type {
        case RPSampleBufferType.video:
            self.videoSource?.processFrame(sampleBuffer: sampleBuffer)
            break
        case RPSampleBufferType.audioApp:
            break
        case RPSampleBufferType.audioMic:
            // We use `TVIDefaultAudioDevice` to capture and playback audio for conferencing.
            break
        default:
            print(error ?? "screenRecorder error")
        }

    }) { (error) in
        if error != nil {
            print("Screen capture error: ", error as Any)
        } else {
            print("Screen capture started.")
            self.publishVideoTrack()
        }
    }
}
}

你可以从 viewDidLoad() 连接房间

    func connectToChatRoom(){
    
    // Configure access token either from server or manually.
    // If the default wasn't changed, try fetching from server.
    accessToken = self.callRoomDetail.charRoomAccessToken
    
    guard accessToken != "TWILIO_ACCESS_TOKEN" else {
        let message = "Failed to fetch access token"
        print( message)
        return
    }
    // Prepare local media which we will share with Room Participants.
    self.prepareLocalMedia()
    
    // Preparing the connect options with the access token that we fetched (or hardcoded).
    let connectOptions = ConnectOptions(token: accessToken) { (builder) in
        
        // The name of the Room where the Client will attempt to connect to. Please note that if you pass an empty
        // Room `name`, the Client will create one for you. You can get the name or sid from any connected Room.
        builder.roomName = self.callRoomDetail.chatRoomName
        
        // Use the local media that we prepared earlier.
        if let audioTrack = self.localAudioTrack {
            builder.audioTracks = [ audioTrack ]
        }
        
        if let videoTrack = self.localVideoTrack {
            builder.videoTracks = [ videoTrack ]
        }
        
        
        // Use the preferred audio codec
        if let preferredAudioCodec = Settings.shared.audioCodec {
            builder.preferredAudioCodecs = [preferredAudioCodec]
        }
        
        // Use the preferred video codec
        if let preferredVideoCodec = Settings.shared.videoCodec {
            builder.preferredVideoCodecs = [preferredVideoCodec]
        }
        
        // Use the preferred encoding parameters
        let videoCodec = Settings.shared.videoCodec ?? Vp8Codec()!
        let (encodingParams, _) = ReplayKitVideoSource.getParametersForUseCase(codec: videoCodec,
                                                                                          isScreencast: true,
                                                                                       telecineOptions:ReplayKitVideoSource.TelecineOptions.p60to24or25or30)

        builder.encodingParameters = encodingParams

        // Use the preferred signaling region
        if let signalingRegion = Settings.shared.signalingRegion {
            builder.region = signalingRegion
        }
        
        builder.isAutomaticSubscriptionEnabled = true
        
        builder.isNetworkQualityEnabled = true
        builder.networkQualityConfiguration = NetworkQualityConfiguration(localVerbosity: .minimal,
                                                                          remoteVerbosity: .minimal)
        
    }
    
    // Connect to the Room using the options we provided.
    room = TwilioVideoSDK.connect(options: connectOptions, delegate: self)
    print( "Attempting to connect to room \(self.callRoomDetail.chatRoomName ?? ""))")
    
    self.showRoomUI(inRoom: true)
}

您可以从 twilio 存储库获取 ReplayKitVideoSource 文件和其他文件 https://github.com/twilio/video-quickstart-ios/tree/master/ReplayKitExample

关于swift - 在 iOS 中使用 Twilio 进行屏幕共享,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64416384/

相关文章:

swift - 使用 Swift 和 Perfect 的亚马逊 AWS SDK?

swift - 动态 scrollView contentSize autoLayoutConstraints swift

objective-c - OS X 中跨进程通信的首选方法是什么?

Imageview 在运行时更改位置 - Swift

每个用户的 twilio 多个同时对话

ios - TwilioChatClientDelegate 应该由父级还是子级遵守?

ios - SpriteKit : How to stop actions with removeAllActions immediately

twilio - Rocket.Chat 无法接收来自 Twilio 的短信。 (Twilio 的调试器 : HTTP retrieval failure)

twilio - 将 Twilio 调用移至 session 室

Twilio 未检测到来自 Skype 的 DTMF 音