iOS集成WebRTC时RTCMTLVideoView无画面问题排查求助
我正在iOS应用中集成WebRTC视频功能,已从官方渠道下载源码并成功编译。因该版本不支持GLView,改用MetalKit引入RTCMTLVideoView,同时实现了RTCVideoRenderer与RTCVideoViewDelegate并设置self.metalVideoView.delegate = self。
收到视频时,通知对象显示为RTC_OBJC_TYPE(RTCMediaStreamTrack): video janusv0 enabled Live,且VideoTracks数量为1,但屏幕仅显示空白画面。此前用GLView时相同逻辑可正常运行。
以下是处理视频接收的代码:
@objc func handleFloorPlanVideoReceived(_ notification: Notification?) { if let remoteVideoTrack = notification?.object as? RTCVideoTrack { print("Recieved Remote Video: \(remoteVideoTrack)") DispatchQueue.main.async { // Initialize the metalVideoView self.metalVideoView = RTCMTLVideoView(frame: CGRect.zero) self.metalVideoView.delegate = self // Add the metalVideoView to the view hierarchy self.view.addSubview(self.metalVideoView) self.metalVideoView.backgroundColor = .edgeGray self.metalVideoView.videoContentMode = .scaleAspectFit // Set up auto layout constraints self.metalVideoView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ self.metalVideoView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor), self.metalVideoView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor), self.metalVideoView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor), self.metalVideoView.heightAnchor.constraint(equalTo: self.view.heightAnchor, multiplier: 1.0/3.0) ]) remoteVideoTrack.add(self.metalVideoView) // Create and add the UIActivityIndicatorView let activityIndicator = UIActivityIndicatorView(style: .large) activityIndicator.color = .white self.metalVideoView.addSubview(activityIndicator) self.activityIndicator = activityIndicator // Set up constraints for the activity indicator activityIndicator.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ activityIndicator.centerXAnchor.constraint(equalTo: self.metalVideoView.centerXAnchor), activityIndicator.centerYAnchor.constraint(equalTo: self.metalVideoView.centerYAnchor) ]) activityIndicator.startAnimating() // Create and add the close button let closeButton = UIButton(type: .system) if let closeImage = UIImage(systemName: "xmark") { closeButton.setImage(closeImage, for: .normal) } self.metalVideoView.addSubview(closeButton) // Set up constraints for the close button closeButton.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ closeButton.topAnchor.constraint(equalTo: self.metalVideoView.topAnchor, constant: 8), closeButton.trailingAnchor.constraint(equalTo: self.metalVideoView.trailingAnchor, constant: -8) ]) // Add target for close button tap event closeButton.addTarget(self, action: #selector(self.closeButtonTapped), for: .touchUpInside) self.metalVideoView.setNeedsLayout() } } }
避免重复创建视图实例:当前每次收到视频通知都会重新初始化
metalVideoView,会导致之前的渲染上下文被重置。建议提前在viewDidLoad等生命周期方法中创建好metalVideoView并添加到视图层级,仅在收到视频轨道时执行remoteVideoTrack.add(self.metalVideoView)。补全RTCVideoViewDelegate方法:必须实现
videoView:didChangeVideoSize:方法,该回调会触发视图根据视频尺寸调整渲染逻辑,缺失可能导致画面无法显示:func videoView(_ videoView: RTCMTLVideoView, didChangeVideoSize size: CGSize) { // 可选:根据视频尺寸更新视图约束或布局 }验证视频帧接收:在
RTCVideoRenderer的renderFrame:方法中添加日志,确认是否有视频帧传入:func renderFrame(_ frame: RTCVideoFrame?) { guard let frame = frame else { return } print("收到视频帧:分辨率\(frame.width)x\(frame.height)") }移除冗余布局调用:
self.metalVideoView.setNeedsLayout()在Auto Layout约束激活后是多余的,系统会自动处理布局更新,可删除该代码。检查线程安全:确保所有与
RTCMTLVideoView相关的操作都在主线程执行(当前代码已通过DispatchQueue.main.async处理,这部分符合要求)。
内容的提问来源于stack exchange,提问作者Sergey Z

