// This file is required by the index.html file and will
// be executed in the renderer process for that window.
// No Node.js APIs are available in this process because
// `nodeIntegration` is turned off. Use `preload.js` to
// selectively enable features needed in the rendering
// process.
const jQuery = (window.jQuery = require('jquery'));
require('@popperjs/core');
require('bootstrap');
const Vue = require('vue/dist/vue');
const electron = require('electron');
const fs = require('fs');
const SCREEN_WIDTH = 3072;
const SCREEN_HEIGHT = 1920;
const PlayerCanvas = require('./PlayerCanvas');
new Vue({
  el: '#vueapp',
  data: {
    recording: false,
  mounted() {
    this._playerCanvas = new PlayerCanvas(SCREEN_WIDTH, SCREEN_HEIGHT);
  methods: {
    // 开始录制
    async btnStartRecordClicked(e) {
      this._stream = new MediaStream();
      await this.attachAudioStream();
      // 摄像头 stream
      this._cameraStream = await navigator.mediaDevices.getUserMedia({
        video: true,
        audio: false,
      this._playerCanvas.setCameraVideo(
        this.createVideoElementWithStream(this._cameraStream)
      // 屏幕 stream
      this._screenStream = await navigator.mediaDevices.getUserMedia({
        audio: false,
        video: {
          mandatory: {
            chromeMediaSource: 'desktop',
            minWidth: SCREEN_WIDTH,
            maxWidth: SCREEN_WIDTH,
            minHeight: SCREEN_HEIGHT,
            maxHeight: SCREEN_HEIGHT,
      this._playerCanvas.setScreenVideo(
        this.createVideoElementWithStream(this._screenStream)
      this._audioStream
        .getAudioTracks()
        .forEach((value) => this._stream.addTrack(value));
      let playerCanvasStream = this._playerCanvas.canvas.captureStream();
      playerCanvasStream.getTracks().forEach((t) => this._stream.addTrack(t));
      this.$refs.preview.srcObject = playerCanvasStream;
      this.startRecord();
    // 附加音频流
    async attachAudioStream() {
      // 获取麦克风流
      this._audioStream = await navigator.mediaDevices.getUserMedia({
        video: false,
        audio: true,
      // 将麦克风的流,附加到主流上
      this._audioStream
        .getAudioTracks()
        .forEach((value) => this._stream.addTrack(value));
    // 停止录制
    btnStopRecordClicked(e) {
      this.recording = false;
      this._recorder.stop();
    // 创建一个 HTMLVideoElement
    createVideoElementWithStream(stream) {
      let video = document.createElement('video');
      video.autoplay = true;
      video.srcObject = stream;
      return video;
    // 开始录制
    startRecord() {
      this._recorder = new MediaRecorder(this._stream, {
        mimeType: 'video/webm;codes=h264',
      this._recorder.ondataavailable = async (e) => {
        let path = electron.remote.dialog.showSaveDialogSync(
          electron.remote.getCurrentWindow(),
            title: '保存文件',
            defaultPath: 'ScreenData.webm',
        let dataArrayBuffer = await e.data.arrayBuffer();
        fs.writeFileSync(path, Buffer.from(dataArrayBuffer));
        // fs.writeFileSync(path, new Uint8Array(dataArrayBuffer));
      this._recorder.start();
      this.recording = true;
const jQuery = (window.jQuery = require('jquery'));
require('@popperjs/core');
require('bootstrap');
const Vue = require('vue/dist/vue');
const electron = require('electron');
const fs = require('fs');
new Vue({
  el: '#vueapp',
  data: {
    recording: false,
  methods: {
    async btnStartRecordClicked(e) {
      this._stream = await navigator.mediaDevices.getUserMedia({
        video: false,
        audio: true,
      let screenStream = await navigator.mediaDevices.getUserMedia({
        audio: false,
        video: {
          mandatory: {
            chromeMediaSource: 'desktop',
            minWidth: 3072,
            maxWidth: 3072,
            minHeight: 1920,
            maxHeight: 1920,
      screenStream
        .getVideoTracks()
        .forEach((value) => this._stream.addTrack(value));
      this.$refs.preview.srcObject = screenStream;
      this._recorder = new MediaRecorder(this._stream, {
        mimeType: 'video/webm;codes=h264',
      this._recorder.ondataavailable = async (e) => {
        let path = electron.remote.dialog.showSaveDialogSync(
          electron.remote.getCurrentWindow(),
            title: '保存文件',
            defaultPath: 'ScreenData.webm',
        let dataArrayBuffer = await e.data.arrayBuffer();
        fs.writeFileSync(path, Buffer.from(dataArrayBuffer));
        // fs.writeFileSync(path, new Uint8Array(dataArrayBuffer));
      this._recorder.start();
      this.recording = true;
    btnStopRecordClicked(e) {
      this.recording = false;
      this._recorder.stop();

源码下载:

分类: Web Web 前端标签 , , 发表评论 on 基于 Electron 的屏幕录制工具
    webPreferences: {
      nodeIntegration: true,
      enableRemoteModule: true,   // 这行代码必须加进去,不然渲染进程无法访问 nodejs,electron 的资源

然后在 package.json 文件中加入配置

  1. "main":"./src/electron/main.js" 其中的路径为你的 main.js 路径配置。
  2. "homepage": "./" 表示请求资源用相对路径,否则打包之后请求不到js,css资源

继续:引入 electron-is-dev 包

npm install electron-is-dev --save

这个包用于判断当前运行环境是开发环境还是生产环境,在 main.js 中,我们这里加一个判断:

继续:引入 concurrently

npm install concurrently --save

这个包用于同时启动多个服务用

继续:引入 wait-on

npm install wait-on --save

用于启动等待命令

const isDev = require('electron-is-dev')
const path = require('path')
if (isDev) {
  win.loadURL('http://localhost:3000')
} else {
  win.loadFile(path.join(__dirname, '../build/index.html'))

路劲为 main.js 相对 build 文件夹(React打出来的包文件夹)的路径。

可选配置(没有也没关系)

修改package.json,添加一个electron-dev脚本命令:
  "scripts": {
    "dev": "concurrently \"BROWSER=none react-scripts start\" \"wait-on http://localhost:3000 && electron .\"",

这样就可以直接 npm run dev 开启调试模式,不用单独再运行 React 和 Electron。

以上,即可:npm run dev 运行程序

分类: Web 前端标签 , 创建 Electron + React 项目流程有1条评论 <title>vest</title> <% if (htmlWebpackPlugin.options.nodeModules) { %> <!-- Add `node_modules/` to global paths so `require` works properly in development --> <script> require('module').globalPaths.push('<%= htmlWebpackPlugin.options.nodeModules.replace(/\\/g, '\\\\') %>') </script> <% } %> </head> <div id="app"></div> <!-- Set `__static` path to static files in production --> <% if (!require('process').browser) { %> <script> if (process.env.NODE_ENV !== 'development') window.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\') </script> <% } %> <!-- webpack builds are automatically injected --> </body> </html>

以上代码,覆盖到 index.ejs 文件即可。

分类: Web 前端标签 , 发表评论 on 解决 Electron-Vue 报错:Webpack ReferenceError: process is not defined