ffmpeg
有很多插件、js库,这里介绍ffmpeg-static
、fluent-ffmpeg
、ffmpeg.wasm
在 纯前端实现 vue 利用ffmpeg.wasm将图片合成视频 这篇文章的gitHub代码中,vite.config.js
进行了如下配置:
server: {
// host: '0.0.0.0', //只能使用localhost
//处理ffmpeg的SharedArrayBuffer is not defined
headers: {
"Cross-Origin-Embedder-Policy": "require-corp",
"Cross-Origin-Opener-Policy": "same-origin",
},
},
如果你的项目中使用了阿里云存储图片,两者会有冲突,同源隔离的错误,我没解决了。。。
其次这个案例中使用的ffmpeg.FS
同时只能执行一次,我没有过多研究。。。不建议使用
https://github.com/fluent-ffmpeg/node-fluent-ffmpeg
这是一个js库,ffmpeg
阉割版,和直接使用命令行相比差很多,很多命令都不能实现。比如实现“图片转带有静音音频的视频”,“多视频合并”都不能正常实现。即使是最简单的“图片转视频”也可能会报错!不建议使用
ffmpeg-static
可以让哦们使用ffmpeg
命令
安装
npm i ffmpeg-static
在node
环境下使用ffmpeg
命令
electron/main/index.ts
import { exec } from "child_process";
const ffmpegInstaller = require("ffmpeg-static");
const command = `${ffmpegInstaller} -version`
exec(command, (error, stdout, stderr) => {
if (error) {
console.log(error);
} else {
console.log(stdout);
console.log("------------------");
console.log(stderr);
}
})
当你的项目使用electron-builder
打包后,你会发现ffmpeg-static
不好使了,因为路径不对了。
如果你在打包后的项目控制台打印ffmpegInstaller
(见上述代码)是这样:
// 为了观看不同处, 手动换行
C:\Usersl31957\AppData\Local\programs\k8-video-analysis-web\resources\
app.asar
\node _modules\ffmpeg-static\ffmpeg.exe
但实际路径是:
// 为了观看不同处, 手动换行
C:\Users\31957\AppData\Local\Programs\k8-video-analysis-web\resources\
app.asar.unpacked
\node_modules\ffprobe-static\ffmpeg.exe
我在网上看了很多文章,也有这个问题。在npm ffmpeg-static
官网中给出的解决方案没看懂,其他文章给出的解决方案也不好使。直接用我的!
const ffmpegInstaller = require("ffmpeg-static");
// 直接替换
let ffmpegInstallerPath = ffmpegInstaller.replace("app.asar", "app.asar.unpacked");
就是手动更换一下
在本地项目中,是不会有resources
这个文件的,所以只会在生产环境替换,如果你不放心也可以自己加一个判断
ffmpeg安装教程(windows版)
为了方便测试你的操作是否正确,可以将下载ffmpeg
,在cmd
中直接使用命令
const thisCommand = `${ffmpegInstaller} -loop 1 -i "${inputPath}" -t ${videoTime} -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 -vf scale=1280:720 -c:v libx264 -pix_fmt yuv420p -y -c:a aac -shortest "${outputVideoName}.mp4"`;
ChatGPT生成的命令。说几个要注意的地方:
-vf scale=1280:720
:设置视频分辨率。如果图片的宽高有奇数,那么转换会报错
-vf scale=640:-2
改变视频分辨率,缩放到640px宽,高度的-2是考虑到libx264要求高度是偶数,所以设置成-2,让软件自动计算得出一个接近等比例的偶数高
"inputPath"
:是一个本地绝对路径。可能你的路径是“C:\Users\xy\Pictures\Saved Pictures",其中“Saved Pictures”纯在空格,导致无法正确的找到路径,所以要加上引号
使用URl:inputPath
也可以是url,图片案例https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png。最开始我用的逻辑是将url保存到本地然后再转格式。保存这里除了使用ffmpeg
也是使用其他方法比如curl
。但是我没有在转换格式命令中尝试。
let saveLocalPath = `${ffmpegInstaller} -i ${inputPath} ${outputImgName}`;// 将图片保存到本地
ffmpeg合并多个MP4视频
除了这篇文章写的,还有其他方法,可以参考 FFmpeg教程(超级详细版)或者直接阅读官网文档
ffmpeg中文网
我使用的是第一篇文章中的第三种:
直接将多个MP4直接拼接成一个MP4
1、将合并的文件夹都放在同一个文件夹下,例如:test.mp4,test2.mp4
2、新建一个video.txt文件,文件的内容是需要合并的视频名称,内容格式为
file C:\/Users\/xy\/Videos\/temp_81el8n.mp4 file 'C:\/Users\/xy\/Videos\/temp_81el8n.mp4'
3、执行ffmpeg的命令
ffmpeg -f concat -i video.txt -c copy concat.mp4
注意:video.txt
中文件的路径写法,对于win和mac文件路径的拼接是不同的。
如果你在项目获取得的路径是C:\\Users\\xy\\Videos\\temp_81el8n.mp4
或者C:\Users\sc\Videos\temp_81el8n.mp4
,需要手动转换格式
'C:\/Users\/xy\/Videos\/temp_81el8n.mp4'
'/Users/xy/Videos/temp_81el8n.mp4'
electron/main/index.ts
const cachePath = app.getPath("videos");
function selectDirectory(arg) {
dialog
.showSaveDialog({
title: "保存视频",
defaultPath: path.join(desktopDir, "视频.mp4"),
buttonLabel: "保存",
filters: [{ name: "Movies", extensions: ["mp4"] }],
})
.then((file) => {
if (!file.canceled) {
console.log(file.filePath, "pathpath"); // 选择的文件夹路径
concatVideos(arg, file.filePath);
// mergeVideos(arg, file.filePath);
}
})
.catch((err) => {
console.error(err);
});
}
// 合并视频
function concatVideos(mergeList, concatPath) {
let localUrl = mergeList.map((url) => {
let outputName;
// 注意路径拼接
if (process.platform === "win32") {
outputName = `${cachePath}\\temp_${Math.random()
.toString(36)
.substring(7)}.mp4`;
} else {
outputName = `${cachePath}/temp_${Math.random()
.toString(36)
.substring(7)}.mp4`;
}
let saveLocalPath = `${ffmpegInstallerPath} -i ${url} ${outputName}`;
execSync(saveLocalPath, (error, stdout, stderr) => {
if (error) {
console.log(error);
}
});
return outputName;
});
let videoCancatFileUrl;
if (process.platform === "win32") {
videoCancatFileUrl = cachePath + "\\videoCancatFile.txt";
} else {
videoCancatFileUrl = cachePath + "/videoCancatFile.txt";
}
let videoCancatFileWords = [];
// 转换
localUrl.forEach((fileUrl) => {
/* win 和 mac 系统路径不同
win 获取到的路径为 C:\\Users\\sc\\Videos\\temp_81el8n.mp4
ffmpeg 需要的为 C:\/Users\/sc\/Videos\/temp_81el8n.mp4
mac 获取到的路径为 /Users/mmmddd/Movies\temp sc30ye.mp4
ffmpeg 需要的为 /Users/mmmddd/Movies/temp sc30ye.mp4
*/
let str;
if (process.platform === "win32") {
str = fileUrl.replace(/\\/g, "\\/");
} else {
str = fileUrl.replace("\\", "/");
}
videoCancatFileWords.push(`file '${str}'`);
});
console.log(videoCancatFileUrl, "333333333333");
fs.writeFileSync(videoCancatFileUrl, videoCancatFileWords.join("\n"));
const concatCommand = `${ffmpegInstallerPath} -f concat -safe 0 -i ${videoCancatFileUrl} -y -c copy ${concatPath}`;
execSync(concatCommand, (error, stdout, stderr) => {
if (error) {
console.log(error);
}
});
localUrl.forEach((file) => {
fs.unlinkSync(file);
});
fs.unlinkSync(videoCancatFileUrl);
}
转换后的视频使用mac默认的播放器 QuickTime Player 会出现,建议更换播放器或者自己调试ffmpeg参数
3-electron-builder-如何将ffmpe集成到Electron中