用FFmpeg编码的视频播放速度太快 [英] Videos encoded with FFmpeg play too fast

查看:2448
本文介绍了用FFmpeg编码的视频播放速度太快的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

  ffmpeg -t 5 -f dshow -ivideo = Logitech HD Pro WebcamC910CLI.mpg 

哪个生成了一个五秒的视频可以在VLC中播放,并显示持续时间并播放正确。您可以在此处获取视频: https://drive.google.com/文件/ d / 0B1VGi1Ts7D7TR3c4VUlyM2dIcFk /编辑?usp =共享



然后我用自己的代码生成了一个五秒的视频。我已经试图把它归结为只有我认为需要记录。您可以在这里找到代码: https://drive.google.com/文件/ d / 0B1VGi1Ts7D7TMnFxSE1HX2FKbEU /编辑?usp =共享



它也生成了一个视频,具有类似的视频质量,但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); 

before

  ret = avcodec_encode_video2(gCodecContext,& pkt,gFrame,& got_output); 
if(ret< 0){
fprintf(stderr,Error encoding frame\\\
);
返回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,所以我必须使用库。除非你能提出一个更好的选择,否则我必须保持货运。

解决方案

code> 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 到函数的返回值。但要小心:您不能拥有< =以前的时间戳记的时间戳。所以你需要放下框架,如果你一次几个全部(或写另一个机制来处理这种情况)。 BTW,这些都是为您在 ffmpeg CLI程序中完成的,这就是为什么很少有人尝试使用ffmpeg库...


I've scoured the Google/SO/Zeranoe results and tried to integrate everything I found into making my program generate videos correctly but I still can't get it to work right.

I needed a good video to use as a reference so I ran:

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

Which generated a five-second video which can be played in VLC and shows the duration and plays correctly. You can get the video here: https://drive.google.com/file/d/0B1VGi1Ts7D7TR3c4VUlyM2dIcFk/edit?usp=sharing

I then generated a five-second video with my own code. I've tried to pare it down to only what I think is needed to record. You can find the code here: https://drive.google.com/file/d/0B1VGi1Ts7D7TMnFxSE1HX2FKbEU/edit?usp=sharing

It generated a video also, with similar video quality, but VLC doesn't show the video duration and the video seems to play too quickly. I mean that what I see on the screen looks like it's moving slightly too fast. You can find the video my code generated here: https://drive.google.com/file/d/0B1VGi1Ts7D7TSzFGUFZEMHJwQ0U/edit?usp=sharing

Even when you click on the links to the videos, you can see that Google is having trouble with mine but no problem with the one generated by the FFmpeg CLI. Sorry about posting everything off-site but I didn't want to spam my code into the post and I wanted to provide as much information as I could.

I've seen a number of posts about this but I can't seem to find a definitive solution.

EDIT: So I implemented your suggestions and I'm pretty sure that your answer fixed the timing issue but now I consistently get 20 non-strictly-monotonic errors before the first successful call encode_video. This happens whether I use

gFrame->pts = gFrameIndex;

or

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

before

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

This seems to coincide with video artifacts at the start of the video file during playback. gFrameIndex starts at 1.

I believe my webcam auto-focuses at the start of recordings, is it possible this is related?

I've uploaded the generated .h264 file at https://drive.google.com/file/d/0B1VGi1Ts7D7TRjRzbzZZemRaRTA/edit?usp=sharing and my most recent code to https://drive.google.com/file/d/0B1VGi1Ts7D7TbmlyYncxYzRQUTA/edit?usp=sharing.

I really appreciate the help. Sadly, I can't use the FFmpeg CLI directly in my software, so I have to use the library. I'm going to have to keep trucking along with it unless you can suggest a better alternative.

解决方案

Usually before you call avcodec_encode_video2() you set the frame's timestamp, e.g.:

gFrame->pts = gFrameIndex;

gFrameIndex is incremented by 1 each encoded frame, which should be correct in your case because your time_base is 1/30 and each frame represents 1/30th second duration.

Then be careful here:

  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);

Are you having problems because you are using libx264 to encode? I noticed that in that case, you have to rescale the timestamps before and after calling avcodec_encode_video2(), e.g.:

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);

It's because the ffmpeg interface with libx264 is not of very high quality.

Is your webcam dropping frames? If so then you'll need to give the frames real timestamps. Create a function that returns the elapsed time since you started the capture in milliseconds (an integer). Then set time_base to {1,1000} and set gFrame->pts to the return value of your function. But be careful: you can't have a timestamp that is <= a previous timestamp. So you will need to drop frames if you get several all at once (or write another mechanism for dealing with this situation). BTW, this is all done for you in the ffmpeg CLI program, which is why so few people try to use ffmpeg the library ...

这篇关于用FFmpeg编码的视频播放速度太快的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆