拓冰建站拓冰建站
首页 / 资讯中心 / 正文

niri 录屏(Screencasting)实战指南:Portal/PipeWire 采集、窗口遮挡、动态采集目标与镜像

niri 录屏Screencasting实战指南Portal/PipeWire 采集、窗口遮挡、动态采集目标与镜像【免费下载链接】niriA scrollable-tiling Wayland compositor.项目地址: https://gitcode.com/GitHub_Trending/ni/niri本指南围绕 niri一款可滚动平铺的 Wayland 合成器的录屏功能展开系统讲解如何通过 xdg-desktop-portal 与 PipeWire 对显示器或单个窗口进行采集并深入介绍block-out-from窗口/图层遮挡规则、25.05 引入的动态采集目标Dynamic Cast Target、is-window-cast-target采集指示、窗口化全屏windowed fullscreen以及输出镜像等专为录屏场景设计的特性。读完本文你将能够配置一套既能录屏、又能保护敏感窗口的完整 niri 录屏方案并理解其底层ScreenCast D-Bus 协议 PipeWire 流是如何工作的。录屏的两种主流方式niri 主要的录屏接口走Portal PipeWire这条标准链路并且已经得到 OBS、Firefox、Chromium、Electron、Telegram 等大量应用的开箱支持。你可以采集整个显示器也可以只采集某个单独的窗口。要使用它需要满足以下运行条件一个可用的 D-Bus 会话已安装并运行 PipeWire已安装xdg-desktop-portal-gnomeniri 以会话方式运行即通过niri-session或显示管理器启动参见 Getting-Started。在主流发行版上这些依赖通常开箱即用。除了 Portal 方式niri 也支持依赖wlr-screencopy协议的第三方工具例如许多截图/录屏小工具因此选择面很广。从源码结构看这条链路的实现集中在 src/screencasting/mod.rsScreencasting结构体维护casts正在进行的采集、pending_dynamic_casts等待首个目标的动态采集、mapped_cast_output每个已映射窗口对应的输出以及pipewire实例。Portal 端的请求通过 mutter 的 ScreenCast D-Bus 协议src/dbus/mutter_screen_cast.rs以ScreenCastToNiri::StartCast/StopCast消息进入on_screen_cast_msg随后 niri 初始化 GBM 设备与渲染格式、启动 PipeWire 流并在每个帧周期通过render_for_screen_cast整屏采集或render_windows_for_screen_cast单窗口采集把渲染元素送往采集缓冲区。从录屏中遮挡窗口block-out-from录屏演示时你可能不希望密码管理器、聊天窗口等内容出现在画面里。niri 提供block-out-from窗口规则把被匹配到的窗口在录屏中替换为纯黑色矩形。// 将密码管理器从录屏中遮挡掉。 window-rule { match app-idr#^org\.keepassxc\.KeePassXC$# match app-idr#^org\.gnome\.World\.Secrets$# block-out-from screencast }同样的思路也适用于 layer-shell 表面比如通知弹窗只需改用图层规则// 将 mako 的通知从录屏中遮挡掉。 layer-rule { match namespace^notifications$ block-out-from screencast }在配置解析层面block-out-from对应的值由 niri-config/src/appearance.rs 中的BlockOutFrom枚举定义目前支持两个取值screencast仅从 xdg-desktop-portal 录屏中遮挡screen-capture从所有屏幕捕获中遮挡包括第三方截图工具。Configuration:-Window-Rules.md 对这两种取值做了更详细的对比screencast不会影响第三方截图工具——如果你在录屏过程中打开了带预览的截图工具被遮挡的窗口仍会出现在录屏里。niri 内置的交互式截图 UI 不受此问题影响录屏时打开截图 UI你仍能看到所有窗口并正常框选区域而录屏画面上截图选区 UI 会以窗口被遮挡的状态呈现。screen-capture会额外把窗口从第三方面截图中也遮挡掉避免录屏时误开截图预览导致敏感内容泄露的尴尬它仍然允许使用内置的交互式截图 UI但会自动屏蔽screenshot-screen、screenshot-window这类全自动截图动作——因为交互式框选时你可以自行避开敏感内容。调试这类规则时可以利用配置中 debug 段的preview-render选项来预览遮挡效果。[!CAUTION] 请小心基于动态变化的窗口标题来做遮挡。例如下面这个遮挡 Firefox 的 Gmail 标签页的写法window-rule { // 并不能完美工作尝试遮挡 Gmail 标签页。 match app-idfirefox$ title- Gmail block-out-from screencast }它虽然能生效但从敏感标签页切回普通标签页的瞬间敏感标签页的内容仍会在录屏上闪现一瞬。原因在于 Wayland 协议中窗口标题以及 app-id不是双缓冲的无法与特定窗口内容严格绑定Firefox 也没有可靠手段让可见标签页切换与标题变更完全同步。动态采集目标Dynamic Cast Target自 25.05 起提供niri 提供一个可以动态切换内容的特殊录屏流它在录屏窗口选择对话框中显示为 niri Dynamic Cast Target。选择它之后再用下面的绑定键来切换它展示的内容set-dynamic-cast-window采集当前聚焦的窗口set-dynamic-cast-monitor采集当前聚焦的显示器clear-dynamic-cast-target重置为空白视频流。注意在你做出第一次目标选择之前该视频流不会启动保持空流。也可以从命令行触发这些动作例如配合pick-window交互式挑选要采集的窗口$ niri msg action set-dynamic-cast-window --id $(niri msg --json pick-window | jq .id)从实现上看src/screencasting/mod.rsniri 会为 Portal 端合成一个特殊的窗口 IDdynamic_cast_id_for_portal当 ScreenCast 请求落在该 ID 上时请求不会立即启动而是进入pending_dynamic_casts队列等待首个目标set_dynamic_cast_target会把目标CastTarget::Window/CastTarget::Output/CastTarget::Nothing应用到所有动态采集流上并据目标输出刷新率同步调整流的 FPS。行为细节如下如果采集目标消失例如目标窗口被关闭视频流会自动回到空白所有动态采集共享同一个目标但新建的动态采集会从空白开始直到你下一次显式切换目标这是为了避免新会话一上来就意外共享敏感内容从源码可以推断动态采集在目标缺失/输出断开时不会像普通采集那样直接停止而是切回Nothing状态等待下次切换见stop_casts_for_target中 We dont stop dynamic casts, instead we switch them to Nothing 的注释。标记正在被采集的窗口自 25.02 起提供is-window-cast-targettrue窗口规则详见 Configuration:-Window-Rules.md用于匹配正处于窗口采集目标的窗口。典型用法是给它配上醒目的边框/阴影颜色让观众一眼看出哪些窗口正在被录屏例如// 用红色系标记正在被采集的窗口。 window-rule { match is-window-cast-targettrue focus-ring { active-color #f38ba8 inactive-color #7d0d2d } border { inactive-color #7d0d2d } shadow { color #7d0d2d70 } tab-indicator { active-color #f38ba8 inactive-color #7d0d2d } }需要注意它的适用范围对动态采集Dynamic Cast Target锁定的窗口同样生效对仅仅恰好显示在整屏采集画面里的窗口不生效——只有被显式指定为窗口采集目标时才会被标记。底层支撑在Niri::refresh_mapped_cast_window_rulessrc/screencasting/mod.rs每当采集列表变化时niri 会遍历所有映射窗口检查是否存在CastTarget::Window { id }与之匹配并把结果写入mapped.set_is_window_cast_target(...)供渲染与规则匹配阶段使用。窗口化伪/分离全屏自 25.05 起提供录屏基于浏览器的演示如 Google Slides时通常希望隐藏浏览器 UI这往往要求浏览器进入全屏。但全屏并不总是方便比如你用的是超宽屏显示器或者只想让浏览器保持一个小窗口、不想占满整块屏幕。toggle-windowed-fullscreen绑定键就是为此设计的它告诉应用你已经全屏了但实际上窗口仍是普通窗口你可以随意调整大小、放到任意位置。binds { ModCtrlShiftF { toggle-windowed-fullscreen; } }需要注意并非所有应用都会响应全屏请求所以有时按下绑定键看起来什么都没发生——这属于应用侧的行为差异而非 niri 的问题。屏幕镜像Screen Mirroring做演示时把一块输出镜像到另一块输出往往很有用。niri 目前没有内置输出镜像但可以借助第三方工具wl-mirror把某块输出镜像到一个窗口里。下面这条绑定还依赖jq命令binds { ModP repeatfalse { spawn-sh wl-mirror $(niri msg --json focused-output | jq -r .name); } }操作流程聚焦想要镜像的那块输出按下ModP把弹出的wl-mirror窗口移动到目标输出将该窗口全屏默认是ModShiftF。小结与建议配置把上述特性组合起来你可以得到一套完整的 niri 录屏配置// 遮挡敏感窗口与通知。 window-rule { match app-idr#^org\.keepassxc\.KeePassXC$# block-out-from screencast } layer-rule { match namespace^notifications$ block-out-from screencast } // 标记正在被采集的窗口。 window-rule { match is-window-cast-targettrue border { inactive-color #7d0d2d } shadow { color #7d0d2d70 } } binds { // 演示浏览器内容时隐藏浏览器 UI。 ModCtrlShiftF { toggle-windowed-fullscreen; } // 动态采集目标。 ModCtrlC { set-dynamic-cast-window; } ModCtrlM { set-dynamic-cast-monitor; } ModCtrlX { clear-dynamic-cast-target; } // 输出镜像。 ModP repeatfalse { spawn-sh wl-mirror $(niri msg --json focused-output | jq -r .name); } }更完整的规则说明与示例可继续参阅 Configuration:-Window-Rules.md 与 Configuration:-Layer-Rules.md关于录屏实现细节流管理、尺寸/刷新率同步、光标合成等可深入阅读 src/screencasting/mod.rs。【免费下载链接】niriA scrollable-tiling Wayland compositor.项目地址: https://gitcode.com/GitHub_Trending/ni/niri创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门