Electron:摄像头录制和屏幕录制
摄像头录制
main.js
const { app, BrowserWindow} = require('electron')let mainWin = null
const createWindow = () => {mainWin = new BrowserWindow({width: 800,height: 600,title: '自定义菜单',webPreferences: {// 允许渲染进程使用nodejsnodeIntegration: true,// 允许渲染进程使用nodejscontextIsolation: false,}})mainWin.loadFile('index.html')mainWin.webContents.openDevTools()
}app.whenReady().then(() => {createWindow()app.on('activate', () => {if (BrowserWindow.getAllWindows().length === 0) {createWindow()}})
})app.on('window-all-closed', () => {if (process.platform !== 'darwin') {app.quit()}
})
index.html
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title></title>
</head><body><button id="openCamera">打开摄像头</button><button id="start">开始录制</button><button id="stop">停止录制</button><button id="play">播放</button><video src="" id="originVideo"></video><video src="" id="playVideo" width="400" height="500"></video><script>const openCamera = document.querySelector("#openCamera")const start = document.querySelector("#start")const stop = document.querySelector("#stop")const play = document.querySelector("#play")const originVideo = document.querySelector("#originVideo")const playVideo = document.querySelector("#playVideo")let stream;let blobData = []let recordInstance;openCamera.addEventListener("click", () => {handleOpenCamera()})start.addEventListener("click", () => {startRecord()})stop.addEventListener("click", () => {recordInstance && recordInstance.stop()})play.addEventListener("click", () => {const blob = new Blob(blobData, { type: 'video/mp4' })const videoUrl = URL.createObjectURL(blob)playVideo.src = videoUrl;playVideo.play()})// 打开摄像头const handleOpenCamera = async () => {stream = await navigator.mediaDevices.getUserMedia({video: {width: 400, height: 500},audio: true})console.log("handleOpenCamera stream", stream);originVideo.srcObject = streamoriginVideo.play()}//开始录制const startRecord = () => {recordInstance = new MediaRecorder(stream, { mimeType: 'video/webm' })console.log("startRecord stream", stream);if (recordInstance) {recordInstance.start()recordInstance.ondataavailable = function (e) {blobData.push(e.data)}recordInstance.onstop = function (e) {console.log("startRecord onstop");}}}</script></body></html>
屏幕录制

main.js
const { app, BrowserWindow, desktopCapturer, session } = require('electron')let mainWin = null
const createWindow = () => {mainWin = new BrowserWindow({width: 1000,height: 800,title: '自定义菜单',webPreferences: {// 允许渲染进程使用nodejsnodeIntegration: true,// 允许渲染进程使用nodejscontextIsolation: false,}})session.defaultSession.setDisplayMediaRequestHandler((request, callback) => {desktopCapturer.getSources({ types: ['screen'] }).then((sources) => {// Grant access to the first screen found.callback({ video: sources[0], audio: 'loopback' })})})mainWin.loadFile('index.html')mainWin.webContents.openDevTools()
}app.whenReady().then(() => {createWindow()app.on('activate', () => {if (BrowserWindow.getAllWindows().length === 0) {createWindow()}})
})app.on('window-all-closed', () => {if (process.platform !== 'darwin') {app.quit()}
})
- index.html
<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><title></title>
</head><body><button id="openCamera">打开摄像头</button><button id="screenRecord">屏幕录制</button><button id="start">开始录制</button><button id="stop">停止录制</button><button id="play">播放录制的视频</button><video src="" id="originVideo"></video><video src="" id="playVideo" width="400" height="500"></video><script>const openCamera = document.querySelector("#openCamera")const screenRecord = document.querySelector("#screenRecord")const start = document.querySelector("#start")const stop = document.querySelector("#stop")const play = document.querySelector("#play")const originVideo = document.querySelector("#originVideo")const playVideo = document.querySelector("#playVideo")let stream;let blobData = []let recordInstance;// 打开摄像头openCamera.addEventListener("click", () => {handleOpenCamera()})// 屏幕录制screenRecord.addEventListener("click", () => {handleScreenRecord()})// 开始录制start.addEventListener("click", () => {startRecord()})// 停止录制stop.addEventListener("click", () => {recordInstance && recordInstance.stop()})// 播放录制的视频play.addEventListener("click", () => {const blob = new Blob(blobData, { type: 'video/mp4' })const videoUrl = URL.createObjectURL(blob)playVideo.src = videoUrl;playVideo.play()})// 打开摄像头const handleOpenCamera = async () => {stream = await navigator.mediaDevices.getUserMedia({video: {width: 400, height: 500},audio: true})console.log("handleOpenCamera stream", stream);originVideo.srcObject = streamoriginVideo.play()}// 屏幕录制const handleScreenRecord = async () => {stream = await navigator.mediaDevices.getDisplayMedia({video: {width: 400, height: 500},// video: true,audio: true})console.log("handlescreenRecord stream", stream);originVideo.srcObject = streamoriginVideo.play()}//开始录制const startRecord = () => {recordInstance = new MediaRecorder(stream, { mimeType: 'video/webm' })console.log("startRecord stream", stream);if (recordInstance) {recordInstance.start()recordInstance.ondataavailable = function (e) {blobData.push(e.data)}recordInstance.onstop = function (e) {console.log("startRecord onstop");}}}</script></body></html>
相关文章:
Electron:摄像头录制和屏幕录制
摄像头录制 main.js const { app, BrowserWindow} require(electron)let mainWin null const createWindow () > {mainWin new BrowserWindow({width: 800,height: 600,title: 自定义菜单,webPreferences: {// 允许渲染进程使用nodejsnodeIntegration: true,// 允许渲…...
【uniapp】vue3+vite配置tailwindcss
安装 npm install autoprefixer tailwindcss uni-helper/vite-plugin-uni-tailwind -Dautoprefixer :自动管理浏览器前缀的插件,可以解析css文件并且添加前缀到css内容里。uni-helper/vite-plugin-uni-tailwind: 将 Tailwind CSS 框架集成到使用 Vite 作…...
从源码到应用:医疗陪诊系统与在线问诊小程序开发详解
在数字化医疗时代,医疗陪诊系统与在线问诊小程序的开发成为了医疗机构和技术公司关注的焦点。接下来,小编将与您一同深入了解。 一、医疗陪诊系统的核心功能 医疗陪诊系统旨在为患者提供更贴心的医疗服务,通过专业人员陪同患者完成就医过程。…...
mysql数据库中decimal数据类型比较大小
在MySQL中,DECIMAL数据类型用于存储精确的数值,它非常适合用于需要高精度计算的场景,如金融应用。当我们需要在MySQL数据库中比较DECIMAL类型数据的大小时,可以使用标准的比较运算符,如>, <, >, <, 和 &l…...
掌控库存,简化管理 — InvenTree 开源库存管理系统
InvenTree :简化您的库存管理,让效率和控制力触手可及。- 精选真开源,释放新价值。 概览 InvenTree,一款专为精细化库存管理而设计的开源系统,以其高效和灵活性在众多库存管理工具中脱颖而出。它以Python和Django框架…...
Linux---项目自动化构建工具-make/Makefile
一、背景 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的 规则来指定,哪些文件需要先编译,哪些文件…...
嘉立创EDA个人学习笔记1(PCB板介绍)
前言 本篇文章属于嘉立创EDA的学习笔记,来源于B站教学视频。下面是这位up主的视频链接。本文为个人学习笔记,只能做参考,细节方面建议观看视频,肯定受益匪浅。 嘉立创EDA-PCB设计零基础入门课程(54集全)_…...
(转)Restful接口设计(1)
.representational:代表性的 URI(Universal Resouce Identifier):Universal :普遍的;共同的。Identifier:标识符。统一资源标识符。 31-RESTful接口介绍-02_哔哩哔哩_bilibili 31-RESTful接口介绍-03_哔哩…...
Python进阶之3D图形
Python进阶之3D图形 在数据可视化中,2D图形通常可以满足大多数需求。然而,对于一些复杂的数据或分析,3D图形可以提供更多的视角和洞察。在Python中,使用 Matplotlib 和 Plotly 等库可以轻松创建各种3D图形。本文将介绍如何使用这…...
机器学习深度学习中的搜索算法浅谈
机器学习&深度学习中的搜索算法浅谈 搜索算法是计算机科学中的核心算法,用于在各种数据结构(如数组、列表、树、图等)中查找特定元素或信息。这些算法不仅在理论上具有重要意义,还在实际应用中扮演着关键角色。本文将详细探讨…...
基于IMX8M_plus+FPGA+AI监护仪解决方案
监护仪是一种以测量和控制病人生理参数,并可与已知设定值进行比较,如果出现超标可发出警报的装置或系统。 (1)监护仪主要采集测量人体生理参数,心电、血压、血氧、体温等需要采集处理大量的数据,系统需要多…...
仿RabbitMq实现简易消息队列正式篇(路由匹配篇)
TOC 目录 路由匹配模块 代码展示 路由匹配模块 决定了一条消息是否能够发布到指定的队列 在每个队列根交换机的绑定信息中,都有一个binding_key(在虚拟机篇有说到)这是队列发布的匹配规则 在每条要发布的消息中,都有一个rout…...
一套完整的NVR网络硬盘录像机解决方案和NVR程序源码介绍
随着网络技术的发展,视频数据存储的需求激增,促使硬盘录像机(DVR)逐渐演变为具备网络功能的网络视频录像机(NVR)。NVR,即网络视频录像机,负责网络视音频信号的接入、存储、转发、解码…...
2024年人工智能固态硬盘采购容量预计超过45 EB
根据TrendForce发布的最新市场报告,人工智能(AI)服务器客户在过去两个季度显著增加了对企业级固态硬盘(SSD)的订单。为了满足AI应用中不断增长的SSD需求,上游供应商正在加速工艺升级,并计划在20…...
Java的反射原理
反射允许程序在运行时检查或修改其类、接口、字段和方法的行为。反射主要通过java.lang.reflect包中的类和接口实现,它主要用于以下目的: 在运行时分析类的能力:通过反射,可以在运行时检查类的结构,比如它的方法、构造…...
vue.config.js 配置
vue.config.js 文件是 Vue CLI 项目中的全局配置文件,它允许你以 JavaScript 的形式来配置构建选项,而不是通过命令行参数或者 .vue-clirc 的 JSON 格式。 官方文档: https://cli.vuejs.org/zh/config/#全局-cli-配置 基础配置 publicPath 设置构建好的…...
C ++ 也可以搭建Web?高性能的 C++ Web 开发框架 CPPCMS + MySQL 实现快速入门案例
什么是CPPCMS? CppCMS 是一个高性能的 C Web 开发框架,专为构建快速、动态的网页应用而设计,特别适合高并发和低延迟的场景。其设计理念类似于 Python 的 Django 或 Ruby on Rails,但针对 C 提供了更细粒度的控制和更高效的性能。…...
Taos 常用命令工作笔记(二)
最近测试创建一个涛思的数据库和一堆表进行测试,通过json配置文件配置字段的类型、名称等,程序通过解析json文件的配置,动态创建数据库的表。 其中表字段为驼峰结构的规则命名,创建表也是成功的,插入的测试数据也是成功…...
idea安装二进制文本阅读插件
引言 在软件开发过程中,有时需要查看二进制文件的内容以调试或分析问题。虽然有许多专用工具可以处理这类任务,但直接在 IDE 内集成这些功能无疑更加方便高效。本文将介绍如何在 IntelliJ IDEA 2023中安装和配置一个名为 BinEd的插件,以及如…...
MySQL 常用 SQL 语句大全
1. 基本查询 查询所有记录和字段 SELECT * FROM table_name; 查询特定字段 SELECT column1, column2 FROM table_name; 查询并限制结果 SELECT column1, column2 FROM table_name LIMIT 10; 条件查询 SELECT column1, column2 FROM table_name WHERE condition; 模糊匹…...
利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...
