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

相关推荐
lrlianmengba3 天前
推荐一款功能强大的图表绘制工具:EDGE Diagrammer
前端·edge
Black蜡笔小新3 天前
无插件H5播放器EasyPlayer.js RTSP播放器chrome/edge等浏览器如何使用独立显卡
javascript·chrome·edge
守城小轩8 天前
Brave127编译指南 Windows篇:部署depot_tools(三)
chrome·chrome devtools·指纹浏览器·浏览器开发·brave
幂简集成9 天前
如何一步步获得文心一言API密钥
dubbo·api·文心一言
bu_shuo9 天前
IDM扩展添加到Edge浏览器
edge·idm
灰哥数据智能10 天前
DB-GPT系列(四):DB-GPT六大基础应用场景part1
python·数据挖掘·gpt-3·文心一言
Licky1310 天前
web 远程调试工具PageSpy 实战经验
前端·javascript·架构·chrome devtools
福大大架构师每日一题11 天前
文心一言 VS 讯飞星火 VS chatgpt (389)-- 算法导论25.1 2题
算法·文心一言
WANGWUSAN6611 天前
爬虫新姿势——使用Chrome Devtools写一个小说爬虫
开发语言·前端·经验分享·爬虫·python·学习·chrome devtools
守城小轩11 天前
Chromium127编译指南 Mac篇(六)- 编译优化技巧
chrome·chrome devtools·指纹浏览器·浏览器开发