学习node.js 四 ffmpeg,events,util

目录

ffmpeg

1. 下载

2. 安装

3. 使用

(1) 将视频转为gif

 (2) 添加水印

 (3) 去除水印

 (4) 提取音频

(5) 裁剪视频

EventEmitter

代码案例

常用的util API

1. util.promisify

2. util.callbackify

3. util.format


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. 使用

  1. 格式转换:FFmpeg 可以将一个媒体文件从一种格式转换为另一种格式,支持几乎所有常见的音频和视频格式,包括 MP4、AVI、MKV、MOV、FLV、MP3、AAC 等。
  2. 视频处理:FFmpeg 可以进行视频编码、解码、裁剪、旋转、缩放、调整帧率、添加水印等操作。你可以使用它来调整视频的分辨率、剪辑和拼接视频片段,以及对视频进行各种效果处理。
  3. 音频处理: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
 

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值