在现代软件开发中,自动化测试变得越来越重要,而录屏功能则为测试结果的验证提供了直观的方式。通过结合Selenium、Xvfb和FFmpeg这三个强大的工具,我们可以在服务器上实现无头(headless)的录屏环境,这对于没有图形界面的服务器尤其有用。

Selenium是一个自动化测试工具,它可以模拟用户对网页的操作,如点击、输入文本等。Xvfb(X虚拟帧缓冲)提供了一个虚拟的显示环境,使得我们可以在不需要实际显示器的情况下运行图形应用程序。FFmpeg是一个强大的多媒体框架,能够处理视频和音频的录制、转换和流式传输。

将这三个工具结合起来,我们可以创建一个自动化的录屏流程,这个流程可以在后台运行,录制Selenium驱动的浏览器会话。这样,无论是进行自动化测试验证,还是生成用户操作教程,都可以通过这种方式来实现。

例如,我们可以使用Selenium启动一个浏览器会话,然后用Xvfb创建一个虚拟的显示环境来捕获这个会话的屏幕。接着,使用FFmpeg开始录制屏幕内容,直到测试完成。这个过程完全自动化,可以集成到持续集成/持续部署(CI/CD)的流程中,提高开发效率和质量。

环境准备

  1. 安装软件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 安装浏览器
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
dpkg -i google-chrome-stable_current_amd64.deb

# 下载 chromedrive,选择合适的版本
# https://googlechromelabs.github.io/chrome-for-testing/
wget https://storage.googleapis.com/chrome-for-testing-public/123.0.6312.105/linux64/chromedriver-linux64.zip
unzip chromedriver-linux64.zip
mv chromedriver-linux64/chromedriver /usr/bin/

# 安装xvfb, ffmpeg
sudo apt install -y xvfb ffmpeg xrandr

# 安装selenium package
pip3 install selenium screeninfo # screeninfo 可以获取屏幕分辨率,为录屏做准备

Xvfb开启虚拟桌面

  1. 后台运行Xvfb开启虚拟桌面,终端将会默认在该桌面运行。此时能成功使用selenium控制浏览器
1
2
3
Xvfb -ac :99 -screen 0 1024x768x16 &
export DISPLAY=:99
xrandr
  1. 使用xvfb-run开户虚拟桌面
1
xvfb-run -a --server-args="-screen 0 1920x1080x24" xrandr # 在虚拟桌面下运行xrandr,运行完毕后,自动关闭桌面。可通过添加server参数 --server-args=" -displayID 99"指定display id.

-a : 自动使用不重复的DisplayId, 在运行的脚本中,可使用环境变量$DISPLAY来获取桌面ID,如:”:99”

使用selenium 控制浏览器

不同浏览器可设置不同的参数,以chrom浏览器为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 初始化driver
from selenium import webdriver
def local_chrome_driver():
option = webdriver.ChromeOptions()
option.add_experimental_option('useAutomationExtension', False)
option.add_experimental_option(
"excludeSwitches", ['enable-automation'])
option.add_argument("--disable-infobars")
option.add_argument("--guest")
option.add_argument("--log-level=3")
driver = webdriver.Chrome(options=option)
driver.maximize_window()
return driver

以上参数设置将便得浏览器打开更干净。获取driver后,便可通过selenium代码对其进行控制了。

使用ffmpeg开启录屏

不同的操作系统使用不同的参数,例如:开始录制20s视频

  1. windows
1
ffmpeg -hide_banner -f gdigrab -i desktop -t 20 -f mp4 out.mp4
  1. Mac
1
ffmpeg -hide_banner -f avfoundation -i '1:none' -t 20 -r 30 -y -f mp4 out.mp4

其中’1:none’为显示器与音频的编号。可通过命令ffmpeg -f avfoundation -list_devices true -i ""查看
3. Linux

1
ffmpeg -hide_banner -video_size {width}x{height} -f x11grab -i {os.getenv("DISPLAY")} -t 20 -vcodec h264 -y -f mp4 out.mp4

录屏完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import subprocess
import platform
from screeninfo import get_monitors
def record_screen_with_ffmpeg(self, duration, output_path):
ffmpeg_cmd = "ffmpeg"
platform_os = platform.system().lower()
if platform_os == 'windows':
ffmpeg_format = "-f gdigrab -i desktop -t {duration}"
elif platform_os == 'darwin':
ffmpeg_format = f"-f avfoundation -i '1:none' -t {duration} -r 30 -y "
elif platform_os == 'linux':
monitors = get_monitors()
monitor = monitors[0]
width = monitor.width
height = monitor.height
display_number = os.getenv("DISPLAY")
ffmpeg_format = f" -video_size {width}x{height} -f x11grab -i {display_number} -t {duration} -vcodec h264 -y "
else:
raise Exception("Unsupported platform")
command = f"{ffmpeg_cmd} -hide_banner {ffmpeg_format} -f mp4 {output_path}"
print(f"start record screen: {command}")
subprocess.call(command, shell=True, stdin=subprocess.PIPE)
print(f"completed record. save mp4 file to {output_path}")

补充ffmpeg工具

  1. ffmpeg 工具可以方便对视频进行压缩, vcodec可选择编码格式,其中编码名中有nv字符串,则会利用nvidia gpu加速压缩,
1
2
3
4
5
6
## cpu 编码
ffmpeg -i ./source.mp4 -vcodec libx264 -acodec aac dest.mp4
ffmpeg -i ./source.mp4 -vcodec libx265 -acodec aac dest.mp4
## gpu 编码
ffmpeg -i ./source.mp4 -vcodec h264_nvenc -acodec aac dest.mp4
ffmpeg -i ./source.mp4 -vcodec hevc_nvenc -acodec aac dest.mp4
-vcodec 参数 含义说明
copy 复制原始视频流解码器,不重新编码。
libx264 将视频压缩为H.264格式。
libx265 将视频压缩为H.265/HEVC格式。
h264_nvenc 使用NVIDIA GPU硬件加速进行H.264编码。
hevc_nvenc 使用NVIDIA GPU硬件加速进行H.265/HEVC编码。
h264_qsv 使用Intel Quick Sync Video硬件加速进行H.264编码。
hevc_qsv 使用Intel Quick Sync Video硬件加速进行H.265/HEVC编码。
libvpx 将视频压缩为VP8或VP9格式(通过-b:v指定压缩比特率)。
huffyuv 生成无损视频。
  1. ffmpeg 可对mp4文件进行diff
1
2
3
4
5
## 生成一个差值视频
ffmpeg -i video1.mp4 -i video2.mp4 -filter_complex "[0:v][1:v]blend=all_mode='difference'" -y diff.mp4

## 计算视频相似度,结果存放在diff_ssim.log
ffmpeg -i video1.mp4 -i video2.mp4 -filter_complex "[0:v][1:v]ssim=diff_ssim.log" -f null -

对比前需确保两个视频的分辨率和帧率相同,否则FFmpeg可能无法正确处理。如果两个视频的规格不一致,需要先对其进行转码,使它们匹配后再进行差异比较。

使用 x11vnc 远程访问服务器应用界面

  1. 安装x11vnc
    在服务器上安装 x11vnc。可以通过以下命令进行安装
1
sudo apt install x11vnc -y
  1. 启动 Xserver
    启动一个虚拟的 Xserver。使用 Xvfb 可以创建一个虚拟显示器
1
Xvfb -ac :99 -screen 0 1024x768x16
  1. 设置x11vnc密码
    为了确保连接的安全性,您需要为 x11vnc 设置一个访问密码。运行以下命令来设置密码
1
x11vnc -storepasswd

默认情况下,密码会保存在 ~/.vnc/passwd 文件中。
4. 启动 x11vnc
启动 x11vnc 并指定使用虚拟显示器 :99:

1
x11vnc -display :99 -rfbport 5900 -forever -shared -rfbauth ~/.vnc/passwd

这将使 x11vnc 在虚拟显示器 :99 上运行,并通过端口 5900 提供 VNC 服务。
5. 在虚拟显示器中运行 Google Chrome
为了在远程访问中看到浏览器界面,您需要在虚拟显示器 :99 中启动 Google Chrome

1
2
export DISPLAY=:99
google-chrome
  1. 通过 VNC 客户端访问 VNC 服务器
    使用常规的 VNC 客户端连接到您的 VNC 服务器。输入服务器的 IP 地址和端口号(例如 192.168.1.100:5900),您将能够看到并控制服务器上的 Google Chrome 界面。
    vnc google chrome

总结

通过Selenium、Xvfb和FFmpeg的结合使用,我们可以在服务器上实现高效、灵活的自定义录屏解决方案,为软件开发和测试提供了极大的便利。