用FFmpeg编码的视频播放速度太快

时间:2014-04-22 12:23:22

标签: video ffmpeg

我已经搜索了Google / SO / Zeranoe的搜索结果,并试图整合我发现的所有内容,使我的程序正确生成视频,但我仍然无法使其正常工作。

我需要一个好的视频作为参考,所以我跑了:

ffmpeg -t 5 -f dshow -i "video=Logitech HD Pro WebcamC910" CLI.mpg

生成一个可以在VLC中播放的5秒视频,并显示持续时间并正确播放。您可以在此处获取视频:https://drive.google.com/file/d/0B1VGi1Ts7D7TR3c4VUlyM2dIcFk/edit?usp=sharing

然后我用自己的代码生成了一个五秒钟的视频。我试图将其削减到我认为需要录制的内容。您可以在此处找到代码:https://drive.google.com/file/d/0B1VGi1Ts7D7TMnFxSE1HX2FKbEU/edit?usp=sharing

它也生成了一个具有相似视频质量的视频,但VLC没有显示视频持续时间,视频似乎播放得太快。我的意思是我在屏幕上看到的东西看起来像是移动得太快了。您可以在此处找到我的代码生成的视频:https://drive.google.com/file/d/0B1VGi1Ts7D7TSzFGUFZEMHJwQ0U/edit?usp=sharing

即使您点击视频链接,您也可以看到Google遇到了问题,但FFmpeg CLI生成的问题没有问题。很抱歉在场外发布了所有内容,但我不想将我的代码垃圾邮件发送到帖子中,我想提供尽可能多的信息。

我已经看过很多关于此的帖子,但我似乎无法找到明确的解决方案。

编辑: 所以我实现了你的建议,我很确定你的答案解决了时间问题,但现在我在第一次成功调用encode_video之前一直得到20个非严格单调的错误。无论我使用

,都会发生这种情况
gFrame->pts = gFrameIndex;

gFrame->pts = av_rescale_q(gFrameIndex, gCodecContext->time_base, gStream->codec->time_base);

ret = avcodec_encode_video2(gCodecContext, &pkt, gFrame, &got_output);
if (ret < 0) {
  fprintf(stderr, "Error encoding frame\n");
  return false;
}

这似乎与播放期间视频文件开头的视频瑕疵相吻合。 gFrameIndex从1开始。

我相信我的网络摄像头会在录制开始时自动聚焦,这是否可能与此相关?

我已将生成的.h264文件上传到https://drive.google.com/file/d/0B1VGi1Ts7D7TRjRzbzZZemRaRTA/edit?usp=sharing,将我最近的代码上传到https://drive.google.com/file/d/0B1VGi1Ts7D7TbmlyYncxYzRQUTA/edit?usp=sharing

我真的很感激帮助。遗憾的是,我不能直接在我的软件中使用FFmpeg CLI,因此我必须使用该库。除非你能提出更好的选择,否则我将不得不继续保持货运。

1 个答案:

答案 0 :(得分:1)

通常在致电avcodec_encode_video2()之前,您需要设置框架的时间戳,例如:

gFrame->pts = gFrameIndex;

gFrameIndex每个编码帧增加1,这在您的情况下应该是正确的,因为time_base是1/30并且每帧代表1/30秒的持续时间。

然后在这里小心:

  if (pkt.pts != AV_NOPTS_VALUE) pkt.pts = av_rescale_q(gCodecContext->coded_frame->pts, gCodecContext->time_base, gStream->time_base);
  if (pkt.dts != AV_NOPTS_VALUE) pkt.dts = av_rescale_q(gFrameIndex, gCodecContext->time_base, gStream->time_base);

您是否因为使用libx264进行编码而遇到问题?我注意到在这种情况下,您必须在调用avcodec_encode_video2()之前和之后重新调整时间戳,例如:

gFrame->pts = av_rescale_q(gFrameIndex, gCodecContext->time_base, gStream->codec->time_base);
[...]
avcodec_encode_video2()
[...]
pkt.pts = av_rescale_q(pkt.pts, gStream->codec->time_base, gStream->time_base);
pkt.dts = av_rescale_q(pkt.dts, gStream->codec->time_base, gStream->time_base);

这是因为与libx264的ffmpeg接口质量不高。

您的网络摄像头是否丢帧?如果是这样,那么你需要给帧提供实时时间戳。创建一个函数,以毫秒为单位返回自开始捕获以来经过的时间(整数)。然后将time_base设置为{1,1000}并将gFrame->pts设置为函数的返回值。但要小心:您不能拥有&lt; =之前时间戳的时间戳。因此,如果您同时获得几个(或者编写另一种处理这种情况的机制),您将需要删除帧。顺便说一句,这都是在ffmpeg CLI程序中为您完成的,这就是为什么很少有人尝试使用ffmpeg库...