How to asymmetrical video side by side? - ffmpeg

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"

Related

Ffmpeg overlay using filter complex taking too much cpu

I am relaying a input rtmp stream to different server. In one of the use case, i overlay a image on top of the stream using filter complex and scale2ref, but it is taking almost 10 times the cpu as compared to normal ffmpeg command.
overlay: 'ffmpeg -xerror -itsoffset ${delaySeconds} -i ${SOURCERTMP} -i ${overlayUrl} -max_muxing_queue_size 9999 -filter_complex "[1][0]scale2ref[ovr][base];[base][ovr] overlay=0:0, split=1[a]" -map 0:a -map "[a]" -c:v libx264 -c:a aac -f flv -flvflags no_duration_filesize '${forwardUrls[0]}'
simple Version: 'ffmpeg -xerror -itsoffset ${delaySeconds} -i ${SOURCERTMP} -max_muxing_queue_size 9999 -c:v copy -c:a copy -f flv -flvflags no_duration_filesize '${forwardUrls[0]}'
It's not taking too much CPU, Its taking the CPU it needs. That is expected. The second command is doing MUCH less than the first.
The overlay command is not just adding an overlay. It is decoding the video, blitting an overlay, then reencoding the video (which is very expensive), And possibly doing some automatic color space conversation.
The "simple version" is just reading an encoded frame, and writing it back out without looking at it. Its basically a file copy.
Frankly I'm supposed its only 10x more CPU.

Converting a large number of MP3 files to videos for YouTube, each using same the JPEG image

I am looking for a way to convert large number of MP3 files to videos, each using the same image. Efficient processing time is important.
I tried the following:
ffmpeg -i image.jpg -i audio.mp3 -vcodec libx264 video.mp4
VLC media player played the resulting video file with the correct sound, but a blank screen.
Microsoft Media Player played the sound and showed the intended image. I uploaded the video to YouTube and received the message:
"The video has failed to process. Please make sure you are uploading a supported file type."
How can I make this work?
Create video:
ffmpeg -framerate 6 -loop 1 -i input.jpg -c:v libx264 -vf format=yuv420p -t 00:10:00 video.mp4
The duration (-t) should be ≥ the MP3 with the longest duration.
Now stream copy the same video for each MP3:
ffmpeg -i video.mp4 -i audio.mp3 -map 0:v -map 1:a -c copy -movflags +faststart -shortest output.mp4
Some notes regarding compatibility:
MP3 in MP4 does not have universal support, but will be fine in YouTube. If your target players do not like it then add -c:a aac after -c copy to output AAC audio.
If your target player does not like it then increase the -framerate value or add the -r output option with an appropriate value, such as -r 15. Again, YouTube should be able to handle it.

How to combine a video and an image using "reverse" vstack?

I have an image and a video (same width). I now want to use ffmpeg to add the image above the video. Google and other SO threads the use of the vstack filter_complex tag, which works great - except that it puts the image under the video.
I've tried putting the image first and then the video, but this doesnt work. I've also tried giving the vstack command reverse inputs, but also didnt work!
The video may also contain audio which I would need to keep.
See code below:
// Works, but puts image below video (instead of above)
ffmpeg -i test.mp4 -i text.png -filter_complex vstack result.mp4
// Doesn't work at all
ffmpeg -i test.mp4 -i text.png -filter_complex '[1:v][0:v]vstack' result.mp4
// Doesn't work at all
ffmpeg -i test.mp4 -i text.png -filter_complex '[1:v][0:v]vstack=inputs=2[v]' -map '[v]' -map 0:a result.mp4
Google / SO did not yield any tips on how to achieve this so far. Do you know a solution?
Use
ffmpeg -i test.mp4 -i text.png -filter_complex '[1:v][0:v]vstack' -c:a copy -pix_fmt yuv420p result.mp4
Videos and images can have different pixel formats. When the various inputs to a stack filter don't have the same format, the filter picks the format of the first input and converts all other inputs to that format. However, some video players don't support a wide variety of formats. yuv420p is the widely supported format and so the command above forces the output to that one. Audio, if present in the MP4, will get carried over.
ffmpeg -i test.mp4 -i text.png -filter_complex '[1:v]format=yuv444p[img];[img][0:v]vstack' -c:a copy -pix_fmt yuv420p result.mp4

How to improve quality after putting two videos side by side vertically?

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.

Changing resolution mid-video with FFMPEG

I have a source video (mpeg2video) which I'm transcoding to x264. The source contains 2 different programs recorded from TV. One is in 4:3 AR and the other 16:9 AR. When I play the source file through VLC the player correctly changes size to show the video at the correct AR. So far so good.
When I transcode the conversion process auto detects the AR from the first few frames and then transcodes the whole video using this AR. If the 16:9 section comes first then the whole conversion is done in 16:9 and the 4:3 section looks stretch horizontally. If the 4:3 section is at the start of the source file then the whole transcode is done in 4:3 and the 16:9 section looks squashed horizontally.
No black bars are ever visible.
Here's my command:
nice -n 17 ffmpeg -i source.mpg -acodec libfaac -ar 48000 -ab 192k -async 1 -copyts -vcodec libx264 -b 1250k -threads 2 -level 31 -map 0:0 -map 0:1 -map 0:2 -scodec copy -deinterlace output.mkv
I don't fully understand what's going on. How do I get the same 'change in AR' mid video in the output file that I have in the input video?
I don't think ffmpeg is designed to do that midway. You will have to write your own application using libav for it. The simpler way would be create two chunks of video that you combine.
EDIT:
The best way to deal with it is if you can detect the change of AR yourself and transcode the two segments seperately and join them.
EDIT2:
Use ffmpeg itself to chunk the video, demux anything you want and mux it back again. It should work fine. You needn't use avidemux.

Resources