I am putting two videos side by side vertically with ffmpeg.
Both of the videos are in high quality.
There is a loss of quality and the output looks very bad after this command:
ffmpeg -i input1t.avi -i input2 -filter_complex vstack output.avi
You can see an screen capture of the output movie here:
Any idea why? How to solve it?
FFmpeg will reencode your video, without additional parameters it will use default value resulting in a poor quality. Here's an example with a more modern format and codec:
ffmpeg -i input1.avi -i input2 -filter_complex vstack -c:v libx264 -preset slow -crf 20 -c:a aac -movflags +faststart output.mp4
If you need better quality, lower the -crf value.
Related
I have 30 clips which are different in aspect ratio(like some videos are 10801920(they are vertical) and some are 1280720(horizontal aspect ratio videos). I want to merge all of them but also have a static background image that is of 1920x1080 aspect ratio. The video would be such that all the clips are concatenated but they have a background image(just like those tiktok compilation videos on youtube). Can someone please help me with this program?
Example using 3 videos. It can easily be expanded to 30 videos. I broke the command into multiple lines so you can see the syntax better. Make it one line before executing.
ffmpeg -i 1.mp4 -i 2.mp4 -i 3.mp4 -i image.png -filter_complex
"[0:v]scale=1280:720:force_original_aspect_ratio=increase,crop=1280:720,setsar=1,fps=25,format=yuv420p[v0];
[1:v]scale=1280:720:force_original_aspect_ratio=increase,crop=1280:720,setsar=1,fps=25,format=yuv420p[v1];
[2:v]scale=1280:720:force_original_aspect_ratio=increase,crop=1280:720,setsar=1,fps=25,format=yuv420p[v2];
[0:a]aformat=sample_rates=44100:channel_layouts=stereo[a0];
[1:a]aformat=sample_rates=44100:channel_layouts=stereo[a1];
[2:a]aformat=sample_rates=44100:channel_layouts=stereo[a2];
[v0][a0][v1][a1][v2][a2]concat=n=3:v=1:a=1[vid][a];
[3][vid]overlay=(main_w-overlay_w)/2:(main_h-overlay_h)/2[v]"
-map "[v]" -map "[a]" -c:v libx264 -c:a aac -movflags +faststart output.mp4
References:
How to concatenate videos in ffmpeg with different attributes?
How to center overlay in ffmpeg?
Resizing videos with ffmpeg to fit specific size
I am trying to take a single image and add audio resulting in a video playing the entire song with that single image; much like you see for YouTube videos for songs. The command I am using is from this link: https://askubuntu.com/questions/868283/image-audio-mp4-how-to-make-video-smaller
This is the command:
ffmpeg -loop 1 -framerate 1 -i image.png -i song.aac -c:v libx264 -preset veryslow -crf 0 -c:a copy -shortest output.mp4
It works as intended for having the video file be a small size, and the song plays as well, but depending on the image I used, some of the images appear 'Green' when playing the video.
However though, this command works for any image used:
ffmpeg -loop 1 -framerate 1 -i image.jpg -i music.mp3 -c copy -shortest output.mp4
But the result is a very big file whereas I would like it to be smaller. Any help would be greatly appreciated! Thank you!
FFMpeg version: 4.3.1
The command you used from the answer you linked to is for YouTube specifically and even says, "your player probably won't like it but YouTube will". I'm assuming you're using a player and not YouTube.
In the same answer is another command under Widest compatibility for any player:
ffmpeg -loop 1 -i image.png -i music.mp3 -vf "scale='min(1280,iw)':-2,format=yuv420p" -c:v libx264 -preset medium -profile:v main -c:a aac -shortest -movflags +faststart output.mp4
Try that instead.
I'm trying to apply a caption using drawtext that should disappear one second before the video end:
ffmpeg -i input.mp4 -vf "drawtext=enable='between(t,0,5)':fontfile=font.ttf:text='Some caption':x=60:y=640:fontsize=40:fontcolor=#f0f0f0#0.9" -vcodec libx264 -crf 27 -preset ultrafast -strict -2 -acodec copy output.mp4
The problem is that I don't know the video length beforehand. I've tried using 'between(t,0,-1)' but it doesn't work, the caption never shows up.
Anyone knows if is there a way to do this without having to open the video first to check length and only after that draw the caption?
Thanks in advance!
FFmpeg does not convey the stream duration to filters, so this has to be done in a roundabout manner.
FFmpeg has a sseof function that can seek from the end of a file. It also has a copyts option to maintain timestamps. So, we load the input twice, once the full input, and the other, just the last second. Then we draw the text on the entire 1st input but overlay the last second from the 2nd input, which because of the retained timestamps, will be burnt in place.
ffmpeg -copyts -i input.mp4 -sseof -1 -i input.mp4 -filter_complex "[0]drawtext=fontfile=font.ttf:text='Some caption':x=60:y=640:fontsize=40:fontcolor=#f0f0f0#0.9[txt];[txt][1]overlay" -vcodec libx264 -crf 27 -preset ultrafast -acodec copy output.mp4
I need to convert many videos in such a way that I take 2 different crops from each frame of a single video, stack them one over the other and scale down the result, creating a new smaller video.
I want to convert this fullHD frame (two crop areas are marked red) to this small stacked frame.
Right now I use the following code:
ffmpeg -i "video.mkv" -filter:v "crop=560:416:0:0" out1.mp4
ffmpeg -i "video.mkv" -filter:v "crop=560:384:1060:128" out2.mp4
ffmpeg -i out1.mp4 -vf "movie=out2.mp4[inner]; [in][inner] overlay=0:32,scale=280:208[out]" -c:v libx264 -preset veryfast -crf 30 result.mp4
It works but it is very inefficient and requires temporary files (out1 and out2). And the problem is I have over 100.000 of such videos (they are big and stored on a NAS and not directly on my computer's HDD). Converting all of them with a Windows batch script (for loop) will take...48 days. Can you help me to optimize the script?
Use the crop, vstack, scale, and format filters:
ffmpeg -i input.mkv -filter_complex "[0:v]crop=560:24:0:0[top];[0:v]crop=560:384:1076:128[bottom];[top][bottom]vstack,scale=280:-2[out]" -map "[out]" -c:v libx264 -preset veryfast -crf 30 -movflags +faststart result.mp4
If you want to complicate it somewhat for faster filtering (maybe) then you can try scaling first:
ffmpeg -i input.mkv -filter_complex "[0:v]scale=iw/2:-1,split[v0][v1];[v0]crop=560/2:24/2:0:0[top];[v1]crop=560/2:384/2:1076/2:128/2[bottom];[top][bottom]vstack[out]" -map "[out]" -c:v libx264 -preset veryfast -crf 30 -movflags +faststart result.mp4
You'll have to experiment to see which is fastest for you.
I want asymmetrical side by side video with resolution 1920x1080. The first video has bitrate 1mb/s and the second video has bitrate 500kb/s. Both videos have the same resolution 1920x1080 and encoded h.265, container mp4.
I used ffmpeg code:
ffmpeg -i leftvideo.mp4 -i rightvideo.mp4 -filter_complex "[0:v] scale=iw/2:ih, pad=2*iw:ih [left]; [1:v] scale=iw/2:ih [right]; [left][right] overlay=main_w/2:0 [out]" -map [out] -c:v libx265 output.mp4
It works well but I want the resulting video quality while keeping. I don't want re-encoded.
Is it possible the two videos change resolution (960x1080) and together packed into container mp4?
EDIT: or another method?
Using ffmpeg
You are required to re-encode if you want to use filters in ffmpeg, but if you want to "keep the quality" you can use a lossless output:
ffmpeg -i left.mp4 -i right.mp4 -filter_complex \
"[0:v]scale=iw/2:ih[l];[1:v]scale=iw/2:ih[r];[l][r]hstack" \
-c:v libx264 -qp 0 output.mp4
The resulting file size may be huge. If this is not acceptable you can try a "visually lossless" output by changing -qp 0 to -crf 18.
You did not provide full details about your inputs, and did not mention audio, so I assumed you are not concerned with the audio.
You did not provide the complete console output from your command so I assumed your ffmpeg is new enough to use the hstack filter.
Using ffplay
Another option is to just use your player to play side-by-side and not even deal with re-encoding. Example using ffplay.
ffplay -f lavfi "movie=left.mp4,scale=iw/2:ih[v0];movie=right.mp4,scale=iw/2:ih[v1];[v0][v1]hstack"