[英]How can I seek to frame No. X with ffmpeg?
我正在写一个视频编辑器 ,我需要寻找精确的帧,知道帧号 。
stackoverflow上的其他帖子告诉我,ffmpeg可能会在搜索后给我一些破帧,这对于播放来说不是问题,但对于视频编辑来说是个大问题。
我需要通过帧号来寻找, 而不是按时间来寻找,这在转换为帧号时会变得不准确。
我读过dranger的tuts(现在已经过时了),最后得到:
av_seek_frame(fmt_ctx, video_stream_id, frame, AVSEEK_FLAG_ANY);
它始终寻求No. 0
帧,并始终return 0
,这意味着成功。 然后我试着阅读Blender的源代码并发现它真的很复杂(也许我应该实现一个图像缓冲区?)。
那么,有没有简单的方法来寻找一个只需要像seek(context, frame_number)
这样的简单调用的框架(虽然获得一个完整的框架,而不是一个完整的框架)? 或者,是否有任何轻量级库可以简化这个?
编辑:感谢praks411 ,我找到了解决方案:
void AV_seek(AV * av, size_t frame)
{
int frame_delta = frame - av->frame_id;
if (frame_delta < 0 || frame_delta > 5)
av_seek_frame(av->fmt_ctx, av->video_stream_id,
frame, AVSEEK_FLAG_BACKWARD);
while (av->frame_id != frame)
AV_read_frame(av);
}
void AV_read_frame(AV * av)
{
AVPacket packet;
int frame_done;
while (av_read_frame(av->fmt_ctx, &packet) >= 0) {
if (packet.stream_index == av->video_stream_id) {
avcodec_decode_video2(av->codec_ctx, av->frame, &frame_done, &packet);
if (frame_done) {
...
av->frame_id = packet.dts;
av_free_packet(&packet);
return;
}
}
av_free_packet(&packet);
}
}
EDIT2:原来有一个库: FFMS2 。 它是“基于FFmpeg的源库,便于帧精确访问”,并且是可移植的(至少在Windows和Linux上)。
av_seek_frame
将仅基于关键帧的时间戳进行搜索。 因为它寻求关键帧,你可能无法得到你想要的。 因此,建议寻找最近的关键帧,然后逐帧读取,以达到所需的帧。
但是,如果您正在处理固定的FPS值,则可以轻松地将时间戳映射到帧索引。
在寻找之前,如果您指定了流,则需要将您的时间转换为AVStream.time_base
单位。 在avformat.h
阅读av_seek_frame
ffmpeg文档。
例如,如果你想寻找1.23
秒的剪辑:
double m_out_start_time = 1.23;
int flgs = AVSEEK_FLAG_ANY;
int seek_ts = (m_out_start_time*(m_in_vid_strm->time_base.den))/(m_in_vid_strm->time_base.num);
if(av_seek_frame(m_informat, m_in_vid_strm_idx,seek_ts, flgs) < 0)
{
PRINT_MSG("Failed to seek Video ")
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.