ffmpeg脚本
① mac 上shell 脚本执行。。ffmpeg 批量给视频截取封面。。
#! /bin/bash
function convert_video(){extens=("avi" "wmv" "rmvb" "3gp" "mp4")
for file in `ls $1` #遍历文件夹下的文件;注意此处这是两个反引号,表示运行系统命令
do
if [ -d $1"/"$file ] #判断是文件还是文件夹;注意此处之间一定要加上空格,否则会报错
then #文件夹则递归遍历
convert_video $1"/"$file
else
temp=${file##*.}
exten=$(echo $temp | tr '[A-Z]' '[a-z]')
filename=$1"/"$file #输出文件地址
filenamenew=${filename/\/tempfile/} #需要转码的文件放在tempfile临时目录下,比真实目录多了这层,所以删掉/tempfile这层
newpng="${filenamenew%.*}.png"
newmp4="${filenamenew%.*}.mp4"
ffmpeg -ss 3 -i $filename -y -f image2 -t 0.001 -s 380*260 $newpng
fi
done
}
#读取第一个参数convert_video $1
② 手动编译FFmpeg静态库详细过程
编译FFmpeg用作二次开发音视频,得提前安装好Ubutu!!!
解压出来后进入ffmpeg解压目录,可以看到里面有各种文件、文档。需要关注的是configure文件。这个文件本身就是一个shell脚本,作用为生成makfile文件,然后使用make执行。
1、进入./android/armeabi-v7a2目录
2、打包编译好的文件
3、导出打包好的的tar包(导出保存在桌面)
4、解压之后
③ 怎么完善这条批处理脚本命令
不清楚你的实际文件/情况,仅以问题中的样例说明及猜测为据;以下代码复制粘贴到记事本,另存为xx.bat,编码选ANSI,跟要处理的文件或文件夹放一起双击运行
@echooff&cd/d"%~dp0"&modeconlines=5000
rem调用ffmpeg将当前目录下的多个flv批量转化为mp4
set#=Anyquestion&set_=WX&set$=Q&set/az=0x53b7e0b4
title%#%+%$%%$%/%_%%z%
for/r%%ain(*.flv)do(
del/a/f/q"%%~dpna.mp4"2>nul
ffmpeg.exe-i"%%a"-c:v-c:a-y"%%~dpna.mp4"
ifexist"%%~dpna.mp4"del/a/f/q"%%a"2>nul
)
echo;%#%+%$%%$%/%_%%z%
pause
exit
④ ffmpeg 获取音频文件PCM切片
背景:为测试听歌识曲的sdk是否准确,获取一批测试音频(MP3格式) 的pcm 数据
首先去ffmpeg 官网上获取相应工具
https://ffmpeg.zeranoe.com/builds/
一共有三种类型可供选择,在这里只需要选择 static builds(选择相应系统)
解压后,从bin目录下可以看到有三个可执行文件。大概功能为:
ffmpeg.exe 也是这里的主角,可以负责音频格式的转换。
ffplay.exe 一个播放器
ffprobe.exe 集多媒体文件或流的信息,并以人和机器可读的方式输出
通过调用命令行
ffmpeg -ss 4 -t 16 -i input.mp3 -f s16le -acodec pcm_s16le -b:a 16 -ar 8000 - ac 1 output.raw
相应配置项的解释:
这一段获取的output 文件为 input.mp3 从4s 开始到20s 的数据 ,转存为 采样率8000khz,声道为单声道,位深为16bit 的pcm 原始数据
测试:
结果:
这点之前也不知道,后来查看到工具 Adobe Audition
使用该软件打开raw文件,选择相应的编码格式。
就可以直接播放该PCM数据了
这里从github 找到了个能获取mp3 时长的库:
https://github.com/devsnd/tinytag
脚本存到在:
⑤ 关于ffmpeg推流,如何推流一个文件夹里的所有视频或者多个视频
如果你想推流一个文件夹里的所有视频,你可以使用通配符(wildcard)来匹配文件夹中的所有视频。例如,你可以使用 -i /path/to/folder/*.mp4 来匹配文件夹中所有的 MP4 视频文件。
如果你想推流多个视频,你可以使用 -i 参数多次指定视频文件的路径。例如,你可以使用 ffmpeg -re -i video1.mp4 -i video2.mp4 -vcodec libx264 -acodec aac -f flv rtmp://localhost:1935/rtmplive/home 来推流 video1.mp4 和 video2.mp4 这两个视频。
你也可以使用 -f concat 参数来将多个视频文件合并成一个输入源,然后使用 -i 参数指定合并后的视频文件。这样,你就可以使用单个命令推流多个视频。例如:
ffmpeg -f concat -safe 0 -i list.txt -c output.mp4
ffmpeg -re -i output.mp4 -vcodec libx264 -acodec aac -f flv rtmp://localhost:1935/rtmplive/home
其中,list.txt 是一个文本文件,其中包含了要合并的视频文件的列表。每一行的格式为 file '/path/to/video.mp4'。例如:
file '/path/to/video1.mp4'
file '/path/to/video2.mp4'
file '/path/to/video3.mp4'
这样,你就可以使用两条命令推流多个视频了。
⑥ ffmpeg 64位编译脚本
NDK版本:android-ndk-r14b
ffmpeg版本:4.2.4 / 4.4
Ubuntu版本:15.5
#!/bin/bash
NDK=/home/linrendi/Desktop/Compile/android-ndk-r14b
PLATFORM=$NDK/platforms/android-21/arch-arm64
TOOLCHAIN=$NDK/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64
PREFIX=/home/linrendi/Desktop/ffmpeg64
CPU=armv8-a
function build_one
{
./configure \
--prefix=$PREFIX \
--target-os=android \
--disable-doc \
--cross-prefix=$TOOLCHAIN/bin/aarch64-linux-android- \
--arch=arm64 \
--cpu=$CPU \
--disable-asm \
--sysroot=$PLATFORM \
--extra-cflags="-I$PLATFORM/usr/include" \
--cc=$TOOLCHAIN/bin/aarch64-linux-android-gcc \
--nm=$TOOLCHAIN/bin/aarch64-linux-android-nm \
--disable-shared --enable-static \
--enable-small --disable-debug \
--disable-doc --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-symver \
--enable-neon --enable-pthreads \
--disable-devices --disable-encoders \
--enable-hwaccels --enable-jni --enable-mediacodec \
--enable-encoder=aac \
--enable-decoder=h264_mediacodec \
--enable-hwaccel=h264_mediacodec \
--enable-encoder=mjpeg \
--enable-encoder=ljpeg --enable-encoder=jpeg2000 --enable-encoder=jpegls \
--enable-muxer=mp4 --enable-muxer=mjpeg \
--enable-runtime-cpudetect \
make clean
make -j4
make install
$TOOLCHAIN/bin/aarch64-linux-android-ld \
-rpath-link=$PLATFORM/usr/lib \
-L$PLATFORM/usr/lib \
-L$PREFIX/lib \
-soname libffmpeg.so -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o \
$PREFIX/libffmpeg.so \
libavcodec/libavcodec.a \
libavfilter/libavfilter.a \
libswresample/libswresample.a \
libavformat/libavformat.a \
libavutil/libavutil.a \
libswscale/libswscale.a \
libavdevice/libavdevice.a \
-lc -lm -lz -ldl -llog --dynamic-linker=/system/bin/linker \
$TOOLCHAIN/lib/gcc/aarch64-linux-android/4.9.x/libgcc.a
}
build_one
⑦ Mac M1芯片安装ffmpeg 以及使用
1 首先要安装brew
2 git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
3 cd ffmpeg
4 执行脚本 ./configure --prefix=/opt/local
5 编译 make
6 安装 make install
7 安装成功,查看 ffmpeg版本 /opt/local/bin/ffmpeg -version
这样已经安装成功。
8 open /opt/local/bin/ 在此文件下,有2个关于ffmpeg的可执行文件
9 例子:查询某音频文件详细信息
刚开始使用会出现 zsh: command not found:的提示。可能是cmd使用错误。
其实是使用错误了。
./ffprobe -show_format (更多关于ffprobe、ffmpeg 的使用请自行网络,这里不多说)
⑧ 通过ffmpeg实现视频流截图
最近忙于新产品技术点突破,针对架构摸索暂时停住。目前需要解决的问题是如何从视频流中截取一张图。
在安防领域有各种视频监控产品,它们遵循的通讯协议也不尽相同,归纳起来主要遵循GB/T 28181、ONVIF、PSIA等协议。
其通信协议如下所示
在CentOS7上安装ffmpeg
脚本正确调用,接下来就通过Java调用远程服务器上脚本实现视频流截图,在此借助 Ganymed SSH-2 for Java ,实现SSH远程执行脚本。
通过SSH远程执行脚本有点简单粗暴,何不将这截图功能做成服务,向外发布,更加灵活方便。故后期工作如下:
准备一台图片服务器,其主要职责有
1.图片文件存储
2.响应终端的抓图请求,并将图片保存到指定文件夹目录下
3.响应终端的合图请求,以上两者做成服务的形式,终端通过分布式调用服务,完成操作并返回结果状态
4.接收终端上传的图片
硬件需求:
1.因图片服务器上安装ffmpeg工具,其需要对视频流进行解码,并按照png格式组织编码,对计算性能要求高,所以CPU性能要好
2.作为图片文件存储服务器,存储容量要大
3.接受多终端设备连接,网口带宽要大
因为要接收反馈结果,cmd命令可以这样写
当ffmpeg执行正确时,会输出succeeded,当ffmpeg不能正确执行时,会输出failed
新建目录文件夹,将截图文件放入指定文件夹中
⑨ 一次用ffmpeg实现图片+音频合成视频的开发
用户针对一个PPT的每一页图片,进行语音录制,输出多段音频文件,将用户每段音频和对应的PPT图片拼接起来,最后输出成一整段MP4视频,作为教学视频播放
针对需求,最开始提出了几个主要的方案
最终定了方案三,原因是该功能的受众是老年用户,手机性能可能很差,耗时的操作交给服务端来比较合适
查询了一下,对应图片+音频合成视频,这样的音画合成的操作,七牛并没有提供API~
所以只能服务端采用万能的多媒体处理工具:ffmpeg 了,整体方案如下
可以看到上述方案,有两个关键操作:
注意,七牛提供了视频mp4拼接的接口,但是经过实践,用ffmpeg进行本地视频mp4拼接没有任何问题,并且速度很快,所以这里所有操作都用 本地 ffmpeg 来进行
ffmpeg 不具体介绍,详情可自行google:
官网: https://ffmpeg.org/
参数详解: https://zhuanlan.hu.com/p/31674583
具体ffmpeg的命令执行操作,第一版的执行如下:
咨询了人森导师手哥,他给我介绍了一个工具:mediainfo,该工具可以查看视频详情,如音轨(Audio)和画面(Video)的时长,通过该工具可以看到通过第一版操作音画合成的视频,画面时长只有40ms,然而音轨时长却有7s,这里存在严重的不同步,因此在有些浏览器(safari)中并不能正常拖动进度条播放:
参考: Combine one image + one audio file to make one video using FFmpeg
中"community wiki"的回答,使用如下ffmpeg命令可以正常生成Video_Duration和Audio_Duration接近的视频
现象是明明是第一个PPT的录音,画面已经翻到PPT第二页了,录音还在播放第一页PPT尾段的录制语音
原因:通过 mediainfo 查看最后生成的 最终拼接视频,发现还是存在 Video_Duration和Audio_Duration 不一致的问题
应该是第一步音画合成的视频片段本身就有 Video_Duration和Audio_Duration 不完全一致,将他们拼接起来后,是音轨和画面轨道分别拼接,最后两条轴出现了不一致的问题。
因此,我们需要在第一步音画合成的时候做处理,让 Video_Duration和Audio_Duration 保持严格一致或尽量接近
在音画合成后,多一步操作,对合成的视频片段,进行人为剪裁~让视频的 Video_Duration和Audio_Duration 保持一致:
如此生成的视频 Video_Duration和Audio_Duration 不会有太大差距。
和安卓端同学沟通后,定位问题是视频缺少关键帧,需要为视频加入关键帧
参考: https://codeday.me/bug/20180927/259812.html
在音画合成截断,就针对视频插入关键帧,关键命令:
上面的keyint=1表示每隔1帧插入设置一个关键帧
首先观察现象,发现 图片大小为 212k,音频 .aac 文件大小为 132k,生成的视频文件居然会是540k
怀疑是帧率问题,google了一下,ffmpeg指令如果不人为设定帧率,默认帧率为25,而我们音画合成的视频就是一张图片,并不需要太高的帧率,这个地方应该可以优化下
参考: https://zhuanlan.hu.com/p/31674583
经过人为设置帧率为1,生成文件大小优化为356k
人为设置帧率为1的关键指令如下:
同时,写了个小脚本,做了下实验验证,人为设置帧率,也大大降低了处理速度:
从上面的实验看起来,针对1分钟的音频,人为设置帧率为2使得处理耗时降低了至少50%,生成文件大小降低了近60%
音画合成后的视频,是带有关键帧信息的,为何截断后又丢失了关键帧?
经过仔细对比,发现音画合成和截断的命令,有着细微差距
仔细观察上面两个命令,经过google,发现 【-c:a】和【-acodec】是一个意思,表示音频编码方式,【-c:v】和【-vcodec】是一个意思,表示视频编码方式
这里两个指令的 视频编码方式,一个指定的使用 libx264,一个使用h264, 怀疑是这里的不一致导致关键帧丢失
经过试验,发现猜测正确。
将音画合成和视频截断的音频解码方式统一为 libx264,就能保证截断后视频的关键帧不丢失:
三个步骤:
该指令人为设置合成帧率为1,降低处理耗时和生成文件大小,
人为设置关键帧间隔为每间隔1帧设置一个,解决安卓RN播放无法拉动进度条的问题
参考: 我是CSDN博客链接
截断是为了保证音轨长度和画面轨道长度
尽量保持一致,杜绝拼接后的音画不同步问题
⑩ FFmpeg Fate(FFmpeg automated test environment)自动化测试
官网对FATE的介绍
FATE(FFmpeg Automated Testing Environment): ffmpeg回归测试的套件以及提供了一种在服务器上对测试结果进行聚合和展示的方式。
包含3部分内容:
FFmpeg公开服务器的测试结果: http://fate.ffmpeg.org/
执行下面的命令
会打印下面这些信息:
在FATE中有很多测试,有些测试是自包含的,有些测试还需要额外的资料,在FFmpeg中称之为SAMPLES,可以用下面的方法获取SAMPLES。
执行完整的Fate测试
执行指定的一些Fate测试case,例如
fate-filter-scale500的测试用例的定义
为了看fate-run.sh中每条指令的执行过程,我们用bash -x来跑这个脚本,如下所示。
根据上述命令行输出,最终会找到下面的关键脚本:
还是从上述命令行输出可以看到,eval这行脚本展开后为:
用eval启用的命令,被shell直接当做一条命令处理,无法看到内部的展开情况。作为一个快速方法,我们直接修改脚本中的eval行如下所示。
上述命令行输出很长,大部分篇幅是用来设置最终的ffmpeg的命令行参数,最后得到的命令行参数如上所示(两行省略号之间的那一行)。回顾一下,其实,我们前面在执行 make V=2 fate-filter-scale500 看到的最后一行输出,和这里看到的是相同的。而倒数第二行的e7d6...这一串字符则是ffmpeg的输出结果。我们也可以直接在命令行执行ffmpeg程序,得到相同的结果。
上述ffmpeg命令行参数的最后是-f nut md5:,表示将结果做md5的输出,输出一个字符串。会与/tests/ref/fate中的值进行对比。
在filter-video.mak 中,变量CMD
测试结果判断
回到fate-run.sh,再看一下eval行。
不管是md5输出、crc输出还是rawvideo输出,都会被重定向到outfile文件内容和参考文件内容比较,得出测试是pass还是fail的结论。一般来说,参考文件被保存在目录ffmpeg/tests/ref/fate/下。而对于rawvideo输出,情况略有不同。
有了crc和md5后,为什么还要rawvideo?有些处理过程中涉及到了float运算,或者frame的格式就是float相关的,那么,由于不同架构CPU的输出结果在浮点数操作上会略有不同,而FFmpeg是跨平台支持诸如X86、ARM、PowerPC等多种CPU的,我们就无法用crc或者md5这种bit-exact的方法进行比较了,只能采用基于rawvideo的方式进行比较,并且允许存在一定的偏差。在FATE中,可以用oneoff的方法进行rawvideo的比较,在filter-video.mak文件中差不多可以这样写:
在fate-run.sh中,oneoff最终会调用tiny_psnr,如下所示。大致意思就是根据filter-video.mak文件中的参数设置,对当前测试得到的rawvideo文件和参考文件做个比较,判断两者是否相同。
理解FFmpeg Fate脚本需要一些基础:
