一、安装 CamSplitter
这块网上有很多教程了,这里不再赘述,就一点,需要分几个虚拟摄像头,就要在CamSplitter 的安装目录下 driver_install.cmd 执行几次。
二、React + ts + react-webcam 调用虚拟摄像头
import { useState, useEffect, useCallback, useMemo } from "react";
import Webcam from "react-webcam";
interface DeviceInfo {
deviceId: string;
label: string;
kind: string;
}
export const VirtualCameraViewer = () => {
const [_, setDevices] = useState<DeviceInfo[]>([]);
const [selectedDevice, setSelectedDevice] = useState<string | null>(null);
//这里实现了跨系统的适配
const systemSpecificConstraints = useMemo(() => {
const isLinux = navigator.userAgent.includes("Linux");
const isWindows = navigator.userAgent.includes("Windows");
if (isLinux) {
return {
width: { ideal: 640 },
height: { ideal: 480 },
frameRate: { ideal: 15 },
facingMode: "environment",
};
} else if (isWindows) {
return {
width: { ideal: 640 },
height: { ideal: 480 },
frameRate: { ideal: 30 },
facingMode: "user",
};
}
return {};
}, [navigator.userAgent]);
// 必须先请求摄像头权限才能获取完整设备信息
async function initCamera() {
try {
//浏览器webRTC 请求摄像头权限
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
stream.getTracks().forEach((track) => track.stop()); // 释放初始流
//获取摄像头列表
const devices = await navigator.mediaDevices.enumerateDevices();
//过滤出来虚拟摄像头 这里 linux系统可以使用 v4l2loopback实现
//v4l2loopback label 包含 Virtual。
//CamSplitter的虚拟摄像头默认名称为CamSplitter #1,CamSplitter #2
const cameras = devices.filter(
(d) =>
d.kind === "videoinput" &&
(d.label.includes("Virtual") || d.label.includes("CamSplitter"))
);
console.log("摄像头列表:", cameras); // 检查label和deviceId
handleDevices(cameras);
} catch (error) {
console.error("权限获取失败:", error);
}
}
const handleDevices = useCallback((mediaDevices: MediaDeviceInfo[]) => {
setDevices(mediaDevices);
if (mediaDevices.length > 0) {
setSelectedDevice(mediaDevices[0].deviceId);
}
}, []);
useEffect(() => {
initCamera();
}, [handleDevices]);
return (
<>
{selectedDevice && (
<Webcam
audio={false}
videoConstraints={
selectedDevice
? {
...systemSpecificConstraints,
deviceId: { exact: selectedDevice },
}
: { ...systemSpecificConstraints }
}
/>
)}
</>
);
};
上面就实现了一个简单 的 浏览器通过webRTC 调用虚拟摄像头,避免摄像头被占用的问题。
注意:1、webRTC只有现代浏览器支持,成熟方案应该考虑老旧版本浏览器不支持webRTC的问题。
2、考虑摄像头流资源释放问题。
3、浏览器调用摄像头,第一次要获取权限。
4、CamSplitter 要读取真实的摄像头流并最小化。