How to convert video to gif and mp3 that sync using ffmpeg? - ffmpeg

I want to convert video to gif with audio. The two should match when played at the same time.
The command I use somehow generates results that's a bit off.
To create gif:
ffmpeg -ss 00:00:10 -i input.mp4 -t 4 -pix_fmt rgb24 -r 10 -filter:v "scale=-1:300" out.gif
To create mp3:
ffmpeg -ss 00:00:10 -i input.mp4 -t 4 out.mp3
I'm guessing this has something to do with the slicing.

Untested: You could try one of these two options below. If still not working then please provide a short clip (MP4 link) that can be tested to give you required solution...
Option 1) Try using -itsoffset instead of -t...
ffmpeg -ss 00:00:10 -itsoffset 4 -i input.mp4 -pix_fmt rgb24 -r 10 -filter:v "scale=-1:300" out.gif
ffmpeg -ss 00:00:10 -itsoffset 4 -i input.mp4 out.mp3
Option 2) Avoid issue of non-matching times for keyframes (of video track vs audio track)...
First trim the video (get's whatever audio is available at nearest video keyframe to your time):
ffmpeg -ss 00:00:10 -i input.mp4 -t 4 trimmed.mp4
Then use trimmed MP4 (will have synced audio) as source for your output GIF and MP3.
ffmpeg -i trimmed.mp4 -pix_fmt rgb24 -r 10 -filter:v "scale=-1:300" out.mp4
ffmpeg -i trimmed.mp4 out.mp3

Related

FFMPEG attach thumbnail to first frame of the video

I want to attach/append an image (something like youtube) to first frame of the video, i tried this command :
ffmpeg -i video.mp4 -i image.png -map 1 -map 0 -c copy -disposition:0 attached_pic out.mp4
But it doesnt working, the first frame is not my custom image
my ffmpeg version:
ffmpeg version n4.4-80-gbf87bdd3f6-20210830 Copyright (c) 2000-2021 the FFmpeg developers
You will have to concatenate a frame to the beginning.
Re-encode audio in video.mp4. The audio is HE-AACv2, but you don't have a HE-AACv2 encoder. So it has to be changed to the more common AAC-LC to allow concatenation with the video generated from the image.
ffmpeg -i video.mp4 -c:v copy -c:a aac main.mp4
Make a video from image.png with silent filler audio. It has to have the same attributes as main.mp4.
ffmpeg -loop 1 -framerate 30 -i image.png -f lavfi -i anullsrc=r=48000 -frames:v 2 -c:v libx264 -vf format=yuv420p -video_track_timescale 30k -c:a aac image.mp4
-frames:v 2 is used instead of -frames:v 1 as required for the audio.
Make input.txt containing:
file 'image.mp4'
file 'main.mp4'
Concatenate:
ffmpeg -f concat -i input.txt -c copy output.mp4

FFMPEG no sound

I am trying to cut a part of a mp4 to make a shorter clip via ffmpeg however when I do I get no sound
ffmpeg -ss 00:06:51 -i truth.mp4 -c:a aac -c:v copy -t 8 true-30sec.mp4
The original clip has sound.
ffmpeg -ss 00:06:51 -i truth.mp4 -t 8 true-8sec.mp4
if you want 30 seconds video from 00:06:51 time, try
ffmpeg -ss 00:06:51 -i truth.mp4 -t 30 true-30sec.mp4

How to replace the video track in a video file with a still image?

I am trying to use ffmpeg to replace the video track in a video file with a still image. I tried some commands I got from other questions such as the one here
ffmpeg -i x.png -i orig.mp4 final.mp4
ffmpeg -r 1/5 -i x.png -r 30 -i orig.mp4 final.mp4
But these didn't work. I'm not sure which of these arguments are required or not. The output should be accepted by YouTube as a valid video - I was able to simply remove the video track, but apparently they don't let you upload a video without a video track.
You can try looping the still image like this:
ffmpeg -loop 1 -i x.png -i orig.mp4 final.mp4
Then you can tweak the encoding process by introducing the following quality parameters:
ffmpeg -loop 1 -i x.png -i orig.mp4 -crf 22 -preset slow final.mp4
they are described here.
If your colorspace gets rejected by YouTube you can try adding: -pix_fmt yuv420p.
Solution: A final solution is something like this:
Where -t 30 is an example duration of 30 seconds.
Using -c:a copy will directly copy the original audio without a new re-encoding (is faster).
ffmpeg -loop 1 -i x.png -i orig.mp4 -map 0 -map 1:a -c:v libx264 -pix_fmt yuv420p -crf 22 -preset slow -c:a copy -shortest final.mp4

Quicky output selection of video frames using ffmpeg

I would like to extract, say, 10 video frames from a given video file using ffmpeg, ideally uniformly distributed throughout the video. I know this can be done in a few ways, for example
ffmpeg -i input.mp4 -vf fps=1/10 out%03d.jpg
will output one image every 10 seconds. However, this is too slow for my liking and scales proportionally with the length of the video. I have read a bit about ffmpeg's seeking capability, for example
ffmpeg -ss 00:00:05 -i input.mp4 -frames:v 1 out001.jpg
will very quickly seek to the 5th second of the video and extract one frame. However I haven't come across a way to seek to multiple locations in the video without calling the above command repeatedly at various times.
Is there a quicker way of accomplishing this?
Using a long command, this can be done
e.g.
ffmpeg -ss 00:00:05 -i input.mp4
-ss 00:01:05 -i input.mp4
-ss 00:03:05 -i input.mp4
-ss 00:40:05 -i input.mp4
-map 0:v -frames:v 1 out001.jpg
-map 1:v -frames:v 1 out002.jpg
-map 2:v -frames:v 1 out003.jpg
-map 3:v -frames:v 1 out004.jpg

animation between images using FFmpeg

Hi I am new in FFmpeg,
I have made video from slideshow of sequential images (img001.jpg, img002.jpg, img003.jpg....). Using following commands in Ubuntu 14.04
ffmpeg -framerate 1/5 -i img%03d.jpg -c:v libx264 -r 30 -pix_fmt yuv420p -vf scale=320:240 out.mp4
But now I want to put animation like fade-in, fade-out between each sequential images, I want to generate video,
can anybody help me how to make it, i have searched lots of things but could not get....
The best way to do this is create intermediate mpeg's for each image and then concatenate them all into a video. For example, say you have 5 images; you would run this for each one of the images to create the intermediate mpeg's with a fade in at the beginning and a fade out at the end.
ffmpeg -y -loop 1 -i image -vf "fade=t=in:st=0:d=0.5,fade=t=out:st=4.5:d=0.5" -c:v mpeg2video -t 5 -q:v 1 image-1.mpeg
where t is the duration, or time, of each image. Once you have all of these mpeg's, you use ffmpeg's concat command to combine them all into an mp4.
ffmpeg -y -i image-1.mpeg -i image-2.mpeg -i image-3.mpeg -i image-4.mpeg -i image-5.mpeg -filter_complex '[0:v][1:v][2:v][3:v][4:v] concat=n=5:v=1 [v]' -map '[v]' -c:v libx264 -s 1280x720 -aspect 16:9 -q:v 1 -pix_fmt yuv420p output.mp4
This gives you the desired video and is the simplest and highest quality solution with ffmpeg. Let me know if you have any questions about how the above command works.

Resources