2 月 16 日凌晨 OpenAI 发布了文本生成视频的新应用模型 Sora,是 OpenAI 首个视频生成模型,拥有与 DALL·E 3 的画面质量以及指令能力,该模型可以帮助用户通过简单的文本描述视频中的内容,即可在短时间内得到一个分钟级别的视频素材。
既然音视频现如今这么火,那么为何我们不赶紧学起来,拥抱未来。说起音视频,那必然不能少了 ffmpeg 啦。
什么是 ffmpeg
FFmpeg 是一个开源的跨平台多媒体框架,它能够解码、编码、转换、封装、解封装、流、过滤和播放几乎所有格式的视频和音频文件。由于其强大的功能和灵活性,FFmpeg 被广泛应用于各种应用程序和服务中,包括视频转换和处理、流媒体服务、媒体播放器以及更多的专业媒体生产和处理工具中。
ffmpeg 能用来干什么
ffmpeg 的应用场景可就多了,下面列举几个例子吧:
-
音视频转码:将不同格式的音视频文件转换为适合特定设备和需求的格式。
-
视频剪辑和合并:允许用户对视频进行剪辑、合并操作,甚至从视频中提取音频部分。
-
视频处理:提供视频裁剪、旋转、缩放、改变帧率、添加水印等功能。
-
流媒体传输:能够实时地将音视频内容传输到网络上,常用于直播和视频会议。
-
音频处理:进行音频的剪辑、混音、音量调节、降噪、去除静音等操作。
除了我们提到的这些功能之外,还有很多很多可以实现的。
如何在 MacOS 中安装 ffmpeg
在 macOS 上安装 FFmpeg,最简单和最常用的方法是使用 Homebrew,并使用以下命令通过 Homebrew 安装 FFmpeg:
bash
brew install ffmpeg
安装完成后,你可以通过运行以下命令来验证 FFmpeg 是否成功安装:
bash
ffmpeg -version
如果看到了 FFmpeg 的版本信息,那么恭喜你,FFmpeg 已经成功安装在你的 macOS 上了。
使用 ffmpeg 实现视频转 gif 图
因为这都是我在日常中遇到的场景,所以我会很推荐有兴趣的都可以来学习一下 ffmpeg。
首先我写的文章都会发布到掘金上面,但是掘金上面只能发 gif 和图片两种,听说现在可以嵌入西瓜视频,让我去另外一个平台注册一个账号再上传视频进行嵌入那必是不可能的事情。
所以这个时候 ffmpeg 就派上用场了,其实 ffmpeg 也支持在终端中执行命令来执行,但是这样看起来会很高端,接下来我们就用低端一点的吧,用 nodejs 来使用代码实现这个我想要的功能。
首先,我们要安装一个依赖包,它是 fluent-ffmpeg,它是一个基于 Node.js 的库,它提供了一个高级的 API 来操作 ffmpeg,使得在 Node.js 应用程序中使用 ffmpeg 变得更加容易和直观。通过 fluent-ffmpeg,开发者可以在 JavaScript 代码中方便地构建复杂的 ffmpeg 命令,执行视频和音频的编解码、转换等操作。
fluent-ffmpeg 本身并不包含 ffmpeg 的二进制文件。它是一个接口库,用于在 Node.js 环境中更加方便地调用已安装的 ffmpeg 功能。因此,要在项目中使用 fluent-ffmpeg,你首先需要确保系统上已经安装了 ffmpeg。
js
const ffmpeg = require("fluent-ffmpeg");
function convertVideoToGif(videoPath, gifPath, callback) {
ffmpeg(videoPath)
.outputOptions([
"-vf",
"fps=10,scale=1080:-1:flags=lanczos",
"-c:v",
"gif",
"-f",
"gif",
])
.save(gifPath)
.on("end", function () {
console.log("转换完成");
callback(null);
})
.on("error", function (err) {
console.log("转换出错: " + err.message);
callback(err);
});
}
convertVideoToGif("./m.mp4", "./moment.gif", (err) => {
if (err) return console.error(err);
console.log("GIF文件已创建");
});
在上面的这些代码中,首先传入源文件路径调用 ffmpeg 方法,.outputOptions([...])
用于设置转换过程中的一系列参数:
-
fps=10:设置输出 GIF 的帧率为 10 FPS(每秒帧数)。
-
scale=1080:-1:flags=lanczos:设置输出 GIF 的宽度为 1080 像素,高度自动调整以保持原始视频的宽高比。flags=lanczos 是一种缩放算法,用于改善图像质量。
-
c:v gif:设置视频编码器为 GIF。
-
f gif:指定输出格式为 GIF。
这些都完成之后,我们继续链式调用 sava 方法并传入输出的路径,这样我们就可以接收到文件了。之后我们使用 node 执行该代码就可以生成我们想要的 gif 图了:
使用 ffmpeg 将 MP4 转换成 avi 文件
转换文件类型的这个倒是还没有遇到过,但是人家确实是能做这个事情:
js
const ffmpeg = require("fluent-ffmpeg");
function convertMp4ToAvi(sourcePath, destinationPath, callback) {
ffmpeg(sourcePath)
.toFormat("avi")
.on("end", function () {
console.log("转换完成!");
callback(null);
})
.on("error", function (err) {
console.log("转换失败: " + err.message);
callback(err);
})
.save(destinationPath);
}
convertMp4ToAvi("./m.mp4", "./moment.avi", (err) => {
if (err) {
console.error("转换过程中发生错误:", err);
} else {
console.log("转换成功!");
}
});
在上面的代码中就没有啥特别的点,就链式调用了 .toFormat('avi')
方法设置输出格式为 AVI。
在终端上执行该文件,也正常输出了:
文件是没问题的。
生成视频的缩略图
缩略图为用户提供视频内容的快速预览,帮助他们判断视频是否符合他们的兴趣或需求。在视频列表或搜索结果中,缩略图是用户决定是否点击观看的关键因素之一。
js
const ffmpeg = require("fluent-ffmpeg");
function generateThumbnails(videoPath, options, callback) {
ffmpeg(videoPath)
.screenshots({
count: options.count, // 指定生成的缩略图数量
folder: options.folder, // 缩略图的保存目录
filename: options.filename, // 缩略图文件名模式
size: options.size, // 缩略图的尺寸
})
.on("end", function () {
console.log("缩略图生成完成");
callback(null);
})
.on("error", function (err) {
console.log("缩略图生成失败: ", err.message);
callback(err);
});
}
const options = {
count: 5, // 生成5张缩略图
folder: "./moment", // 缩略图的保存目录
filename: "moment-%i.png", // 缩略图文件名模式,%i 会被替换为缩略图的索引
size: "1080x960", // 缩略图的尺寸
};
generateThumbnails("./m.mp4", options, (err) => {
if (err) {
console.error("缩略图生成过程中发生错误:", err);
} else {
console.log("缩略图生成成功!");
}
});
在上面的这些代码中,通过通过 ffmpeg(videoPath) 加载指定路径的视频文件。调用 .screenshots 方法,并传入一个配置对象来指定如何生成缩略图。配置对象中包括:
-
count: 指定要生成的缩略图数量。
-
folder: 设置缩略图的保存目录。
-
filename: 定义缩略图文件的命名模式。%i 为占位符,会被替换成缩略图的索引。
-
size: 指定缩略图的尺寸。
最终使用 node 执行该文件,会有以下输出:
这样我们就实现了从指定视频文件生成指定数量和尺寸的缩略图的功能,并将这些缩略图保存在指定的目录中。
总结
在上面的几个 demo 中,我们简单地举例说明了作为一个前端,我们能用 ffmpeg 来实现了一些简单的功能,这也说明了,这不是后端的东西,只是一个工具,我们也可以使用它来实现一些功能来满足我们的需求。
最后可能会打算结合 ffmpeg 和 webRtc 来实现一些商业项目,如果你也感兴趣,欢迎交流。