一个好用的、纯软件的扩展屏方案 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
kuanat
V2EX    分享发现

一个好用的、纯软件的扩展屏方案

  •  
  •   kuanat 2024-06-03 23:10:59 +08:00 2421 次点击
    这是一个创建于 493 天前的主题,其中的信息可能已经有所发展或是发生改变。

    起因是 /t/1044916 这个帖子,我原本认为这个方法会在开发者群体里很普遍,结果问了一圈才发现几乎没人用。我在 B 站也尝试搜索了一下,没有看到类似的用法,所以就有了这个帖子。

    1. 这个方案解决了什么问题

      • 外出环境需要扩展副屏,用于临时多屏提高效率或者展示

      • 老旧平板废物利用

    2. 这个方案的优点在哪里

      • 只依赖开源软件,免费可信。无需采集卡、或者商业软件

      • 无需物理连线,任何手机、平板都可以作为副屏

      • 可扩展的屏幕数量没有上限,不需要 HDMI 欺骗头

      • 可以自定义输出的分辨率,主动匹配显示设备( HDMI 欺骗头也可以通过重写 EDID 来实现,但不如软件方便)

      • 支持低功耗(远程桌面)和低延迟(串流)模式,在移动办公场景,远程桌面模式几乎不会带来功耗增加

      • 支持副屏单独操作副屏的窗口,不影响主机操作( multi-seat 或者多焦点,这个功能仅限 Linux 主机)

    3. 实现原理

      原理简单说分两部分,一部分是传统的 vnc/rdp/sunshine 软件,前两者是远程桌面模式,后者是串流模式。

      由于单纯的远程桌面、串流都需要先有一个桌面,属于镜像模式,对于“扩展屏”的场景来说没有帮助。所以第二个部分就是如何增加一个虚拟的桌面。

      之前的方法是 HDMI 欺骗头,这样就只能输出一个副屏。软件的方法如下:

      • Windows 使用 Virtual-Display-Driver 也有其他的实现可以用

      • Linux 目前有 X11/wayland 两个显示框架,X11 有 xvfb/xrdp 可以用,我很久都没用过 X11 了,所以这两个仅供参考,但是 X11 的支持是没什么问题的。

        Wayland 的话 KDE/KWin 是不行的。Gnome/Mutter 在 42 版本为了自家 rdp 应用增加了一个功能,可以创建一个虚拟桌面,这个 rdp 应用可以把这个虚拟显示器作为后端。wlroots 的实现 sway/hyprland 都支持直接创建。

      • macOS 我不知道……我主动远离苹果生态很久了。欢迎补充。

      剩下的事情就顺理成章了,让 vnc/rdp/sunshine 跑在这个虚拟显示器就可以。

      这样就可以根据显示设备的分辨率,创建一个虚拟显示器。平板手机连接对应的 vnc/rdp/moonlight 即可点对点显示。

    4. 实现原理续

      远程桌面模式需要实际测试一下 vnc/rdp/moonlight 客户端。

      以 Android 平板上的 vnc 客户端为例,如果需要在平板上滑动屏幕,实现显示区域里的浏览器窗口滚动,就需要这个 vnc 客户端将平板的输入映射为鼠标滚轮(或者手势)传递给 vnc 服务器端。不是所有的客户端都实现了类似的功能。

      Sway wm 环境还可以使用 seat 的功能对输入进行分组。vnc 服务器端会创建虚拟的鼠标、键盘或者触摸板输入设备,当客户端有输入传入时,相应指令就会通过虚拟设备发送给系统。

      这样能够实现实现:主机和触摸屏有两组输入焦点,副屏由于物理限制只能使用副屏桌面的应用。这对于演示场景非常有用,展示应用在副屏,客户还可以通过触屏实际体验。而主屏幕任何操作都不会受影响。

    5. 额外补充

      如果需要非常低的延迟,优选 sunshine/moonlight 的串流模式。由于现在的 cpu 普遍有硬件编码器,而平板作为播放器又都有硬件解码器,这个功能对于平板几乎没有硬件限制,十年前能硬解 h264 的即可,稍微新一点的硬件都可以利用上 hevc/av1 方案。

      实测下来,1080p60~10Mbps 大概硬件编码器功耗在 0.8W 左右,虽然比较低,但是会导致 cpu 一直后台处理网络功能,无法进入低功耗状态,所以只推荐固定场景有外接电源时使用。

      相对来说,vnc/rdp 模式更适合静态展示或者终端应用,这一类都是基于画面变化传输数据,对于功耗续航的影响很小,开手机热点即可快速建立连接。

      外出组网,方便的是手机开热点,然后笔记本和平板都连接热点。如果是笔记本开热点需要手动设置,一个频段上网,另一个频段共享。反过来平板开热点,平板有可能访问不到在热点子网里的笔记本。

    6. 使用指南

      这里就以我用的 sway/wayvnc 做个说明,其他的根据自己情况调整即可。需要做的就是两件事,创建虚拟输出,然后把输出投屏出去。图我就不放了,大家脑部一下效果就好。

    # 创建虚拟输出 swaymsg create_output # 由于目前 wlroots 实现,这个输出的名字默认为 HEADLESS-1 ,继续创建则为 HEADLESS-2 以此类推 # 可以在 sway config 中预定义其输出参数,也可以通过 IPC 手动调整 # 在 (2560,0) 位置创建 1920x1200 的虚拟显示器 swaymsg output HEADLESS-1 mode 1920x1200 pos 2560,0 # 启动 vnc 服务端并将 HEADLESS-1 作为显示后端,设定监听入口 wayvnc --output=HEADLESS-1 0.0.0.0 5900 # 如果需要单独输入设备为单独 seat # 目前 wayvnc 不支持直接创建 seat ,所以需要先创建 seat1 来占位,系统默认的是 seat0 swaymsg seat seat1 attach PLACEHOLDER # 将 wayvnc 输入设备绑定到 seat1 wayvnc --output=HEADLESS-1 --seat=seat1 0.0.0.0 5900 # 临时切断副屏输出 swaymsg output HEADLESS-1 toggle # 反正用 sway 的基本都有自己的自动化逻辑,这一整套可以完全自定义 
    2 条回复    2024-06-04 22:45:38 +08:00
    swordsmile
        1
    swordsmile  
       2024-06-04 20:36:34 +08:00
    如果是 Hyprland ,如何创建虚拟 seat 呢
    kuanat
        2
    kuanat  
    OP
       2024-06-04 22:45:38 +08:00
    @swordsmile #1

    Hyprland 目前还不支持 multi-seat 功能 https://github.com/hyprwm/Hyprland/issues/1731

    这也是我一直主用 sway 的原因。其他方面 hyprland 易用性好太多了,不得已我还给 sway 写了个简陋的 master stack 布局管理器……

    另外还有些 layer-shell 协议的应用(悬浮显示状态、通知和关机菜单这一类)也是硬编码了 seat0 的,有可能会导致显示位置或者输入焦点异常。对我影响比较大的是 tofi (一个 wofi 的改版)会有输入焦点问题。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     940 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 18:56 PVG 02:56 LAX 11:56 JFK 14:56
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86