如何强制ffmpeg编码时输出一个关键帧

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何强制ffmpeg编码时输出一个关键帧相关的知识,希望对你有一定的参考价值。

如何强制ffmpeg编码时输出一个关键帧
AVCodecContext *c //编码器环境句柄AVFrame* f //需要编码的一帧视频 在编码前设置
f->pict_type=FF_I_TYPE;
f->key_frame=1;

然后编码
*outsize = avcodec_encode_video(c, temp, outbuf_size, f);

则编码之后通过如下参数判断是否为关键帧:
key_frame=c->coded_frame->key_frame;
pict_type=c->coded_frame->pict_type;
参考技术A int main()

SwsContext *pSWSCtx;
AVFormatContext *pFormatCtx;
const char *filename="sample.mpg";
int i,videoStream,y_size;
AVCodecContext *pCodecCtx;
AVFrame *pFrame;
AVFrame *pFrameRGB;
int numBytes,frameFinished;
uint8_t *buffer;
static AVPacket packet;

av_register_all();

if(av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL)!=0)
printf("error!\n");

if(av_find_stream_info(pFormatCtx)<0)
printf("error!\n");

dump_format(pFormatCtx, 0, filename, false);

videoStream=-1;

for(i=0; i<pFormatCtx->nb_streams; i++)
if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO)

videoStream=i;
break;

if(videoStream==-1)
printf("error!\n");// Didn't find a video stream

pCodecCtx=pFormatCtx->streams[videoStream]->codec;
AVCodec *pCodec;

pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
if(pCodec==NULL)
printf("error!\n");

if(avcodec_open(pCodecCtx, pCodec)<0)
printf("error!\n");
pFrame=avcodec_alloc_frame();

pFrameRGB = avcodec_alloc_frame();
numBytes=avpicture_get_size(PIX_FMT_BGR24, pCodecCtx->width,pCodecCtx->height);
buffer=new uint8_t[numBytes];
avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,pCodecCtx->width, pCodecCtx->height);
pSWSCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);

i=0;
while(av_read_frame(pFormatCtx,&packet)>=0)

if(packet.stream_index==videoStream)

avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,packet.data, packet.size);
if(frameFinished)

if(pFrame->key_frame==1)//这里取到关键帧数据

sws_scale(pSWSCtx, pFrame->data, pFrame->linesize,0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
i++;



av_free_packet(&packet);


av_free(pFrameRGB);

av_free(pFrame);

sws_freeContext(pSWSCtx);

avcodec_close(pCodecCtx);

av_close_input_file(pFormatCtx);

return 0;

ffmpeg视频剪切时长不正确

参考技术A 在windows下使用ffmpeg以下命令剪切视频时,发现剪切后的时长都会比设置的时长长
ffmpeg -ss 00:10 -t 30 -i 0.mp4 -c copy 2.mp4
以上的命令是从10s开始剪30s时长的视频,不过实际出来的时长32s左右

-c copy就是没有重新编码,直接裁剪视频,这样会出现一个问题:如果不重编码的分割视频,就需要对准视频的关键帧分割,比如视频的关键帧在8s处,而你是从10s开始分割,分割就会调整在8s处,这样剪切出来的视频就会比想要的长了

目前我的解决方法就是重新编码视频,去掉-c copy就行了,不过重新编码有点耗时间。有其他的解决方法欢迎指出。

以上是关于如何强制ffmpeg编码时输出一个关键帧的主要内容,如果未能解决你的问题,请参考以下文章

在关键帧之间剪切视频而不使用ffmpeg重新编码完整视频?

请问如何将这些 Blender 视频设置转换为 ffmpeg?

将 FFMPEG 编码为 MPEG-DASH - 或带有关键帧集群的 WebM - 用于 MediaSource API

新手学习FFmpeg - 调用API计算关键帧渲染时间点

ffmpeg视频剪切时长不正确

ffmpeg实现视频I帧提取