当前位置: 首页 > news >正文

Node.js实时截屏实现方案

前端:

<!DOCTYPE html>
<html lang="zh"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>实时截屏</title><style>html,body {margin: 0;overflow: hidden;width: 100%;height: 100%;}img {width: 100%;height: 100%;}</style></head><body><img id="screen" alt="Screen Feed" /><script>const img = document.getElementById('screen');const ws = new WebSocket('ws://localhost:8080'); // 改成服务器 IP 如果跨机ws.onmessage = (event) => {// event.data 是 base64 图片const img = document.getElementById('screen');img.src = event.data;// 计算合适的宽度和高度const containerWidth = document.body.clientWidth; // 容器宽度const aspectRatio = img.naturalWidth / img.naturalHeight; // 原始宽高比if (img.naturalWidth > containerWidth) {img.style.width = `${containerWidth}px`;img.style.height = `${containerWidth / aspectRatio}px`;} else {img.style.width = `${img.naturalWidth}px`;img.style.height = `${img.naturalHeight}px`;}img.src = event.data;};ws.onopen = () => {console.log('Connected to screen capture server');};ws.onclose = () => {console.log('Disconnected');img.src = '';};ws.onerror = (err) => {console.error('WebSocket error:', err);};</script></body>
</html>

服务端:

注意:
robotjs:用于截屏(仅支持桌面环境:Windows/macOS/Linux)
canvas:Node.js 中处理图像(需安装 node-canvas,可能需要系统依赖)
Ubuntu:

sudo apt-get install build-essential libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev

macOS:

brew install pkg-config cairo pango libpng jpeg giflib librsvg

Windows: 推荐使用 windows-build-tools(Node 14+ 可能不需要)

初始化项目

npm init -y
npm install ws robotjs canvas
// server.js
const WebSocket = require('ws');
const robot = require('robotjs');
const { createCanvas } = require('canvas');// 创建 WebSocket 服务器
const wss = new WebSocket.Server({ port: 8080 });
console.log('WebSocket server running on ws://localhost:8080');// 获取屏幕尺寸
const screen = robot.getScreenSize();
let width = screen.width;
let height = screen.height;
width = 1920;
height = 1080;
// 创建与屏幕大小相同的 Canvas
const canvas = createCanvas(width, height);
const ctx = canvas.getContext('2d');wss.on('connection', (ws) => {console.log('Client connected');// 每 100ms 截屏一次(约 10 FPS)const interval = setInterval(() => {try {// 1. 使用 robotjs 截取屏幕const img = robot.screen.capture(0, 0, width, height);if (!img) {console.error('Failed to capture screen: no image data');return;}// 2. 创建 ImageData 并填充像素const imageData = ctx.createImageData(width, height);const pixelBuffer = img.image; // 原始像素数据(BGR 格式)for (let y = 0; y < height; y++) {for (let x = 0; x < width; x++) {const idx = (y * width + x) * 4;       // ImageData 索引(RGBA)const pixelIdx = (y * width + x) * 4;  // robotjs 像素索引(BGR + 未使用)// robotjs 返回的是 BGR + 未使用字节,顺序为 [B, G, R, ?]imageData.data[idx]     = pixelBuffer[pixelIdx + 2]; // RimageData.data[idx + 1] = pixelBuffer[pixelIdx + 1]; // GimageData.data[idx + 2] = pixelBuffer[pixelIdx];     // BimageData.data[idx + 3] = 255;                       // A(不透明)}}// 3. 将 ImageData 绘制到 Canvasctx.putImageData(imageData, 0, 0);// 4. 转为 JPEG Base64(压缩,质量 50%)const dataUrl = canvas.toDataURL('image/jpeg', 1.0);// 5. 发送给客户端ws.send(dataUrl);} catch (err) {console.error('Capture error:', err.message || err);}}, 100); // 100ms = 10 FPS// 客户端断开时清理ws.on('close', () => {console.log('Client disconnected');clearInterval(interval);});// 处理错误ws.on('error', (err) => {console.error('WebSocket error:', err);});
});// 错误处理
wss.on('error', (err) => {console.error('WebSocket Server error:', err);if (err.code === 'EADDRINUSE') {console.error('端口 8080 已被占用,请关闭其他程序或更换端口。');}
});

效果:
请添加图片描述


文章转载自:

http://fl8bNy3i.mprtj.cn
http://g02AdLOp.mprtj.cn
http://CE8pKtnK.mprtj.cn
http://kI0gyUuT.mprtj.cn
http://DAozsgnx.mprtj.cn
http://LLGR9PGs.mprtj.cn
http://c8FFOCGD.mprtj.cn
http://tz8lG0dx.mprtj.cn
http://U3av9dII.mprtj.cn
http://EAHsfv0l.mprtj.cn
http://wkvkbxSP.mprtj.cn
http://sD9NoiNj.mprtj.cn
http://NFJVOoAQ.mprtj.cn
http://bRjeDmDO.mprtj.cn
http://Qez8XfqD.mprtj.cn
http://QRPBSG9l.mprtj.cn
http://5MYu9jl5.mprtj.cn
http://0SWQW6gK.mprtj.cn
http://9W0TKkPq.mprtj.cn
http://OJMy9cv9.mprtj.cn
http://ivUvaXnP.mprtj.cn
http://uKNYbIqh.mprtj.cn
http://5cN3TrU0.mprtj.cn
http://sYAd7Aga.mprtj.cn
http://oGHDglgC.mprtj.cn
http://YsN6djh4.mprtj.cn
http://CMpvlZYH.mprtj.cn
http://HRJBd7FE.mprtj.cn
http://QDcKr4Q9.mprtj.cn
http://uHYQmFVF.mprtj.cn
http://www.dtcms.com/a/383022.html

相关文章:

  • 01数据结构-01背包问题
  • 20250914-01: Langchain概念:流式传输(Streaming)
  • 初步认识 Spring Boot 自动装配
  • 《突破Unity+腾讯云联机瓶颈:多人游戏同步延迟与数据安全的双维度优化》
  • 计算机算术9-浮点乘法
  • 第24课:项目实战与总结
  • 【深度学习|学习笔记】从背景→公式→性质→梯度→何时用哪一个→数值稳定性与常见坑方面描述sigmoid和softmax函数!(一)
  • C++宽度优先搜索算法:队列与优先级队列
  • 同步降压转换器原理
  • 人工智能训练师三级备考笔记
  • <基于深度学习的条纹图分析及其不确定性估计>-论文总结
  • 【愚公系列】《人工智能70年》020-语音识别的历史性突破(深度学习带来历史性突破)
  • 网络操作系统与分布式操作系统的区别
  • Spring Cloud Alibaba 实战:从 0 到 1 构建可监控的微服务体系
  • 分布式推理与量化部署
  • Kafka 实现从网络层到日志与位点的“全景拆解”
  • Python入门教程之赋值运算符
  • 机器学习系统设计:从需求分析到模型部署的完整项目流程
  • SpringMVC架构解析:从入门到精通(1)
  • Why Language Models Hallucinate 论文翻译
  • 从 WPF 到 Avalonia 的迁移系列实战篇5:Trigger、MultiTrigger、DataTrigger 的迁移
  • easyExcel动态应用案例
  • 目标计数论文阅读(2)Learning To Count Everything
  • 贪心算法应用:速率单调调度(RMS)问题详解
  • 【传奇开心果系列】基于Flet框架实现的用窗口管理器动态集中管理多窗口自定义组件模板特色和实现原理深度分析
  • [Android] 汉语大辞典3.2
  • 《嵌入式硬件(八):基于IMX6ULL的点灯操作》
  • css的基本知识
  • AOP 切面日志详细
  • 软件工程实践二:Spring Boot 知识回顾