Adding text to video frames?

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
refsvik
Posts: 2
Joined: 2011-06-21T23:32:29-07:00
Authentication code: 8675308

Adding text to video frames?

Post by refsvik »

Hi,

I have extracted numbered still frames (1080) from a video sequence using ffmpeg, and want to see if I can write text (single line text credits) on the frames before collecting the PNGs back together as a movie again with ffmpeg afterwards.

There appears to be a number of ways to do this in imagemagick, and I just wanted to be pointed in the most productive direction (convert, montage, append, caption).

What I want to do is to write a text line (white with drop shadow, utf8, size around 50) in the middle of the images and have it fade in and out again (opacity?), each with a duration of 25 frames. I am aware that some clever loops may be involved, but I can handle that.

Best regards,

Kjell Are Refsvik
Lillehammer, Norway
User avatar
glennrp
Posts: 1147
Joined: 2006-04-01T08:16:32-07:00
Location: Maryland 39.26.30N 76.16.01W

Re: Adding text to video frames?

Post by glennrp »

I'd probably use a looping script with "convert -draw ..." at the heart of it.
However, this doesn't quite work:

Code: Select all

convert frame.png -draw 'image "dissolve 10x100" 100,100 0,0 text.png' combined.png
This overlays the text.png over the frame.png as if I'd used "over" instead of "dissolve 10x100" (I also tried 100x10, and tried swapping the quotes and double-quotes, but got the same result).
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Adding text to video frames?

Post by anthony »

Of course looping through images, using one command per image is probably the easiest to implement.

One method of looping over a large number of images, as a 'image stream' without saving intermeditae images, was demonstrated in another similar discussion. However the images are streams using ASCII PPM file format.
viewtopic.php?f=2&t=18320&p=71150
and resulting in the script
http://www.imagemagick.org/Usage/script ... m_pipeline

But these methods require you to constantly start (fork) a separate process or command for each image. That is you would be starting a new process and initializing (setup) the core library once for each image, which can be in-efficent.

At this time you can only truely avoid forking a "convert" comamnd multiple times by using some other non-shell API, so that the library only is configured once. Then have it read, process, write and destory (remove from memory) each frame in turn.

In shell scripts you can minimise startup time by processing images using mogrify which reads and processes one of the given image file at a time. Mogrify works by cycling though the non-image command line options once for each image.
http://www.imagemagick.org/Usage/basics/#mogrify

That however is limited, it is hard to modify the arguments being used for each image (say for the credit string and its position). You also can not easily compose or merge two or more images onto each frame.

You can also read a small batch of images, say 10 to 50 frames (depending on memory) using convert, and a technique for using the input filename to set the output filename of each image. See "Using Convert Instead of Morgify"
http://www.imagemagick.org/Usage/basics ... fy_convert
Which may be useful for say a static credit on N frames, then a different credit for the next N frames and so on.

You can also generate a very long convert command that reads, processes, and writes (deleting from memory) one image at a time. This lets you use one command, but apply different operations for each image (say drawing scrolling credits, or adding a side animation that is common on modern movies).

For example

Code: Select all

    convert \
         ... \
        "frame_0053.png"  -annotate +10+30 "Camera 1: John Doe" -write  "new_0053.png" +delete \
        "frame_0054.png"  -annotate +10+27 "Camera 1: John Doe" -write  "new_0054.png" +delete \
        "frame_0055.png"  -annotate +10+24 "Camera 1: John Doe" -write  "new_0055.png" +delete \
        ... \
        null:
At any one only one frame is in memory, but you only one one comment to process that batch of images. The technqiue also allows you to be free to do ANYTHING you like.

For example you can have a extra image in memory with each frame (in turn). Such as one very long static credit image that you can then overlay on your smaller video frame, at different offsets so as to generate a long sequence of scrolling text over the top of your video.

The limitation with this is at the length of the command line! Not all shells will having a command line longer than one to two thousand characters (bash seems to hand long command lines though).

But it is most versatile and efficient technique, as you don't have to fork, settup, or re-read secondary images over and over.


This brings me to -- The Future.

I have plans to re-write the CLI interface in IM version 7, so that IM can read image processing options from a file instead of just the command line. this will allow you to 'script' the image processing.

Further I plan to be very strict in how it works so you can even pipeline commands into the image processing command, which means you can run a 'image processor' in the background, and have the wrapping script (shell or otherwise) feed it operations to perform and even receive feedback on those operations, as they are done (or even do other things while they are being done). A technique known as 'co-processing' (google for it).

You can think of it as the shell running and controlling a image processing 'daemon' which holds the images and process them according to the shell.

In this method. you have no command line limits, and only imagemagick one command needs to be run. The shell can even modify its actions based on feed back from the image processor.

In otherwords... scripted image processing with feedback.

For example: it could study the frames and change its annotation of the the image based on the frame contents. Imagemagick supplies the image processing, the wrapping script supplies the 'intelligence'.

Exciting times -- stay tuned!
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: Adding text to video frames?

Post by anthony »

glennrp wrote:I'd probably use a looping script with "convert -draw ..." at the heart of it.
However, this doesn't quite work:

Code: Select all

convert frame.png -draw 'image "dissolve 10x100" 100,100 0,0 text.png' combined.png
This overlays the text.png over the frame.png as if I'd used "over" instead of "dissolve 10x100" (I also tried 100x10, and tried swapping the quotes and double-quotes, but got the same result).
The -draw image composition arguments is only a geometry resize and offset placement, You can not specify the other special arguments needed for compositions such as 'dissolve' in that way.

However while I have not tested it. I believe you can use the -define compose:args=??? before the -draw operation to set those arguments. But why not just use the -composite operator instead?
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
glennrp
Posts: 1147
Joined: 2006-04-01T08:16:32-07:00
Location: Maryland 39.26.30N 76.16.01W

Re: Adding text to video frames?

Post by glennrp »

use -composite
I was looking for a simple command, and didn't understand the documentation for -composite.

Code: Select all

convert frame.png -page +150+100 -compose "dissolve 50" text.png combined.png
doesn't work either; the text is properly placed but again it's opaque. And this fails in the same manner:

Code: Select all

composite -gravity center -compose "dissolve 50" text.png frame.png  composite.png
(I'm testing with IM-6.7.0-8)
PS Ahah, this works!

Code: Select all

composite -gravity center -dissolve 50 text.png frame.png  dissolve.png
So to answer the original question, you could put this at the heart of the loop, with the filenames (text, frame) and the dissolve percentage (50) being loop variables.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Adding text to video frames?

Post by fmw42 »

Glenn,

see convert with -compose dissolve and a -set or -define near the bottom of:
http://www.imagemagick.org/script/compose.php

convert ... -compose dissolve -define compose:args=src_percent[xdst_percent] -composite ...

so that you don't have to use composite, but convert, if you want.
User avatar
glennrp
Posts: 1147
Joined: 2006-04-01T08:16:32-07:00
Location: Maryland 39.26.30N 76.16.01W

Re: Adding text to video frames?

Post by glennrp »

OK. So the "special augmented compose operators" such as "dissolve" can't be used with the convert -draw option, at least at present.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Adding text to video frames?

Post by fmw42 »

glennrp wrote:OK. So the "special augmented compose operators" such as "dissolve" can't be used with the convert -draw option, at least at present.
I believe that is correct, but Anthony is the one to confirm that.

Blend and Dissolve are not listed as compose options on http://www.imagemagick.org/script/magic ... aphics.php
User avatar
whugemann
Posts: 289
Joined: 2011-03-28T07:11:31-07:00
Authentication code: 8675308
Location: Münster, Germany 52°N,7.6°E

Re: Adding text to video frames?

Post by whugemann »

If you are working under Windows, you should give AVIsynth a try, which is a more convenient than IM when it comes to video processing. Use VirtualDub as the Interface and AvSP as the Editor. The way to achieve what you are trying to do would be the runtime function ScriptClip or ConditionalReader. With AVIsynth, you do not have to split the video into single frames and re-assemble these; you can do it all in a single run.
Wolfgang Hugemann
Post Reply