Jenkins服务器上Selenium无法调用摄像头拍照,如何模拟摄像头?
问题背景
本地基于Java 11、Selenium 4.1.2、Firefox无头模式运行Angular摄像头拍照自动化脚本时一切正常,但Jenkins服务器上无法完成拍照操作。已配置Firefox授予摄像头权限:
// set the profile to allow camera access FirefoxProfile profile = new FirefoxProfile(); profile.setPreference("media.navigator.permission.disabled", true); firefoxOptions.setProfile(profile); System.setProperty(systemProperty, driverPath); webDriver = new FirefoxDriver(firefoxOptions);
拍照核心逻辑:
@Step ("capture photo") public ConfirmPhotoPO capturePhoto(){ SeleniumWaitUtil.waitUntilElementToBeClickable(captureBtn); // try capture a photo, and check if we can upload clickElement(captureBtn); return new ConfirmPhotoPO(); }
推测问题根源为Jenkins服务器无实体摄像头,询问是否可通过模拟摄像头解决该问题。
解决方案:模拟摄像头
可以通过模拟摄像头解决该问题,优先尝试Firefox内置虚拟流方案,复杂场景再使用第三方虚拟摄像头工具:
方法一:Firefox内置虚拟媒体流(无需额外安装工具)
在现有FirefoxProfile配置中添加虚拟流开关,让Firefox自动生成虚拟视频流,无需依赖实体设备:FirefoxProfile profile = new FirefoxProfile(); // 禁用摄像头权限提示 profile.setPreference("media.navigator.permission.disabled", true); // 启用Firefox内置虚拟媒体流 profile.setPreference("media.navigator.streams.fake", true); firefoxOptions.setProfile(profile); System.setProperty(systemProperty, driverPath); webDriver = new FirefoxDriver(firefoxOptions);该配置会让Firefox模拟出虚拟摄像头,调用
getUserMedia时直接返回虚拟视频流,满足基础拍照需求。方法二:第三方虚拟摄像头工具(适配定制化场景)
若需要指定特定图片/视频作为摄像头输入,可在Jenkins服务器安装虚拟摄像头工具:- Linux服务器:安装
v4l2loopback内核模块创建虚拟设备# Debian/Ubuntu系统安装依赖 sudo apt-get update && sudo apt-get install v4l2loopback-dkms v4l2loopback-utils # 加载模块,创建1个虚拟摄像头设备(设备号为10,可自定义) sudo modprobe v4l2loopback devices=1 video_nr=10 card_label="VirtualCam" exclusive_caps=1 # 可选:将指定图片推送到虚拟摄像头(依赖ffmpeg) ffmpeg -re -loop 1 -i /path/to/test-image.jpg -f v4l2 /dev/video10 - Windows服务器:安装
OBS Virtual Camera或ManyCam,在软件中配置虚拟摄像头的输入源(图片/视频)。
配置Firefox指向该虚拟设备:
profile.setPreference("media.navigator.permission.disabled", true); // 指定虚拟摄像头设备路径(Linux为/dev/video10,Windows需根据工具配置调整) profile.setPreference("media.navigator.video.source", "/dev/video10"); firefoxOptions.setProfile(profile);- Linux服务器:安装
优化脚本等待逻辑
虚拟摄像头加载可能存在延迟,可在点击拍照按钮前等待视频流就绪:@Step ("capture photo") public ConfirmPhotoPO capturePhoto(){ // 等待摄像头流就绪 new WebDriverWait(webDriver, Duration.ofSeconds(10)) .until(driver -> (Boolean) ((JavascriptExecutor) driver) .executeScript("return navigator.mediaDevices.enumerateDevices().then(devs => devs.some(d => d.kind === 'videoinput' && d.deviceId !== ''));")); // 等待拍照按钮可点击并执行操作 SeleniumWaitUtil.waitUntilElementToBeClickable(captureBtn); clickElement(captureBtn); return new ConfirmPhotoPO(); }
内容的提问来源于stack exchange,提问作者Tinashe Chinyanga
相关产品推荐
相关产品推荐

