Rotate text in ffmpeg [duplicate] - ffmpeg

I am trying to overlay some text on video using ffmpeg. I am able to overlay text by the bellow command.
ffmpeg -i input1.mp4 -filter_complex "[0:v]transpose=2[anticlockwiserotated];[anticlockwiserotated]drawtext=fontfile=../../public/fonts/Roboto-Regular-webfont.ttf: text='Test Text':x=100: y=50: fontsize=36: fontcolor=white:[textapplied];[textapplied]transpose=1" output_video.mp4
It is allowing me to overlay horizontally or vertically only.
But I want to append it with some angle like 45 degrees.
For that if I modify the command as
ffmpeg -i input1.mp4 -filter_complex "[0:v]rotate=45*PI/180[anticlockwiserotated];[anticlockwiserotated]drawtext=fontfile=../../public/fonts/Roboto-Regular-webfont.ttf: text='Test Text':x=100: y=50: fontsize=36: fontcolor=white:[textapplied];[textapplied]rotate=315*PI/180" output_video.mp4
By this I am getting overlay video as:
Because in this first I am rotating video to 45 degrees, appending text and bringing it back to original position. So I am loosing borders.
Please suggest me the best way to overlay text with required angle on video.
Thanks in advance.

Basic method is to generate text on a blank canvas, then an alpha layer for the text, rotating the result and overlaying that on the main video.
In the command below, a should be replaced by the angle. The co-ordinates for the drawtext are used in the overlay instead. Depending on the length of your text, some of it may get clipped if you've rotated it anticlockwise. So check and adjust the Y offset accordingly.
ffmpeg -i input1.mp4 -filter_complex
"color=black:100x100[c];
[c][0]scale2ref[ct][mv];
[ct]setsar=1,drawtext=fontfile=../../public/fonts/Roboto-Regular-webfont.ttf:
text='Test Text':fontsize=36:fontcolor=white,split[text][alpha];
[text][alpha]alphamerge,rotate=a:ow=rotw(a):oh=roth(a):c=black#0[txta];
[mv][txta]overlay=x='min(0,-H*sin(a))+100':y='min(0,W*sin(a))+50':shortest=1"
output_video.mp4

One method is by using ASS or SRT subtitles with the FFmpeg subtitles or ass filters.
ffmpeg -i input -filter_complex "subtitles=diagonal.ass" output
SRT subtitles are much simpler than ASS and don't support rotation, but you can manually add it with the filter:
ffmpeg -i input -filter_complex "subtitles=diagonal.srt:force_style='Angle=45'" output
You can create and style the subtitles with Aegisub or manually.

Related

FFMpeg add drop shadow to a video

I have this example video, recorded by Kazam:
https://user-images.githubusercontent.com/1997316/178513325-98513d4c-49d4-4a45-bcb2-196e8a76fa5f.mp4
It's a 1022x728 video.
I need to add a drop shadow identical to the one generated by the "Drop shadow (legacy)" filter of Gimp with the default settings. So, I generated with Gimp a PNG containing only the drop shadow. It's a 1052x758 image:
Now I want to put the video over the image to get a new video with the drop shadow. The wanted effect for the first frame is:
So, the video must be placed over the image. The top-left corner of the video must be in the position 11x11 of the background image.
How can I achieve this result?
I tried without success the following command. What's wrong?
ffmpeg -i shadow.png -i example.mp4 -filter_complex "[0:v][1:v] overlay=11:11'" -pix_fmt yuv420p output.mp4
About the transparency of the PNG background image, if it can't be maintained, then it's okay for the shadow to be on a white background. Otherwise, if it can be maintained by using an animated GIF as the output format, it is better.
The solution is to remove the transparency from shadow.png. Then:
ffmpeg -i example.mp4 -filter_complex "[0:v] palettegen" palette.png
ffmpeg -loop 1 -i shadow.png -i example.mp4 -i palette.png -filter_complex "[1:v] fps=1,scale=1022:-1[inner];[0:v][inner]overlay=11:11:shortest=1[new];[new][2:v] paletteuse[out]" -map '[out]' -y output.gif
The result is exactly what I wanted:
This solution is inspired by the answer https://stackoverflow.com/a/66318325 and by the article https://www.baeldung.com/linux/convert-videos-gifs-ffmpeg

ffmpeg overlay background color/image with multiple videos

I'm new to ffmpeg and I'm stuck not sure how to continue.
I have two videos that I will like to merge into a single video with background color/image overlay.
The image bellow is what I'm trying to achieve, the rectangle is the main video, the round is another video and the red is the background color/image.
video info:
one.mp4
original size: 1280x720
position/resized: (x20, y20, w980, h:keep-aspect-ration)
two.mp4
original size: 1280x720
position/resized: (x-bottom, y-buttom-left, w:keep-aspect-ration, h200)
So far I've only been able to add a bg-color but with a problem, the audio is gone, not to say that I haven't even added the second video as part of my command.
ffmpeg -f lavfi -i color=c=white:s=1920x1080:r=24 -i video.mp4 -filter_complex "[0:v][1:v]overlay=shortest=1,format=yuv420p[out]" -map "[out]" output.mp4
Any suggestion on how to achieve it?
Thanks in advance.
[edit 3/19: added full command for OP's need]
Try this:
ffmpeg -i one.mp4, -i two.mp4, \
-f lavfi -i color=c=white:s=1920x1080:r=30 \
-f lavfi -i color=c=white:s=400x400:r=1,\
format=yuva444p,\
geq='lum(X,Y)':'cb(X,Y)':'cr(X,Y)':\
a='if(lt((X-200)^2+(Y-200)^2,200^2),0,255)' \
-filter_complex \
[0:v]scale=980:-1[L0];\
[1:v]crop=600:600:20:20,scale=400:-1[L1];\
[L1][3:v]overlay=shortest=1[L2];\
[2:v][L0]overlay=20:20:shortest=1[L3];\
[L3][L2]overlay=W-420:H-420[vout] \
-map [vout] -map 0:a output.mp4
1st color input (2:v): This serves as the background canvas. Its framerate r=30 will be the output framerate.
2nd color input (3:v): This is the circular mask to the cropped two.mp4. Note that I fixed geq filter so the color is properly maintained (my earlier take was made for grayscale video)
one.mp4(0:v) gets scaled to the final size -> [L0]
two.mp4(1:v) is first cropped to square, capturing what to be shown in the circular cutout. crop arguments are w:h:x:y where the x:y is the coordinate of the upper-left corner. The cropped frame is then scaled to the final size (400x400 in this example) -> [L1]
The cropped and scaled two.mp4 ([L1]) is then masked by 3:v input to show through the circular cutout with the first overlay filter.
shortest=1 option for overlay filters to end when the videos ends (not color sources which will go on forever)
The final two overlay filters places the 2 prepared videos to desired places on the canvas. Adjust its arguments as needed to change positions
Because SD (720p) video inputs are converted to HD (1080p) video output, you may not need to do any scaling. If so, remove the scale filters from the filtergraph. For one.mp4, the first filterchain goes, so replace [L0] label with [0:v] in the modified filtergraph.
That should do it. As we went through earlier, when you run it, make sure to remove all the spaces, newlines, and backslashes in the middle of every filtergraph expression.
[original]
An approach I implemented in the past is to manipulate the masking image with geq filter. You can try the following:
For an illustration purpose, I use a rectangle with upper-left corner at (10,10) and lower-right corner at (1500,900) and a circle with its center at (1700,950) and radius 100.
ffmpeg -i input.mp4 \
-vf color=c=red:s=1920x1080:r=1:d=1,\
format=rgba,\
geq=lum='lum(X,Y)':a='if(between(X,10,1500)*between(Y,10,900)+lt((X-1700)^2+(Y-950)^2,100^2),0,255)',\
[v:0]overlay \
output.mp4
color source filter only generate 1 frame (1 fps for 1 second) and overlay apply it to every frame of the input video
color output does not have alpha channel, so you need to convert to a pix_fmt
geq sets the alpha values of all pixels: if coordinate (X,Y) is masked (so it assigns the alpha value of 255 = opaque) or True if (X,Y) is not masked (alpha = 0, 100% transparent). See FFmpeg Expressions Documentation.
overlay gets the input video stream v:0 and overlays the output of geq filter on it.
Because the filtergraph is implemented with -vf output option, inpnnut audio stream will be mapped automatically
[edit single line version]
ffmpeg -i input.mp4 -vf color=c=red:s=1920x1080:r=1:d=1,format=rgba,geq=lum='lum(X,Y)':a='if(between(X,10,1500)*between(Y,10,900)+lt((X-1700)^2+(Y-950)^2,100^2),0,255)',[v:0]overlay output.mp4

Adding two overlays in FFMPEG

I am adding an animated PNG overlay to an existing video with some text written right below the gif in ffmpeg using the command:
.\ffmpeg.exe -i vid.mp4 -ignore_loop 0 -i elephant.png -filter_complex "overlay=x=(main_w-overlay_w-10):y=(main_h-overlay_h-30):shortest=1, drawtext=fontfile=seguiemj.ttf:text='This is a test': fontcolor=white: fontsize=48: x=(w-text_w-250): y=(h-text_h-10)" output.mp4
Now, instead of text, I want to add another png in the same position as the text and using the same relative equations but I'm not sure how to write the variables for the second overlay? Since I'm already using overlay_w and overlay_h for the first image overlay, how can I define other variables for other overlay images?

FFMPEG - crop and pad a video (keep 3840x1920 but with black borders)

I am trying to crop a video so that I can remove a chunk of the content from the sides of a 360-degree video file using FFmpeg.
I used the following command and it does part of the job:
ffmpeg -i testVideo.mp4 -vf crop=3072:1920:384:0,pad=3840:1920:384:0 output.mp4
This will remove the sides of the video and that was initially exactly what I wanted (A). Now I'm wondering if it is possible to crop in the same way but to keep the top third of video. As such, A is what I have, B is what I want.:
I thought I could simply do this:
ffmpeg -i testVideo.mp4 -vf crop=3072:1920:384:640,pad=3840:1920:384:640 output.mp4
But that doesn't seem to work.
Any input would be very helpful.
Use the drawbox filter to fill cropped portion with default colour black.
ffmpeg -i testVideo.mp4 -vf drawbox=w=384:h=1280:x=0:y=640:t=fill,drawbox=w=384:h=1280:x=3840-384:y=640:t=fill -c:a copy output.mp4
The first filter acts on the left side, and the 2nd on the right.

Overlaying text on video with required angle using FFMPEG

I am trying to overlay some text on video using ffmpeg. I am able to overlay text by the bellow command.
ffmpeg -i input1.mp4 -filter_complex "[0:v]transpose=2[anticlockwiserotated];[anticlockwiserotated]drawtext=fontfile=../../public/fonts/Roboto-Regular-webfont.ttf: text='Test Text':x=100: y=50: fontsize=36: fontcolor=white:[textapplied];[textapplied]transpose=1" output_video.mp4
It is allowing me to overlay horizontally or vertically only.
But I want to append it with some angle like 45 degrees.
For that if I modify the command as
ffmpeg -i input1.mp4 -filter_complex "[0:v]rotate=45*PI/180[anticlockwiserotated];[anticlockwiserotated]drawtext=fontfile=../../public/fonts/Roboto-Regular-webfont.ttf: text='Test Text':x=100: y=50: fontsize=36: fontcolor=white:[textapplied];[textapplied]rotate=315*PI/180" output_video.mp4
By this I am getting overlay video as:
Because in this first I am rotating video to 45 degrees, appending text and bringing it back to original position. So I am loosing borders.
Please suggest me the best way to overlay text with required angle on video.
Thanks in advance.
Basic method is to generate text on a blank canvas, then an alpha layer for the text, rotating the result and overlaying that on the main video.
In the command below, a should be replaced by the angle. The co-ordinates for the drawtext are used in the overlay instead. Depending on the length of your text, some of it may get clipped if you've rotated it anticlockwise. So check and adjust the Y offset accordingly.
ffmpeg -i input1.mp4 -filter_complex
"color=black:100x100[c];
[c][0]scale2ref[ct][mv];
[ct]setsar=1,drawtext=fontfile=../../public/fonts/Roboto-Regular-webfont.ttf:
text='Test Text':fontsize=36:fontcolor=white,split[text][alpha];
[text][alpha]alphamerge,rotate=a:ow=rotw(a):oh=roth(a):c=black#0[txta];
[mv][txta]overlay=x='min(0,-H*sin(a))+100':y='min(0,W*sin(a))+50':shortest=1"
output_video.mp4
One method is by using ASS or SRT subtitles with the FFmpeg subtitles or ass filters.
ffmpeg -i input -filter_complex "subtitles=diagonal.ass" output
SRT subtitles are much simpler than ASS and don't support rotation, but you can manually add it with the filter:
ffmpeg -i input -filter_complex "subtitles=diagonal.srt:force_style='Angle=45'" output
You can create and style the subtitles with Aegisub or manually.

Resources