Page 1 of 1

Adding text to video frames?

Posted: 2011-06-23T00:14:58-07:00
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

Re: Adding text to video frames?

Posted: 2011-06-23T08:21:25-07:00
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).

Re: Adding text to video frames?

Posted: 2011-06-23T20:24:16-07:00
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!

Re: Adding text to video frames?

Posted: 2011-06-23T20:34:44-07:00
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?

Re: Adding text to video frames?

Posted: 2011-06-24T05:10:53-07:00
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.

Re: Adding text to video frames?

Posted: 2011-06-24T10:45:06-07:00
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.

Re: Adding text to video frames?

Posted: 2011-06-24T17:11:22-07:00
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.

Re: Adding text to video frames?

Posted: 2011-06-24T17:17:25-07:00
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

Re: Adding text to video frames?

Posted: 2011-06-25T10:17:41-07:00
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.