目录
ffmpeg
FFmpeg全称为Fast Forward Moving Picture Experts Group,于2000年诞生,是一款免费,开源的音视频编解码工具及开发套件。它的功能强大,用途广泛,大量用于视频网站和商业软件(比如 Youtube 和 iTunes)。
FFmpeg 本身是一个庞大的项目,包含许多组件和库文件,最常用的是它的命令行工具
1. 下载
官网下载,点击官网下载后,在release builds第一个绿框里面选择一个版本下载。
下好后解压
2. 安装
1. 下载完成后解压该压缩包,在bin文件里会有三个exe文件,复制此时的地址
2. 找到环境变量,在path里面点新建,将复制的地址粘贴进入
3.测试是否安装成功
按win+R,输入cmd打开命令行窗口,输入命令“ffmpeg –version”
如下图,就说明安装成功
3. 使用
- 格式转换:FFmpeg 可以将一个媒体文件从一种格式转换为另一种格式,支持几乎所有常见的音频和视频格式,包括 MP4、AVI、MKV、MOV、FLV、MP3、AAC 等。
- 视频处理:FFmpeg 可以进行视频编码、解码、裁剪、旋转、缩放、调整帧率、添加水印等操作。你可以使用它来调整视频的分辨率、剪辑和拼接视频片段,以及对视频进行各种效果处理。
- 音频处理:FFmpeg 可以进行音频编码、解码、剪辑、混音、音量调节等操作。你可以用它来提取音频轨道、剪辑和拼接音频片段,以及对音频进行降噪、均衡器等处理。
(1) 将视频转为gif
const {execSync} = require("child_process")
execSync("ffmpeg -i video/video1.mp4 test.gif",{stdio: 'inherit'})
(2) 添加水印
-vf 就是video filter
drawtext 添加文字 fontsize 大小 xy垂直水平方向 fontcolor 颜色 text 水印文案 全部小写
const {execSync} = require("child_process")
execSync(`ffmpeg -i video/video1.mp4 -vf drawtext=text="YIYIYIYI":fontsize=40:fontcolor=red:x=40:y=50 video/video2.mp4`,{stdio: "inherit"})
(3) 去除水印
w h 宽高
xy 垂直 水平坐标
delogo使用的过滤参数删除水印
const {execSync} = require("child_process")
execSync(`ffmpeg -i video/video2.mp4 -vf delogo=w=320:h=40:x=40:y=50 video/video3.mp4`,{stdio: "inherit"})
(4) 提取音频
const {execSync} = require("child_process")
execSync(`ffmpeg -i video/video2.mp4 video/echo.mp3`,{stdio: "inherit"})
(5) 裁剪视频
-ss 起始时间
-to 结束事件
ss写在 -i的前面可能会导致精度问题,因为视频还没解析就跳转到了相关位置,但是解析速度快
ss写在 -i后面精度没问题,但是解析速度会变慢
const {execSync} = require('child_process')
execSync(`ffmpeg -ss 10 -to 20 -i test.mp4 test3.mp4`,{stdio:'inherit'})
EventEmitter
Node.js 核心 API 都是采用异步事件驱动架构,简单来说就是通过有效的方法来监听事件状态的变化,并在变化的时候做出相应的动作。
例如,exec等
Nodejs事件模型采用了,发布订阅设计模式
当一个发布者有新消息时,就将这个消息发布到调度中心。调度中心就会将这个消息通知给所有订阅者。这就实现了发布者和订阅者之间的解耦,发布者和订阅者不再直接依赖于彼此,他们可以独立地扩展自己
代码案例
const EvenEmitter = require('events').EventEmitter;
const emitter = new EvenEmitter();
function fn(name) {
console.log(name);
}
emitter.on("test", fn);
emitter.emit("test", "hello"); // hello
只想监听一次 once 即使emit
派发多次也只触发一次once
const EvenEmitter = require('events').EventEmitter;
const emitter = new EvenEmitter();
function fn(name) {
console.log(name);
}
emitter.once("test", fn);
emitter.emit("test", "hello");
emitter.emit("test", "world");
取消侦听 off
const EvenEmitter = require('events').EventEmitter;
const emitter = new EvenEmitter();
function fn(name) {
console.log(name);
}
emitter.on("test", fn);
emitter.off("test", fn);
emitter.emit("test", "hello");
emitter.emit("test", "world");
监听消息数量默认是10个,对于10个会报错,如果非要多余10个也可以
调用 setMaxListeners 传入数量
event.setMaxListeners(20)
const EvenEmitter = require('events').EventEmitter;
const emitter = new EvenEmitter();
function fn(name) {
console.log(name);
}
emitter.setMaxListeners(20);
emitter.on("test", fn);
emitter.on("test", fn);
emitter.on("test", fn);
emitter.on("test", fn);
emitter.on("test", fn);
emitter.on("test", fn);
emitter.on("test", fn);
emitter.on("test", fn);
emitter.on("test", fn);
emitter.on("test", fn);
emitter.on("test", fn);
emitter.emit("test", "hello");
process就采用了这个设计模式
常用的util API
util 是Node.js内部提供的很多实用或者工具类型的API,方便我们快速开发。
1. util.promisify
在events里,说过,node.js 核心 API 都是采用异步事件驱动架构,遵循回调的模式去写的
例如:
exec
const {exec} = require('child_process');
exec("node -v",(error, stdout, stderr)=> {
if(error){
return console.log(`error: ${error.message}`);
}
if(stderr){
return console.log(`stderr: ${stderr}`);
}
console.log(`stdout: ${stdout}`);
})
我们使用util的promisify
改为promise 风格 Promiseify 接受 original
一个函数体
const {exec} = require('child_process');
const util = require("node:util");
const execPromise = util.promisify(exec)
execPromise("node -v").then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
手写实现 promisify
const {exec} = require('child_process');
const util = require("node:util");
const promisify = (fn) => {
return (...args) => {
return new Promise((resolve, reject) => {
fn(...args, (err, ...values) => {
if (err) {
reject(err)
} else {
if(values && values.length > 1) {
let obj = {}
values.forEach((value, index) => {
obj[index] = value
})
resolve(obj)
}else {
resolve(values[0])
}
}
})
})
}
}
const execPromise = promisify(exec)
execPromise("node -v").then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
这样可以大致实现但是拿不到values 的key 因为 nodejs内部 没有对我们开放 这个Symbol kCustomPromisifyArgsSymbol
所以输出的结果是 { '0': 'v18.16.0\n', '1': '' }
正常应该是 { stdout: 'v18.16.0\n', stderr: '' }
但是我们拿不到key,只能大概实现一下。
2. util.callbackify
这个API 正好是 反过来的,将promise类型的API变成 回调函数。
const {exec} = require('child_process');
const util = require("node:util");
function testCallbackify(type) {
if(type === 1) {
return Promise.resolve("成功的回调")
}
return Promise.reject("失败的回调")
}
const callbackify = util.callbackify(testCallbackify)
callbackify(1,(err,data) => {
if(err) {
console.log(err)
} else {
console.log(data)
}
})
手写实现 callbackify
function callbackify(fn) {
return (...args) => {
let callback = args.pop();
fn(...args).then(res => callback(null, res), err => callback(err))
}
}
3. util.format
语法 跟 C 语言的 printf
一样的
util.format(format, [args])
案例:
用 -----> 连接两个字符串
const str = util.format("%s---->%s","warn","warning")
console.log(str)
如果不传入格式化参数 就按空格分开
const str = util.format("warn","warning")
warn warning