4

I want to convert a gif file to a video with ffmpeg. I'm using:

ffmpeg -y -i /gif/583fd7661b46d.gif -strict -2 -an -b:v 32M /gif/mp4/583fd7661b46d.avi

The duration of my gif in photoshop is 27 seconds, but the duration of the video "583fd7661b46d.avi" generated is 15 seconds. How can I get the same duration of my gif in the video generated?

ivan_pozdeev
  • 1,897
  • 18
  • 34
Aminesrine
  • 143
  • 5
  • How specifically is the result distorted? Do different delays become the same, or they are all changed proportionally to what they should be? – ivan_pozdeev Dec 06 '16 at 15:47
  • According to http://stackoverflow.com/a/24724126/648265, recent versions of `ffmpeg` should honor the delays specified in the GIF. – ivan_pozdeev Dec 06 '16 at 15:48
  • I have gif with 21 seconds and the video generated with 24 seconds, also gif with 27s and the video generated with 15s. I don't have a proportionally!! I use "ffmpeg version N-80901-gfebc862 Copyright (c) 2000-2016 the FFmpeg developers built with gcc 4.8 (Ubuntu 4.8.4-2ubuntu1~14.04.3)" What version I should use? – Aminesrine Dec 06 '16 at 16:12
  • That doesn't answer the question "How specifically is the result distorted?". Okay, I'll reformulate in simple words. How is the video visually different from the gif? What changes lead to a different duration? – ivan_pozdeev Dec 06 '16 at 16:27
  • I don't see a difference in speed. there is an exemple of the gif and the video generated: https://drive.google.com/open?id=0B-6RrqcLpcp9NzhWWlgta1NTZlk – Aminesrine Dec 06 '16 at 16:44

2 Answers2

3

Using your sample, I identified the problem:

In your GIF, the last (empty) frame has a duration of 10370ms. It seems to be ignored by ffmpeg, producing the difference.

If I change the output format to .mp4, the duration becomes correct. Changing encoder has no effect.

So, this is a bug in ffmpeg. This might be due to a limitation of the output format, which is very unlikely (the problem is also present for .mkv), but in that case, it should at least print a warning. Looking through their bug tracker, I found #4235 (Converting GIF to MP4 using FFmpeg produces a video that doesn't follow the GIF frame timings.) - looks like this was fixed for the .mp4 format but not for others.

ivan_pozdeev
  • 1,897
  • 18
  • 34
  • To the OP, the solution is to output first to MP4, then rewrap as AVI if that's the final format needed. – Gyan Dec 06 '16 at 19:47
  • [Filed a bug report](https://trac.ffmpeg.org/ticket/6000). – ivan_pozdeev Dec 06 '16 at 20:30
  • 2
    Solution already exists - add `-vsync cfr` when outputting to avi or mkv/webm. – Gyan Dec 07 '16 at 05:19
  • @Mulvya yes, but it's a workaround, not a solution. It completely destroys the original frame set, replacing it with a constant-frame-rate sequence. So, it's only good if outputting to a constant-frame-rate format. The correct solution would be to use an "end-of-stream marker" for slide-show formats. – ivan_pozdeev Jan 15 '17 at 13:14
  • AVIs only support CFR and don't have timestamps so their frame durations are imputed using the reciprocal of the frame rate. To generate the equivalent of VFR in AVI, you have to designate a high framerate which is the reciprocal of the smallest interval between frames and then write 0 byte chunks for longer intervals. There won't be any 'pure solution' for the OP's issue anyway. – Gyan Jan 15 '17 at 13:46
  • @Mulvya the point is, that switch should not be required, slideshow streams should be interpreted correctly regardless of it. Ignoring the stream's "tail" after the last slide is definitely not the correct behaviour. – ivan_pozdeev Mar 23 '17 at 16:08
0

Just apply presentation timestamp filter with a coefficient equal to fraction original time / achieved time in your case - 27/15. So you add filter -filter:v "setpts=27/15*PTS" before output file name.

More about framerate changes at FFmpeg wiki: https://trac.ffmpeg.org/wiki/How%20to%20speed%20up%20/%20slow%20down%20a%20video

Pavlus
  • 538
  • 5
  • 10
  • 1
    But I dont know the 15 and 27 values exactly. I want to convert a gif to a video with same duration without knowing any value – Aminesrine Dec 06 '16 at 14:01
  • If you know your gif framerate (you produce them, right?), you can adjust your video framerate accordingly. To get video duration -- use `ffprobe`: http://superuser.com/a/945604/318118 – Pavlus Dec 06 '16 at 14:04
  • I import the gif file from my interface then I should execute the ffmpeg comand to have the video corresponding of this gif with same duration. There is a way to get the duration of my gif with php? – Aminesrine Dec 06 '16 at 14:12
  • You can call ffprobe via `shell_exec`. Also, check out `PHP-FFmpeg` project https://github.com/PHP-FFMpeg/PHP-FFMpeg/ It's a PHP wrapper around FFmpeg. – Pavlus Dec 06 '16 at 14:19
  • I execute this: "ffprobe -i /gif/584020787a1b7.gif -show_format | grep duration" but the result is "duration=N/A" – Aminesrine Dec 06 '16 at 14:22
  • 1
    Can't get duration? Why not find FPS?! `ffprobe -v 0 -select_streams v -print_format flat -show_entries stream=r_frame_rate ./4.gif` will give something in format `streams.stream.0.r_frame_rate="30/1"` There are multiple output formats, chose one you like: https://ffmpeg.org/ffprobe.html#Writers – Pavlus Dec 06 '16 at 14:38
  • How can I use the frame_rate of my gif in the ffmpeg command to have a video with same duration? – Aminesrine Dec 06 '16 at 14:59
  • Use it to set output frame rate. If you still get wrong time -- let user to change PTS coefficient. Since GIF doesn't have frame timestamps and have delay unique for each frame, it's playback time usually tricky and system-dependent, so conversion it to video requires user interaction or deep understanding of video encoding techniques. – Pavlus Dec 06 '16 at 15:10
  • For my gif: streams.stream.0.r_frame_rate="100/3". So I execute this: "ffmpeg -y -i gif/584020787a1b7.gif -strict -2 -an -b:v 32M -r 100/3 /gif/mp4/583fd7661b46d_new_.avi" But it steel generate a video with 15 seconds of duration – Aminesrine Dec 06 '16 at 15:40