nodejs中使用ffmpeg零基础教程(electron+vue3)

同学们可以私信我加入学习群!


正文开始


前言

最近想要把自己写的一些知识点,在写完demo后,除了形成博客记录笔记,还可以便捷地录屏形成视频教程。所以研究了好久如何在nodejs中完成录屏功能。本功能模块基于electron+vue3完成,原生nodejs也可以作为参考,原理是一致的。

踩了很多坑,否了很多方案后,终于形成了目前的方案。


一、多方案对比

1.最简单的就是使用electron的desktopCapturer.getSources获取屏幕源,大致代码如下:

c 复制代码
const sources= await desktopCapturer.getSources({ types: ['window', 'screen'] })
    let sId=null
    for (const source of sources) {
        console.log(source.name);
        if (source.name.includes('整个')) {
            sId=source.id
        }
    }
    return sId

然后将屏幕id传递给渲染层vue中,利用浏览器提供的navigator.mediaDevices.getUserMedia,录制视频流:

c 复制代码
 const stream = await navigator.mediaDevices.getUserMedia({
        audio: false,
        video: {
          mandatory: {
            chromeMediaSource: 'desktop',
            chromeMediaSourceId: sourceId,
            minWidth: 1280,
            maxWidth: 1280,
            minHeight: 720,
            maxHeight: 720
          }
        }
      })

这种方案舍弃,原因是录制特定区域内容形成视频,还是需要借助ffmpeg插件,多一步操作就多一些性能损耗。

2.又在网上查到一种方案,是利用canvas将屏幕形成图片,最终再由ffmpeg插件将图片形成视频,性能太差,舍弃!

3.借助ffmpeg插件,这里又有许多方案可供参考:

  • 直接下载ffmpeg,把它放到全局变量,然后使用ffmpeg命令行(不现实,不能要求每个人用录屏软件时,都要先等几十秒去下载插件)
  • 直接使用ffmpeg-static插件,然后获取到node_modules中的exe可执行文件,再使用命令行(可行,但不太方便,因为一致操作命令行,容易出错,对各类报错捕获也过于原始)
  • 使用@ffmpeg-installer/ffmpeg插件配合fluent-ffmpeg插件,理论可行,由@ffmpeg-installer/ffmpeg维护下载ffmpeg,由fluent-ffmpeg操作ffmpeg,但是我的@ffmpeg-installer/ffmpeg插件下载ffmpeg时,总是失败,不知道原因。
  • 最终采用ffmpeg-static配合fluent-ffmpeg的方式,完成录屏功能。

想要明白自己需要什么插件,首先要弄明白这些插件都在做什么,我第一次接触ffmpeg,简直被这几个插件搞懵了。都什么鬼插件,还那么高下载量。既然都是围绕ffmpeg插件展开的,就不能出个一统天下的插件,减少心智负担。

二、ffmpeg各插件简介

  1. ffmpeg插件:这是真正的录屏插件,windows系统中以exe可执行文件形式存在,其它所有插件都是围绕它开发。

  2. @ffmpeg-installer/ffmpeg插件:一个维护下载ffmpeg的插件,可以帮助我们便捷地下载更新对应版本的ffmpeg,并且在下载后,可以暴露出exe可执行文件的地址,方便我们操作ffmpeg。一般情况下,我们只需要使用@ffmpeg-installer/ffmpeg插件,就可以不用直接下载ffmpeg插件了。

  3. ffmpeg-static插件:功能类似于上面的插件,但是实现原理不同,在ffmpeg-static插件中,自带某个版本的ffmpeg,ffmpeg-static插件并不提供下载维护ffmpeg的功能,但是下载ffmpeg-static,就会顺带下载ffmpeg,并帮助我们完成一些基础工作,引入ffmpeg-static插件也可以直接获取ffmpeg插件的地址,方便我们操作。

  4. fluent-ffmpeg插件:正常操作ffmpeg是通过命令行的方式,ffmpeg-static插件把命令行的方式做了一层封装,让我们可以通过api的形式调用ffmpeg,写代码更简单方便一些。

三、使用ffmpeg-static插件

我们先来看如何简单地使用ffmpeg-static插件。

第一步------下载:

c 复制代码
npm i ffmpeg-static

第二步------引入:

c 复制代码
  const pathToFfmpeg = require('ffmpeg-static')

第三步------写命令行,运行ffmpeg插件

c 复制代码
ffmpegCommand = `${pathToFfmpeg} -f gdigrab -r 30  -i desktop -c:v libx264 -preset ultrafast -t 10 output1111.mp4`

四、使用fluent-ffmpeg插件

fluent-ffmpeg插件只是简化了操作的步骤,仍然需要借助上面的ffmpeg-static插件。

第一步------下载:

c 复制代码
npm i fluent-ffmpeg

第二步------引入,配合ffmpeg-static

c 复制代码
 const ffmpeg = require('fluent-ffmpeg');
 const pathToFfmpeg = require('ffmpeg-static')

第三步------使用:

c 复制代码
ffmpeg.setFfmpegPath(pathToFfmpeg);
const command = ffmpeg()
    .input(`desktop`) 
    .fromFormat('gdigrab')
    .videoCodec('libx264')
    .preset('divx') 
    .outputOptions('-t ' + 10) 
    .output(fileName) 
    .on('end', function () {
        console.log('桌面捕获完成!');
    })
    .on('error', function (err) {
        console.error('发生错误:', err);
    })
    .run(); // 执行命令

五、如果使用ai,可能会踩的坑

首先,这部分的网络资料不多,如果直接百度或谷歌,查到相关资料很多,但是正好是我写的这部分内容,可能不多。而如果使用ai工具辅助完成,可能会有一些bug。

5.1第一个坑

大部分使用fluent-static的资料,输入都是已存在视频文件的路径,而我们需要的是实时录制视频,所以input的参数网上没查到相应资料,如果问ai它可能会给你一个这样的参数:
gdigrab=framerate=${frameRate}:desktop,导致报错。

解决思路:

带大家简单看一下源码,fluent-ffmpeg插件中有一个input.js文件,里面有段代码是在定义input方法:

我们可以看到,这段方法接收的参数就是输入的源source,source最终push到了_inputs中。

再看一下processor.js中有下面一段代码:

这段代码可以看到,最终把inputs中的source参数赋值给了-i,看到这我们就能理解个差不多,原来input方法的参数就是ffmpeg插件中"-i"后面的参数。

下面是最原始的命令行:

c 复制代码
ffmpegCommand = `${pathToFfmpeg} -f gdigrab -r 30  -i desktop -c:v libx264 -preset ultrafast -t 10 output1111.mp4`

-i参数后面的值是desktop,所以我们应该在input方法中输入"desktop",也就是如下代码:

c 复制代码
ffmpeg()
    .input('desktop') 

当然,从源码,我们还可以看到这个视频源应该还有流数据的格式,不过初次体验,就先不踩坑去尝试了。

5.2第二个坑

如果按照命令行的编码格式,参数preset后面是ultrafast,也就是说fluent-ffmpeg中preset 方法接收的参数应该是ultrafast,但是这么写后,会报错:

UnhandledPromiseRejectionWarning: Error: preset G:\c-private\lize-tools-pc\node_modules\.store\fluent-ffmpeg@2.1.3\node_modules\fluent-ffmpeg\lib\presets\ultrafast could not be loaded: Cannot find module 'G:\c-private\l ize-tools-pc\node_modules\.store\fluent-ffmpeg@2.1.3\node_modules\fluent-ffmpeg\lib\presets\ultrafast'

根据报错信息,我们可以知道在fluent-ffmpeg\lib\presets目录下,找不到ultrafast,也就是说fluent-ffmpeg不支持这种编码,查看对应目录,我们可以发现它只支持三种编码:

所以我们只能三选一,例如:.preset('divx')。

可能有同学会有疑问,fluent-ffmpeg会不会阉割ffmpeg插件的部分功能?一般不会!通过看fluent-ffmpeg的源码,我们可以发现,它的功能核心十分简单,就是想办法把命令行变成api,或者说是通过api把我们的输入最终变成了ffmpeg能理解的命令行,留一个简单的api,能够把我们输入的任意字符串都拼进最终的命令行,就能兼顾最大自由度的命令行定制功能。

虽然我还没看,但是我猜测它一定有类似的api,其中可以写任意的命令行参数,来使用ffmpeg的所有功能。

5.3第三个坑

命令行中的参数-f gdigrab,在windows环境中,应该指定gdigrab为视频采集工具,mac环境中指定avfoundation为视频采集工具。我们继续找源码:

在output.js中,找到了和"-f"参数相关的代码,所以在windows环境中,我们应该加上一个方法.format("gdigrab"),来指定视频采集工具。


总结

等视频录屏功能和vue代码预览功能都完成后,会在博主的桌面端工具中发布,免费使用,下面有软件获取链接。

获取资源,查看代码示例,或者联系我:

https://lizetoolbox.top:8080/#/qrCode_contact

相关推荐
守城小轩21 小时前
Firefox Android 开发环境搭建全流程(四)
android·firefox·chrome devtools·指纹浏览器·浏览器开发
EndingCoder3 天前
调试技巧:Chrome DevTools 与 Node.js Inspector
javascript·网络·electron·node.js·vim·chrome devtools
yuguo.im7 天前
Chrome DevTools Performance 是优化前端性能的瑞士军刀
前端·javascript·性能优化·chrome devtools
IT小农工8 天前
windows系统edge浏览器退出账户后还能免密登录
前端·edge
小妖6668 天前
如何去除edge浏览器的灰色边框
前端·edge
紫金龙腾17 天前
EDGE 、chrome、浏览器显示“由你的组织管理”
前端·chrome·edge
HaushoLin17 天前
Chrome和Edge如何开启暗黑模式
chrome·edge
xcLeigh18 天前
文心一言4.5开源模型实战:ERNIE-4.5-0.3B轻量化部署与效能突破
人工智能·开源·大模型·文心一言·ernie·轻量化部署
77238922 天前
解决 Microsoft Edge 显示“由你的组织管理”问题
前端·microsoft·edge
lpfasd12324 天前
开发Chrome/Edge插件基本流程
前端·chrome·edge