前言
作为开发者或极客,我们总觉得屏幕不够用。虽然市面上有不少便携显示器,但手边的 iPad、安卓平板甚至大屏手机其实就是一块绝佳的屏幕。
常见的将平板作为电脑副屏的方案(如 VNC、Deskreen)通常存在以下痛点:
- 延迟高:鼠标移动有明显的'飘'感。
- 画质差:压缩痕迹严重,看文字累眼。
- 收费:好用的商业软件(如 Duet Display)往往价格不菲。
- 只是镜像:很多方案只能镜像主屏,无法作为真正的扩展显示器使用。
本文将介绍一种低延迟、高画质、完全免费的'硬核'方案:利用开源游戏流媒体工具 Sunshine (服务端) 和 Moonlight (客户端),配合 NVIDIA 显卡 的虚拟显示技术,在 Linux (Ubuntu 24.04) 上'无中生有'地创造出一块虚拟屏幕,并将其流式传输到你的平板上。
核心优势:
- 极低延迟:基于主要用于云游戏的流媒体技术,局域网内延迟通常低于 10ms。
- 真·扩展屏:不是镜像,而是系统层面识别出的独立显示器,窗口可以拖过去。
- 纯软件实现:无需购买显卡欺骗器(Dummy Plug)等硬件。
方案原理
核心思路
- 虚拟显示器:利用 NVIDIA 驱动的特性,在 X11 系统中强制开启一个物理上不存在的显示接口(Virtual Display)。
- 桌面扩展:操作系统将这个虚拟接口识别为真实显示器,你可以在系统设置里排列它的位置。
- 定向推流:配置 Sunshine 仅捕获这个虚拟显示器的画面。
- 客户端接收:平板上的 Moonlight 连接 Sunshine,显示画面并回传触摸/鼠标操作。
为什么选择 Sunshine + Moonlight?
Sunshine 是 NVIDIA GameStream 协议的开源实现。相比 VNC 等远程桌面协议,它利用 GPU 进行硬件编码(NVENC),效率极高,专为对延迟极度敏感的游戏场景设计,用来做桌面扩展简直是'降维打击'。
环境与硬件要求
本教程基于以下笔记本环境进行配置:
- 操作系统: Ubuntu 24.04 LTS (使用 X11 窗口系统,暂不推荐 Wayland)
- 显卡配置: 双显卡笔记本
- iGPU: Intel Iris Xe (负责内屏 eDP)
- dGPU: NVIDIA RTX 3060 (负责外接 HDMI/DP)
- 显示设备:
- 笔记本自带屏幕 (eDP-1)
- 物理外接显示器 (HDMI-1-0)
- 目标: 新增一个虚拟显示器 (DP-1-0) 推流给平板
- 客户端设备: 华为平板 (HarmonyOS 6.0) 、小米 pad5 pro 或任意安装 Moonlight 的设备
详细配置步骤
第一步:安装 Sunshine 和 Moonlight
- 客户端 (平板):
在应用商店下载 Moonlight Game Streaming,或者前往 Moonlight Android Github Releases 安装对应的
.apk文件。
服务端 (PC):
前往 Sunshine GitHub Releases 下载适用于 Ubuntu 24.04 的 .deb 包并安装:
sudo apt install ./sunshine_*.deb
安装后启动 Sunshine 服务:
systemctl --user start sunshine
systemctl --user enable sunshine
第二步:攻克双显卡难关 —— 配置 Xorg
这是最关键也最容易踩坑的一步。在双显卡笔记本上,通常 Intel 核显负责内屏,NVIDIA 独显负责外接口。我们需要强制 NVIDIA 驱动开启一个并没有连接真实显示器的端口。
我们需要修改或创建 /etc/X11/xorg.conf。
1. 准备 EDID 文件
显卡需要 EDID 信息才知道显示器支持什么分辨率。既然是虚拟显示器,我们可以'借用'现有显示器的 EDID。
假设你已经连接了一个 HDMI 显示器(可以通过 xrandr 查看名称,如 HDMI-1-0 或在 /sys/class/drm/ 下查找):
# 复制现有显示器的 EDID 到系统目录
sudo cp /sys/class/drm/card1-HDMI-A-1/edid /etc/X11/edid.bin
# 注意:路径中的 card1-HDMI-A-1 需根据你的实际情况调整,可能是 card0 或 card2
2. 编辑 /etc/X11/xorg.conf
备份原文件(如果有),然后写入以下配置。这段配置极其关键,请仔细阅读注释:
Section "ServerLayout"
Identifier "Layout0"
Screen 0 "Screen0"
# 定义第二个屏幕 Screen1,放在 Screen0 右边
Screen 1 "Screen1" RightOf "Screen0"
# 关键选项:允许 NVIDIA GPU 在有 Intel 核显的情况下独立管理屏幕
Option "AllowNVIDIAGPUScreens"
EndSection
Section "Device"
Identifier "intel"
Driver "modesetting"
# Intel 核显的总线 ID,使用 lspci | grep VGA 查看 (例如 00:02.0 对应 PCI:0:2:0)
BusID "PCI:0:2:0"
EndSection
Section "Device"
Identifier "nvidia"
Driver "nvidia"
# NVIDIA 独显的总线 ID (例如 01:00.0 对应 PCI:1:0:0)
BusID "PCI:1:0:0"
# 核心魔法:强制 NVIDIA 认为连接了两个显示器
# DFP-0 是真实的物理外接显示器 (如果没接外接屏,这里可能只需要配置虚拟的)
# DFP-1 是我们要伪造的虚拟显示器
Option "ConnectedMonitor" "DFP-0,DFP-1"
# 为虚拟显示器 DFP-1 指定我们刚才复制的 EDID 文件
Option "CustomEDID" "DFP-1:/etc/X11/edid.bin"
# 忽略 EDID 校验,允许强制设置分辨率
Option "ModeValidation" "DFP-1:AllowNonEdidModes,NoMaxPClkCheck"
EndSection
Section "Screen"
Identifier "Screen0"
Device "intel"
EndSection
Section "Screen"
Identifier "Screen1"
Device "nvidia"
EndSection
配置解析:
ConnectedMonitor: 欺骗驱动,让它以为特定端口上有显示器。CustomEDID: 赋予虚拟显示器'灵魂',让系统知道它支持什么分辨率(1080p, 2k 等)。
保存后,重启电脑。
第三步:验证虚拟显示器
重启后,打开终端输入 xrandr。
如果配置成功,你应该能看到一个新的输出端口(例如 DP-1-0 或 DP-0)显示为 connected,并且可以设置分辨率。
此时,在 Ubuntu 的'设置 -> 显示器'中,你应该能看到这块新屏幕,并可以调整它的位置。
第四步:配置 Sunshine 锁定虚拟屏
现在我们需要告诉 Sunshine:'不要录制整个桌面,只录制这块虚拟屏幕'。
- 打开 Sunshine Web 管理界面(通常是
https://localhost:47990)。 - 进入 Configuration -> Audio/Video。
- 找到 Output Name。这里不能随便填,需要填入系统的 Display ID。
如何查找正确的 Display ID?
查找方法如下。最准确的方法是查看 Sunshine 的日志。
在终端运行:
journalctl --user -u sunshine -f | grep "Detected display"
此时重启一下 Sunshine (systemctl --user restart sunshine),观察日志输出。你会看到类似这样的信息:
... Info: Detected display: eDP-1 (id: 0) connected: true ...
Info: Detected display: HDMI-1-0 (id: 1) connected: true ...
Info: Detected display: DP-1-0 (id: 4) connected: true
这里 DP-1-0 就是我们的虚拟显示器,它的 id 是 4。
- 修改 Sunshine 配置文件
~/.config/sunshine/sunshine.conf(或者在 Web UI 中设置):
[general]
# 刚才查到的 ID
output_name = 4
[video]
# 强制使用 X11 捕获模式,对虚拟显示器兼容性更好
capture = x11
[audio]
# 如果不需要平板发声,可以留空或配置 sink
# audio_sink =
第五步:调整屏幕布局 (xrandr)
为了让鼠标移动符合物理摆放,可以使用 xrandr 快速调整布局。
假设笔记本屏 (eDP-1) 在左,虚拟平板屏 (DP-1-0) 在中,外接显示器 (HDMI-1-0) 在右:
# 假设每个屏幕宽 2560
xrandr --output eDP-1 --pos 0x0 --output DP-1-0 --pos 2560x0 --output HDMI-1-0 --pos 5120x0
你可以将此命令保存为脚本,每次连接前运行。
连接与使用
- 平板连接 WiFi (建议 5GHz 频段)。
- 打开 Moonlight,搜索局域网主机。
- 点击连接,输入 PIN 码配对。
- 在应用列表中选择 Desktop。
此时平板即显示 Ubuntu 扩展桌面。
常见问题排查 (Troubleshooting)
Q1: Moonlight 报错 'Error 503' 或画面黑屏
- 原因: Sunshine 无法捕获指定的画面。
- 解法:
- 检查
output_name是否填错了 ID,显示接口的 ID 在重启后可能会变,务必看日志。 - 尝试将
capture模式改为x11(默认可能是 kms)。
- 检查
Q2: Sunshine 日志提示 'Couldn't find monitor'
- 原因: 配置文件里的显示器名称或 ID 不存在。
- 解法: 确保虚拟显示器在
xrandr中是connected状态。如果xrandr里都没有,说明xorg.conf配置失败。
Q3: 虚拟显示器分辨率不对/无法调整
- 原因: EDID 文件限制了分辨率。
- 解法: 使用
xrandr --addmode手动添加分辨率,或者在xorg.conf的ModeValidation中确保添加了AllowNonEdidModes。
Q4: 鼠标在平板上无法点击
- 原因: 权限问题或输入设备映射错误。
- 解法: 运行
sudo usermod -a -G input $USER确保当前用户有输入设备权限,重启生效。
删除配置
如果后续需要移除所有配置,可以执行以下步骤:
- 删除配置文件
# 删除 sunshine 配置
rm -f ~/.config/sunshine/sunshine.conf
# 删除 xorg.conf 和 EDID 文件
sudo rm -f /etc/X11/xorg.conf /etc/X11/edid.bin
# 停止 sunshine
systemctl --user stop sunshine
# 重启电脑
sudo reboot
- 卸载 sunshine
# 卸载 sunshine(保留配置文件)
sudo dpkg -r sunshine
# 卸载并删除所有配置文件
sudo dpkg -P sunshine
# 重启电脑
sudo reboot

