标签:表示 版本 frame ice 3.4 高度 大量 mpi 修改文件
FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。它提供了录制、转换以及流化音视频的完整解决方案。同时,FFmpeg是一套跨平台的方案,所以我们可以在iOS开发中使用它来进行一些视频与GIF的开发。
接下来,我们从编译FFmpeg开始,到使用FFmpeg,再到使用中的一些注意事项进行总结。
在这个过程中,我们需要以下几个资源:
2.yasm
gas-preprocessor 其实就是我们要编译FFmpeg所需的脚本文件。
1).下载并解压
2).将 gas-preprocessor.pl 文件复制到 /usr/sbin/ 目录下,如果该目录无法修改,那么可将文件复制到 /usr/local/bin/ 目录下。
3).为 gas-preprocessor.pl 文件开启可执行权限,在终端中进行如下命令:
chmod 777 /usr/sbin/gas-preprocessor.pl
或
chmod 777 /usr/local/bin/gas-preprocessor.pl
yasm 是一个完全重写的 NASM 汇编。目前,它支持 x86 和 AMD64 指令集,接受 NASM 和气体汇编语法,产出二进制,ELF32,ELF64,COFF,Mach-O 的(32和64),RDOFF2的 Win32 和 Win64 对象的格式,并生成 STABS 调试信息的来源,DWARF 2 ,CodeView 8格式。
MAC上可以使用homebrew来安装:
brew install yasm
在build-ffmpeg.sh这个文件中,我们可以对要进行编译的FFmpeg进行一系列的设置。
1).设置FFmpeg的版本
FF_VERSION="3.4.2"
2).设置所要支持的架构,查找到 ARCHS 关键字
ARCHS="arm64 armv7"
3).设置所需要的FFmpeg功能配置
该设置可在 CONFIGURE_FLAGS= 中进行,通过禁用一些不必要的功能,可以有效地减小最终库文件的大小,格式如下:
禁用交叉编译:
--disable-cross-compile
支持交叉编译:
--enable-cross-compile
4).确保该脚本所在路径中不包含有空格
5).需要为该脚本所在文件夹赋予权限
chmod 777 /Users/mdm/Desktop/ffmpeg
6).进入脚本所在文件夹目录,执行脚本
./build-ffmpeg.sh
此过程可能会出现各种问题,大多数问题可以通过前往执行脚本过程中生成的 scratch 文件夹下的 config.log 中查看对应原因。
另外,如果遇到
xcrun -sdk iphoneos clang is unable to create an executable file.
C compiler test failed.
这是由于系统安装了多个Xcode环境或者没有选定指定的Xcode环境所致,可使用下面方法选定一个Xcode环境来解决问题:
sudo xcode-select -s /Applications/Xcode.app
7).脚本执行完毕,生成所需文件
ffmpeg-3.3.6 FFmpeg源文件
scratch 编译过程中生成的文件
thin 对应各个架构下的库文件
FFmpeg-iOS 合并各个架构之后的库文件
我们在使用ffmpeg时,可以直接使用该功能,通过设置命令参数,从而避免编写大量c语言代码来调用ffmpeg库。
1).从 ffmpeg-3.3.6 中找到以下文件:
ffmpeg.h
ffmpeg.c
cmdutils.h
cmdutils.c
ffmpeg_filter.c
ffmpeg_opt.c
cmdutils_common_opts.h
2).从 scratch 文件夹下随便一个架构文件夹中找到如下文件:
config.h
1).前往 cmdutils.c 文件中,注释以下内容:
#include "compat/va_copy.h" #include "libavdevice/avdevice.h" #include "libavresample/avresample.h" #include "libpostproc/postprocess.h" #include "libavutil/libm.h" PRINT_LIB_INFO(avdevice, AVDEVICE, flags, level); PRINT_LIB_INFO(avresample, AVRESAMPLE, flags, level); PRINT_LIB_INFO(postproc, POSTPROC, flags, level);
2).前往 ffmpeg_filter.c 文件中,注释以下内容:
#include "libavresample/avresample.h"
3).前往 ffmpeg.c 文件中,注释以下内容:
#include "libavdevice/avdevice.h" #include "libavutil/internal.h" #include "libavutil/libm.h" #include "libavformat/os_support.h" ff_dlog(NULL, "force_key_frame: n:%f n_forced:%f prev_forced_n:%f t:%f prev_forced_t:%f -> res:%f\n", ost->forced_keyframes_expr_const_values[FKF_N], ost->forced_keyframes_expr_const_values[FKF_N_FORCED], ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_N], ost->forced_keyframes_expr_const_values[FKF_T], ost->forced_keyframes_expr_const_values[FKF_PREV_FORCED_T], res);
同时,将 ffmpeg-3.3.6/libavcodec/mathops.h 和 ffmpeg-3.3.6/libavutil/reverse.h 两个文件复制至项目对应位置
4).前往 ffmpeg_opt.c 文件中,注释掉以下内容:
{ "videotoolbox_pixfmt", HAS_ARG | OPT_STRING | OPT_EXPERT, { &videotoolbox_pixfmt}, "" }, { "vda", videotoolbox_init, HWACCEL_VDA, AV_PIX_FMT_VDA }, { "videotoolbox", videotoolbox_init, HWACCEL_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX },
5).前往 ffmpeg.h 文件下增加函数声明:
int ffmpeg_main(int argc, char **argv);
6).修改 ffmpeg.c 文件中
int main(int argc, char **argv) 改为 int ffmpeg_main(int argc, char **argv)
7).修改 ffmpeg.c 文件中
#include "libavutil/time.h" 为
#include "libavutil/ffmpegtime.h"
同时修改 FFmpeg-iOS/include/libavutil/time.h 为 ffmpegtime.h
8).修改执行一次 ffmpeg_main 方法后 App 退出问题
前往 cmdutils.h 中,将
void exit_program(int ret) av_noreturn;
方法声明为
int exit_program(int ret);
并前往 cmdutils.c 中,将对应实现改为:
int exit_program(int ret) { if (program_exit) program_exit(ret); // exit(ret); return ret; }
9).修改多次调用 ffmpeg_main 时,访问空指针的问题
前往 ffmpeg.c 中,在 ffmpeg_cleanup 方法中,增加处理。
在
term_exit(); 之前 增加 nb_filtergraphs = 0; nb_output_files = 0; nb_output_streams = 0; nb_input_files = 0; nb_input_streams = 0;
至此,我们已经集成了 ffmpeg 和 ffmpeg 的命令行工具,接下来我们就可以使用命令行来调起ffmpeg了。
使用ffmpeg命令行的大致格式如下:
ffmpeg [global_options] {[input_file_options] -i input_url} ... {[output_file_options] output_url}
对应于 ffmpeg 工具中,就是如下格式:
当然需要导入 #import "ffmpeg.h"
int result = 1; int argc = 19; int i = 0; char **arguments = calloc(argc, sizeof(char *)); if(arguments != NULL) { arguments[i++] = "ffmpeg"; arguments[i++] = "-r"; arguments[i++] = (char *)[fps UTF8String]; arguments[i++] = "-i"; arguments[i++] = (char *)[gifPath UTF8String]; arguments[i++] = "-i"; arguments[i++] = (char *)[globalPalettePath UTF8String]; arguments[i++] = "-lavfi"; arguments[i++] = "paletteuse"; arguments[i++] = "-s"; arguments[i++] = (char *)[[NSString stringWithFormat:@"%dx%d", (int)size.width, (int)size.height] UTF8String]; arguments[i++] = "-t"; arguments[i++] = (char *)[[self p_formatFloat:[gifInfo[kFFmpegToolGifDuration] floatValue]] UTF8String]; arguments[i++] = "-r"; arguments[i++] = "10"; arguments[i++] = "-b:v"; arguments[i++] = "1024k"; arguments[i++] = "-y"; arguments[i++] = (char *)[resizeGifPath UTF8String]; result = ffmpeg_main(argc, arguments); free(arguments); }
其中,一些常见的参数配置如下:
-f 强制指定编码格式
-i 输出源
-t 指定输入输出时长
-r 指定帧率,即1S内的帧数
-threads 指定线程数
-c:v 指定视频的编码格式
-ss 指定持续时长
-b:v 指定比特率
-s 指定分辨率
-y 覆盖输出
-filter 指定过滤器
-vf 指定视频过滤器
-an 指定去除对音频的影响
ffmpeg -t 3.0 -i /Users/mdm/Desktop/water.gif -t 3.0 -b:v 1024k -y /User/mdm/Desktop/water.mp4
1).如果需要添加水印,可以增加 -vf 过滤器
ffmpeg -t 3.0 -i /Users/mdm/Desktop/water.gif -vf movie=/Users/mdm/Desktop/mark.png[watermark];[in][watermark]overlay=0:0[out] -t 3.0 -b:v 1024k -y /User/mdm/Desktop/water.mp4
其中 overlay 指定水印图片所处的位置
2).如果需要指定输出的分辨率,可为输出指定 -s 参数,若不指定,则默认输出为输入源同等大小分辨率
ffmpeg -t 3.0 -i /Users/mdm/Desktop/water.gif -s 480x480 -t 3.0 -b:v 1024k -y /User/mdm/Desktop/water.mp4
注意:-s之后的参数需指定为整数
ffmpeg -r 7 -threads 0 -c:v png -i /Users/mdm/Desktop/resources/image%d.png -t 3.0 -b:v 1024k -y /Users/mdm/Desktop/water.mp4
注意:
1).如果输入的图片尺寸不一致,那么所有的图片都会从左上角开始绘制,如果需要居中展示,可以进行输出的边界设置,提前指定一个输出尺寸:
ffmpeg -r 7 -threads 0 -c:v png -i /Users/mdm/Desktop/resources/image%d.png -filter scale=480:480:force_original_aspect_ratio=decrease, pad=480:480:(480-in_w)/2:(480-in_h)/2:white -t 3.0 -b:v 1024k -y /Users/mdm/Desktop/water.mp4
其中scale指定绘制画布大小,pad格式为pad=w:h:x:y:color,其中可以使用in_w,in_h表示输入宽高,color指定边界颜色。
ffmpeg -t 3.0 -i /Users/mdm/Desktop/water.mp4 -an -r 25 -filter:v setpts=0.5*PTS -t 6.0 -b:v 1024k -y /Users/mdm/Desktop/newWater.mp4
注意:
ffmpeg -i /Users/mdm/Desktop/water.mp4 -f gif -r 15 -t 3.0 -b:v 1024k -y /Users/mdm/Desktop/water.gif
该方法可以将视频转换为GIF输出,但是在输出之后,发现GIF的图像质量不是很高。这是由于ffmpeg默认使用一个通用的全局调色板来覆盖所有的颜色区域,以此来支持含有大量内容的文件,所以生成的GIF图像质量不是很高。我们可以为视频提供一个特有的全局调色板,这样该视频转换出的GIF图像就有了特定的图片内容支持,从而可以提高图像质量。
ffmpeg -i /Users/mdm/Desktop/water.mp4 -i /Users/mdm/Desktop/waterGlobalPalette.png -lavfi paletteuse=dither=sierra2:diff_mode=rectangle -f gif -r 15 -t 3.0 -b:v 1024k -y /Users/mdm/Desktop/water.gif
通过制定一个输入源为全局调色板,进而来提高输出GIF图像质量。
全局调色板生成请看下一条。
ffmpeg -i /Users/mdm/Desktop/water.mp4 -vf palettegen -vframes 1 -y /Users/mdm/Desktop/globalPalette.png
ffmpeg -i /Users/mdm/Desktop/water.gif -i /Users/mdm/Desktop/globalPalette.png -lavfi paletteuse -s 480x480 -t 3.0 -y /Users/mdm/Desktop/newWater.gif
注意:
ffmpeg -t 3.0 -i /Users/mdm/Desktop/water.png -vf crop=w=380:h=380:x=50:y=50 -t 3.0 -y /Users/mdm/Desktop/newWater.png
注意:
https://blog.csdn.net/TuGeLe/article/details/80656262
https://www.oschina.net/translate/high-quality-gif-with-ffmpeg
http://ffmpeg.org/documentation.html
标签:表示 版本 frame ice 3.4 高度 大量 mpi 修改文件
原文地址:https://www.cnblogs.com/wjw-blog/p/9522843.html