跳到内容
Pika
Esc
导航打开⌘J预览
本页内容

工作原理

为什么 Pika 必须拆成 GNOME Shell 扩展和独立录制进程两半,两者如何通过 D-Bus 通信,门户采集与 GStreamer 编码管线是怎么搭起来的。

为什么是两个进程

Pika 由 GNOME Shell 扩展和一个独立的录制进程组成。这个划分不是可选的, 两个方向的约束各自成立:

界面必须在 Shell 里。 Wayland 协议没有浮层和窗口定位能力 —— 官方 wayland-protocols 里没有 layer-shell 类协议,Mutter 也拒绝实现 wlr-layer-shell。实时选区遮罩、录制取景框、顶栏指示器,普通应用一个都画不出来。

编码绝不能在 Shell 里。 GJS 是单线程的,和合成共用一个主循环 —— 在里面跑 H.264 整个桌面会掉帧。GNOME 自己也是这么分的 (gnome-shell + org.gnome.Shell.Screencast)。

结果是录制进程没有任何窗口,连设置和关于都在扩展的 prefs.js 里 (那是跑在独立进程的 GTK4,卡了也卡不到桌面)。

两半怎么说话

扩展调用录制进程的 D-Bus 接口 io.github.hungtcs.Pika; 录制进程需要选区时反过来调扩展的 io.github.hungtcs.PikaShell

用方法调用而不是信号,是因为信号是广播、没有回执 —— 拿不到错误, 也没法触发按需启动。

录制进程通过 D-Bus 激活按需拉起,用户不需要手动启动任何东西。 激活文件里的 SystemdService= 是有讲究的:xdg-desktop-portal 靠 systemd 单元名反推应用 ID,而门户的授权记忆是按应用 ID 存的。少了这一行, 进程会落进调用方的 cgroup,门户认不出它,结果就是每次录制都重新弹授权框。

采集

采集走 org.freedesktop.portal.ScreenCast。门户返回的不是图像数据, 而是一个 PipeWire node ID 加一个 fd

授权令牌持久化在 $XDG_STATE_HOME/pika/screencast-restore-token, 避免每次弹窗。用户随时可以撤销,所以每条采集路径都有重新申请的兜底。

区域录制其实是「采整块屏 + 裁剪」 —— 门户不支持只采一块区域。

编码管线

pipewiresrc → queue → [videocrop] → vapostproc/videoconvert → 编码器 → h264parse
            → mp4mux → filesink
  • 编码器按 vah264lpencvah264encx264encopenh264enc 顺序探测, 前两个是 VA 硬编。
  • 有音频时并入 audiomixer → audioconvert → audioresample → AAC → mux.audio_0。 即使只有一路来源也走 mixer —— 它会用静音填补空隙,麦克风掉线不会让时间轴缩短。
  • 停止必须走 EOS 而不是直接关闭 —— mp4mux 要靠 EOS 才会写完索引。 分片模式是保底:被外部掐断时文件仍然可播。

配置怎么共享

io.github.hungtcs.Pika.gschema.xml 是唯一事实来源,构建时分别拷进扩展目录和 应用自己的 schema 目录。

必须拷两份,是因为扩展跑在宿主 Shell 里、应用(将来)跑在沙箱里, 两边看不见对方的文件系统。schema 只是元数据,真正的数据在 dconf 里 —— 那是通的。 所以两份的 idpath 逐字一致。

最后更新于 2026年8月22日

这个页面有帮助吗?