You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS下使用PJSIP库自定义视频通话视图求助(仿WhatsApp布局)

实现iOS PJSIP类似WhatsApp的视频通话布局

要实现远程视频全屏显示、本地视频以小窗口悬浮右侧的布局,仅通过硬编码尺寸调用pjsua_vid_win_set_size无法满足需求,需要区分本地/远程窗口、动态适配屏幕并调整层级,具体实现步骤如下:

1. 区分本地预览与远程视频窗口

  • 远程视频窗口ID:在通话媒体状态激活的回调(如on_call_media_state)中,通过pjsua_call_get_vid_win获取。
  • 本地预览窗口ID:调用pjsua_vid_preview_start启动本地摄像头预览时,会返回对应的窗口ID。

2. 设置远程视频窗口全屏显示

动态获取当前屏幕的安全区尺寸,将远程窗口铺满整个屏幕:

// 获取屏幕及安全区参数
let screenBounds = UIScreen.main.bounds
let safeAreaInsets = UIApplication.shared.windows.first?.safeAreaInsets ?? .zero

// 构造全屏尺寸
let fullSize = pjmedia_rect_size()
fullSize.w = UInt32(screenBounds.width)
fullSize.h = UInt32(screenBounds.height - safeAreaInsets.top - safeAreaInsets.bottom)

// 设置远程窗口位置(从安全区顶部开始,左上角原点)
let remoteWinPos = pjmedia_rect()
remoteWinPos.x = 0
remoteWinPos.y = UInt32(safeAreaInsets.top)
remoteWinPos.size = fullSize
pjsua_vid_win_set_pos(remoteWid, &remoteWinPos)

3. 设置本地小窗口悬浮右侧

将本地窗口设为固定小尺寸,放置在屏幕右下角(避开安全区):

// 定义本地窗口尺寸(按16:9比例,宽度为屏幕1/3)
let localWidth = UInt32(screenBounds.width / 3)
let localHeight = UInt32(localWidth * 9 / 16)
let localSize = pjmedia_rect_size(w: localWidth, h: localHeight)

// 计算本地窗口位置:右下角预留边距,避开底部安全区
let localPos = pjmedia_rect()
localPos.x = UInt32(screenBounds.width - localWidth - 16) // 右侧留16pt边距
localPos.y = UInt32(screenBounds.height - localHeight - safeAreaInsets.bottom - 16) // 底部留边距+安全区
localPos.size = localSize

// 应用本地窗口的位置与尺寸
pjsua_vid_win_set_pos(localWid, &localPos)

4. 确保本地窗口在顶层

通过层级设置让本地小窗显示在远程视频之上:

// 数值越大层级越高,确保本地窗口层级高于远程
pjsua_vid_win_set_zorder(localWid, 1)
pjsua_vid_win_set_zorder(remoteWid, 0)

关键注意事项

  • 禁止硬编码尺寸:不同iOS设备屏幕尺寸、安全区差异大,必须动态获取屏幕参数。
  • 监听屏幕旋转:若支持横屏,需在屏幕旋转回调中重新计算并更新两个窗口的位置与尺寸。
  • 权限与初始化:确保已获取摄像头、麦克风权限,且PJSIP视频模块已正确启用初始化。

内容的提问来源于stack exchange,提问作者Shital Bhikhadiya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 11:22:28