腾讯会议 (wemeet) Wayland 屏幕共享修复记录
日期:2026-09-07
环境:Arch Linux + niri (Wayland/scrollable-tiling) + AMD Ellesmere 双屏
软件:wemeet-bin 3.26.10.401-1 + xdg-desktop-portal 1.22.1 (main) + xdg-desktop-portal-wlr 0.8.2
1. 问题现象
在 niri Wayland 环境下,腾讯会议无法正常共享屏幕:
- GNOME portal 路径(
niri-portals.conf指向 gnome 后端):共享后黑屏(无视频流) - wlr portal 路径(指向 xdg-desktop-portal-wlr):点击共享后弹出显示器选区后无反应,6 秒后自动重试
2. 根因分析
2.1 直接根因:wemeet 客户端 D-Bus 竞态 bug
wemeet 的定制模块 libscreen_share_module.so 存在异步调用链缺陷:
1 | 规范要求的正确顺序: wemeet 实际执行: |
Start 的调用被直接放在 SelectSources 发出之后,没有等待其 Response 信号;只有更后面的 OpenPipeWireRemote 正确地放在了 onStartResponse 回调中。这是一个依赖竞态条件的未定义行为。
2.2 为什么 GNOME 能用而 wlr 不能用
| Portal 后端 | SelectSources 行为 | 结果 |
|---|---|---|
| gnome | 立即返回,在 Start 中才弹窗等待用户选显示器 | 掩盖了 wemeet 的竞态缺陷 → 流程跑通(但 AMD 下黑屏另有颜色格式问题) |
| wlr | 同步阻塞调用 slurp 等待用户选显示器 | Start 提前到达时 SelectSources 尚未完成 → 必然失败 |
2.3 证据链
- 后端三层验证全部通过:直连 XDPW impl(node 86)、主 portal 路由(node 75)、wemeet 精确参数复现
persist_mode=1, app_id=''(node 75)——排除 portal 后端问题 - wemeet 14:04:03 发起 CreateSession(1_1822/wemeet1) + SelectSources,14:04:05 SelectSources 成功(选定 HDMI-A-2),但 XDPW 从未收到 start method invoked,14:04:11(恰 6 秒后)会话关闭并重试——对应客户端超时逻辑
- 用
dbus-monitor(Request 接口)+journalctl -v建立的 4 通道监控确认:问题在 wemeet 客户端侧,非路由层
3. 修复方案
采用社区逆向补丁 Matheritasiv/wemeet-screenshare-patch,该补丁精确针对 wemeet v3.26.10.401(与本地 wemeet-bin 3.26.10.401-1 完全匹配)。
3.1 应用补丁(仅 Hunk 0,修复 Start 竞态)
补丁含三个 Hunk:
- Hunk 0(必需):将
dbusStart()从dbusSelectSources()中移到onSelectSourcesResponse()回调 → 修复异步链 - Hunk 1a/1b(颜色格式 hook,AMD + force_mod_linear 场景不需要):当前系统已用
force_mod_linear=1解决颜色问题,按补丁作者说明跳过(否则需要额外 LD_PRELOAD hook 且可能颜色错误)
1 | # 1. 下载补丁:https://raw.githubusercontent.com/Matheritasiv/wemeet-screenshare-patch/main/patch.py |
应用结果:
1 | [PATCH] 0x0043d2fa: 00 => 5d |
3.2 恢复 wlr 显示器选择界面
调试期间为绕过竞态,曾将 wlr 配置改为 chooser_type=none + output_name=HDMI-A-2(固定输出、跳过 slurp)。补丁生效后需移除这两行以恢复选区界面:
1 | # ~/.config/xdg-desktop-portal-wlr/config |
1 | systemctl --user restart xdg-desktop-portal-wlr |
3.3 重启 wemeet
必须完全退出 wemeet 进程再重新启动(运行中的进程仍持有旧库的内存映射,补丁只对磁盘文件生效)。
4. 修复后行为
- 点击”共享屏幕” → 弹出 slurp 显示器选择界面 ✓
- 选定显示器 → 正常出画面 ✓
- 双屏(HDMI-A-1 / HDMI-A-2)均可选 ✓
5. 回滚方法
1 | sudo cp /opt/wemeet/bin/modules/screen_share/libscreen_share_module.so.bak.20260907 \ |
6. 注意事项
- 包升级后需重新打补丁:
wemeet-bin更新后库文件被覆盖,需重新执行第 3 节步骤(先 dry-run 确认新版本字节仍匹配;若补丁作者未跟进新版本,需等待其更新) - 只打 Hunk 0 无需 LD_PRELOAD hook:补丁 README 明确说明,仅当需要颜色转换(Hunk 1a/1b)时才需
export LD_PRELOAD=.../libhook.so - 快捷操作:完整打补丁命令(含下载)
1 | export https_proxy=http://10.255.254.153:7890 # 若需代理 |
参考
- 补丁项目:https://github.com/Matheritasiv/wemeet-screenshare-patch
- xdg-desktop-portal ScreenCast 规范:https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.ScreenCast.html
- niri 黑屏背景:niri PR #1791(SHM 回退)未合并