关于ffmpeg必须知道的

1、ffmpeg.exe只是一个外围程序,其核心逻辑在libavcodec.dll和libavformat.dll,libavdevice.dll等

之所以是外围,相当于一个GUI,也就是说基于这些dll,你可以写自己的外围程序,比如做成特别的功能齐全的录屏软件或windows GUI的转码软件

2、libavcodec超过30mb,要想变小必须自己编译ffmpeg,放弃大量对你无用的encoder和decoder,这样可以降到2MB以内

3、ffmpeg录屏

如果使用gdigrab只能支持录制20fps以内的,以上将导致cpu占比超过30%,而且如果同时录音的话,则会产生巨大的帧延迟

ffmpeg.exe -y -rtbufsize 100M -f gdigrab -framerate 15 -offset_x 0 -offset_y 0 -video_size 1920x1080 -draw_mouse 1 -i desktop -f dshow -i audio="麦克风 (Realtek High Definition Au" -c:v libx264 -r 15 -preset ultrafast -tune zerolatency -crf 25 -pix_fmt yuv420p -c:a libmp3lame -qscale:a 4 "output-grab15.mp4"

 

 

如果使用creen-capture-recorder虽然可以达到30fps,但是cpu占比高达50%以上

 

4、ffmpeg -h encoder=libx264可以查看支持什么pixformat

我尝试过通过c++程序直接把rgba数据格式AV_PIX_FMT_BGRA(ARGB)直接avcodec_encode_video2到x264格式的mp4文件,会提示[libx264 @ 004b1e60] Specified pixel format bgra is invalid or not supported,通过上述命令可以查到:

Encoder libx264 [libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10]:

    General capabilities: delay threads

    Threading capabilities: auto

    Supported pixel formats: yuv420p yuvj420p yuv422p yuvj422p yuv444p yuvj444p nv12 nv16 nv21

可以说mp4只支持yuv系列的数据格式,这些格式中以yuv420p为主,是ffmpeg的默认编码输入的格式。

 

5、关于yuv420p格式:

yuv420p格式,如果不经过准确处理,会导致严重的失真,原因是yuv格式并不是无损格式,只是损失比较小,但是其大小确实比rgb24格式节省了一半的存储空间。

 

如rgb经过变换yuv格式,再变换回rgb格式后,绝对值的和(absSum(r,g,b))要比原来有2-30的误差,导致颜色有一些细微变化。

在我的转换中,虽然清晰度很高,但是某些细微的地方总是出现颜色变化,特别是亮度明显比原来变暗。

但是swscale内部的变换代码却能比较好的处理这种格式,觉察不出有颜色变化,如果有人能从ffmpeg里面提取一个rgb2yuv420p的函数,请告知一下。

而yuv420p2rgb的函数在https://github.com/FFmpeg/FFmpeg/blob/master/libswscale/yuv2rgb.c或http://www.fourcc.org/fccyvrgb.php 找到,或者使用swscale内部的函数:

 SwsContext   *img_convert_ctx= sws_getContext(w,h,AV_PIX_FMT_BGRA, w,h,AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);  

int op=sws_scale(img_convert_ctx, (const unsigned char* const*)srcFrame->data, (const int*)srcFrame->linesize, 0,h, dstFrame->data, dstFrame->linesize);  

 

记得linesize都是一个二维数组,必须对srcFrame进行初始化才能成功,或则会提示数据没有对齐的错误

 

对于rgba数据,必须这样初始化:

AVFrame *srcFrame = av_frame_alloc(); 

srcFrame ->data[0]=in_frame_data;//rgba的数据

srcFrame ->linesize[0]=in_linesize;//像素个数x4

这样转换的yuv420p数据就会转换到srcFrame->data里面

 

6、其他关于录屏的方案

1、先录制yuv420p的文件、pts时间文件和音频文件再后期通过ffmpeg转成mp4

这个方案可以支持的fps应该是最高的,25fps的录制,cpu占有率不会高于20%

风险:视频和音频对不上,而且所需的磁盘文件极为极大,1920x1080的25fps视频60分钟需要超过1T的存储空间。

正方意见:专业电影录制的时候也是音频和视频分开录制的

反方意见:录个屏幕,你有多少时间和精力做后期的处理?又有多少个高速硬盘可以用来录屏?

所以,该方案对于非专业级的需求,是很不经济的。

 

2、用ffmpeg.exe命令行录制音频和视频,对于一般要求,这个基本可以解决问题,但是可控度不高

比如不能暂停,出错不能及时得到通知,不能分文件保存。有点就是无需任何开发工作。这点优势也是高到天花板上去了。

 

3、就是利用libavxxx.dll这些共享dll,开发自己的程序,以实现暂停、及时反馈、分文件

这个就需要开发了,虽然开发工作不算多,但是为了稳定运行,对ffmpeg的api要有比较详细的认知。否则性能和稳定性还不如ffmpeg本身。

 

以上仅为备忘。

你可能感兴趣的:(音视频转换)