前言
大多数获取视频的封面都是使用FFMpeg获取视频的第一帧,但是很多视频第一帧是纯黑的,我们就要取后面的帧,这时候我们就要知道视频本身有多长。
获取视频时长
容器时长(container duration)的获取方法:
代码语言:javascript复制ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 -i a.mp4
音视频流时长(stream duration)的获取方法:
代码语言:javascript复制ffprobe -v error -select_streams v:0 -show_entries stream=duration -of default=noprint_wrappers=1:nokey=1 a.mp4
一个媒体文件里边有多个音视频流,各个流的时长也未必一样,一般播放器会以video stream的时长作为播放时长。
生成封面
代码语言:javascript复制ffmpeg -i a.mp4 -y -f image2 -ss 2 -frames 1 a001.jpg
方式2
代码语言:javascript复制ffmpeg -i a.mp4 -y -f image2 -ss 2 -t 0.001 a002.jpg
-ss 从几秒开始
NodeJS调用
代码语言:javascript复制let cp = require('child_process');
const execGetSec = (pathFile) => {
const cmd = `ffprobe -v error -select_streams v:0 -show_entries stream=duration -of default=noprint_wrappers=1:nokey=1 ${pathFile}`
console.log('当前指令:', cmd)
cp.exec(cmd, (err, stdout, errout) => {
if (!err) {
console.log('结果:', stdout)
}
})
}
const execJpg = (pathFile, saveFilePath) => {
const cmd = `ffmpeg -i ${pathFile} -y -f image2 -ss 2 -frames 1 ${saveFilePath}`
console.log('当前指令:', cmd)
cp.exec(cmd, (err, stdout, errout) => {
if (!err) {
console.log(`${saveFilePath} success...`)
}
})
}
execGetSec("D:\Video\a.mp4");
// execJpg("D:\Video\a.mp4", "D:\Video\a002.jpg");
封装
代码语言:javascript复制let cp = require('child_process');
const execGetSec = (pathFile) => {
return new Promise(((resolve) => {
const cmd = `ffprobe -v error -select_streams v:0 -show_entries stream=duration -of default=noprint_wrappers=1:nokey=1 ${pathFile}`
cp.exec(cmd, (err, stdout, errout) => {
if (!err) {
resolve(parseInt(stdout))
} else {
resolve(0);
}
})
}))
}
const execJpg = (pathFile, saveFilePath) => {
return new Promise(((resolve, reject) => {
const cmd = `ffmpeg -i ${pathFile} -y -f image2 -ss 2 -frames 1 ${saveFilePath}`
cp.exec(cmd, (err, stdout, errout) => {
if (!err) {
resolve(saveFilePath);
} else {
resolve("")
}
})
}))
}
const execJpgByTime = (pathFile, saveFilePath) => {
return new Promise((async (resolve, reject) => {
let sec = await execGetSec(pathFile);
let fromSec = 0;
if (sec > 5) {
fromSec = 5;
} else {
fromSec = sec / 2;
}
const cmd = `ffmpeg -i ${pathFile} -y -f image2 -ss ${fromSec} -frames 1 ${saveFilePath}`
cp.exec(cmd, (err, stdout, errout) => {
if (!err) {
resolve(saveFilePath);
} else {
resolve("")
}
})
}))
}
async function main() {
let sec = await execGetSec("D:\Video\a.mp4");
console.info(sec);
let path = await execJpg("D:\Video\a.mp4", "D:\Video\a_001.jpg");
console.info(path);
let path2 = await execJpgByTime("D:\Video\a.mp4", "D:\Video\a_002.jpg");
console.info(path2);
}
main();
导出/导入
代码语言:javascript复制let cp = require('child_process');
const execGetSec = (pathFile) => {
return new Promise(((resolve) => {
const cmd = `ffprobe -v error -select_streams v:0 -show_entries stream=duration -of default=noprint_wrappers=1:nokey=1 ${pathFile}`
cp.exec(cmd, (err, stdout, errout) => {
if (!err) {
resolve(parseInt(stdout))
} else {
resolve(0);
}
})
}))
}
const execJpgByTime = (pathFile, saveFilePath) => {
return new Promise((async (resolve, reject) => {
let sec = await execGetSec(pathFile);
let fromSec = 0;
if (sec > 5) {
fromSec = 5;
} else {
fromSec = sec / 2;
}
const cmd = `ffmpeg -i ${pathFile} -y -f image2 -ss ${fromSec} -frames 1 ${saveFilePath}`
cp.exec(cmd, (err, stdout, errout) => {
if (!err) {
resolve(saveFilePath);
} else {
resolve("");
}
})
}))
}
exports.execJpgByTime = execJpgByTime;
导入
代码语言:javascript复制const {
execJpgByTime
} = require("./coverUtil.js")
CentOS安装ffmpeg
yum安装
首先更新系统。
代码语言:javascript复制sudo yum install epel-release -y
sudo yum update -y
安装Nux Dextop Yum 源
由于CentOS没有官方FFmpeg rpm软件包。但是,我们可以使用第三方YUM源(Nux Dextop)完成此工作。
CentOS 7
代码语言:javascript复制sudo rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
sudo rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm
CentOS 6
代码语言:javascript复制sudo rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
sudo rpm -Uvh http://li.nux.ro/download/nux/dextop/el6/x86_64/nux-dextop-release-0-2.el6.nux.noarch.rpm
安装FFmpeg 和 FFmpeg开发包
代码语言:javascript复制sudo yum install ffmpeg ffmpeg-devel -y
测试是否安装成功
代码语言:javascript复制ffmpeg
ffprobe
Docker内不要添加sudo
代码语言:javascript复制# 安装ffmpeg
RUN yum install epel-release -y
RUN yum update -y
RUN rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
RUN rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm
RUN yum install ffmpeg ffmpeg-devel -y
编译安装
先下载源码包:
代码语言:javascript复制git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
然后进入ffmpeg文件夹,依次执行下列语句,当然连起来也可以:
代码语言:javascript复制cd ffmpeg
./configure
make && make install
时间较长,不出意外会正常安装好。
但是因为configure时候没有指定路径,所以直接ffmpeg会提示找不到。
所以要将编译好的ffmpeg复制到bin目录即可:
代码语言:javascript复制cp ffmpeg /usr/bin/ffmpeg
然后检查版本。
代码语言:javascript复制ffmpeg -version