Answers.Body: <p>Ok, it can be done, but it's inelegant and has limitations, which make it in the end, not worthwhile. The limitation is that this only properly works with fixed-width fonts. And due to a <a href="https://trac.ffmpeg.org/ticket/3302" rel="nofollow">still-unfixed-bug</a> in ffmpeg, it will look somewhat ugly.</p>
  
  <p>But here it is,</p>
  
  <pre><code>ffmpeg -i input.mp4 -lavfi "color=white:1280x120,fps=30[c]; \
  [c]format=rgba, \
  drawtext=fontfile=cour.ttf:fontcolor=red:fontsize=60:text='    A   AB  ABC ABCD':x=0:y=0, \
  crop=144:120:min(144*trunc(2*t)\,432):0, \
  colorkey=FFFFFF:0.01:1,setpts=PTS+(delay/TB)[tx]; \
  [0:v][tx]overlay=576:600[out]" \
  -map [out] -map 0:a -c:a copy output.mp4
  </code></pre>
  
  <p>The basic flow is</p>
  
  <ol>
  <li>create an opaque canvas - I used full width as my video input and enough height to contain the text, and I used the same framerate as my video</li>
  <li>On this canvas, draw the text once. The basic method here is to animate the crop window. So if your text is 5 characters long, then your print string is <code>text='     1    12   123  1234 12345'</code>. The idea is that the crop width is equal to the full string width and the crop source shifts one string width periodically, thus simulating typing, since each new cropped area contains one additional character. So, first 5 blank spaces for the 5 characters, then after the first <code>1</code> there are four spaces to pad out till a full string width is reached, then the 2nd stage text follows with 2 characters and 3 spaces, and so on. I've specified the color space of RGBA since it seemed to provide better results in the keying step further on.</li>
  <li>Now the canvas with text on it is cropped. Width is the full string width, and I've kept the same height, but as long it doesn't cut the text, doesn't matter. The crop offset X is animated as follows: <code>StringWidth * integer part of (time divided by period)</code>. This shifts the crop window right by one string width after every period i.e. 0.5 seconds in this case. Now, this is enclosed in a minimum function because we want the crop to stay still after all characters have been printed. So, the 2nd value is <code>stringWidth * (no. of characters - 1)</code>. Y isn't animated since this is one line only.</li>
  <li>The next part makes it ugly. Because of the bug, I kept the background opaque. So, now it has to be chroma keyed out. The filter looks for the BG color of white, and selects only that color (<code>0.01</code>) and fully blends it. I was hoping to smooth out the edges. But doesn't work very well.</li>
  <li>The setpts allows to set a delay in seconds. The first character will appear at <code>delay + period</code> seconds. </li>
  <li>Finally, we simply overlay the result on the video.</li>
  </ol>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-02-04T15:10:36.763Z
Answers.Text: ok this is really complicated.. I will check this and see if I can handle it. Could it have been done using several iterations and not trying to do it all in command pass. and (sorry if this is wrong etiquette) but are you available to do some freelance work on this project... it is clear that I am out of my league here.
Answers.UserDisplayName: eof
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-02-04T16:15:42.813Z
Answers.Text: Well looks like ffmpeg is crashing after consuming too much memory every time I run this. And since I cannot use fixed width fonts I need to explore different routes. Can maybe I render a stand alone video that has the name, and a simple croping from left to right. Than overlay that video onto the other video. Maybe the first video has transperancy/alpha, or maybe just use chromakey (green screen) when overlaying with no need for alpha channel? Anyway, let me know if you are available for freelance or know anyone that is . Thanks for all the help...
Answers.UserDisplayName: eof
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-02-04T18:21:53.690Z
Answers.Text: leave your email and I'll get in touch.
Answers.UserDisplayName: Gyan
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-02-04T20:11:02.840Z
Answers.Text: eran_stackoverflow_nzxy at mailnicks dot org
Answers.UserDisplayName: eof
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-02-04T12:28:00.947Z
Answers.LastActivityDate: 2016-02-04T13:01:20.163Z
Answers.LastEditDate: 2016-02-04T13:01:20.163Z
Answers.UserDisplayName: Gyan
Body: <p>I am trying to write text on a video in such a way that the text "writes itself" - letter by letter.</p>
  
  <p>To do this I was able to do something like this:</p>
  
  <pre><code>-vf "[in]drawtext=text='a':fontfile='/Windows/Fonts/arial.ttf'\
  :enable='between(t\,1\,1.5)':x=300:y=(h)-100-th, \
  drawtext=text='ab':fontfile='/Windows/Fonts/arial.ttf':enable='between(t\,1.5\,2)':\
  x=300:y=(h)-100-th"
  </code></pre>
  
  <p>This replaces the text on screen with a new one every half a second adding a new character. ( <code>a</code> changes to <code>ab</code> ). Obviously if the texts are long than this line would be really long.</p>
  
  <p>I was able to do something similar and shorter with :</p>
  
  <pre><code>-vf "[in]drawtext=fontsize=80:shadowcolor=Black:shadowx=2:shadowy=2:fontcolor=White:\
  fontfile='/Windows/Fonts/arial.ttf':text='%{expr\:if(gt(t\,1.5)\,12\,1)}':\
  x=300:y=(h)-100-th"
  </code></pre>
  
  <p>Where the text itself is an expression dependent on time. However this only works for numbers: <code>1</code> changes to <code>12</code> (ignoring the numbers after the decimal point for now).</p>
  
  <p>Now the issue is that if I try to do the same expression for texts (<code>a-&gt;ab</code>) this fails. and I get: </p>
  
  <blockquote>
    <p>Expression 'if(gt(t,1.5),ab,a)' for the expr text expansion function is not valid.</p>
  </blockquote>
  
  <p>The question is: Is it possible to have the expression return <em>the actual text</em> after expansion and <strong>not</strong> just <em>numbers</em>?.</p>
  
  <p>Thanks in advance for anyone helping!</p>
  
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2016-02-03T14:59:57.447Z
Comments.Text: Try with `'if(gt(t,1.5),'ab','a')'`
Comments.UserDisplayName: Gyan
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2016-02-03T17:07:04.160Z
Comments.Text: tried that (and with all conbinations of \, \' \" etc...) didn't help
Comments.UserDisplayName: eof
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2016-02-03T17:49:27.477Z
Comments.Text: Other than the ultralong multiple drawtexts approach, your choice is to draw the full text to a blank canvas, animate a crop and overlay the result on the video.
Comments.UserDisplayName: Gyan
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2016-02-03T19:11:20.940Z
Comments.Text: Thats an interesting idea.... But can I do it with a transparent background so to overlay just the text?
Comments.UserDisplayName: eof
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2016-02-03T19:18:05.983Z
Comments.Text: Yeah, use `color=black@0.0:WxH`
Comments.UserDisplayName: Gyan
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2016-02-03T19:54:46.500Z
Comments.Text: ah.... thats a little over my head. I assume I need to create a mov file that has an alpha channel somehow?
  
  I trried this with no success:
  
  ffmpeg -f lavfi -i color=c=0x00000000:s=320x240:d=2 -vcodec qtrle -pix_fmt argb -vf "drawtext=fontfile=/Windows/Fonts/arial.ttf:fontsize=30:fontcolor=white:x=(w-text_w)/2:y=(h-text_h-line_h)/2:text='Stack Overflow'" -y output.mov
Comments.UserDisplayName: eof
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2016-02-03T20:06:54.213Z
Comments.Text: Give me till tomorrow. I'll work this out.
Comments.UserDisplayName: Gyan
Tags: <ffmpeg>
Title: ffmpeg drawtext text parameter expressions
UserDisplayName: eof
ThreadText: # ffmpeg drawtext text parameter expressions
  
  (Asked by: username_0 on 2016-02-03)
  
  I am trying to write text on a video in such a way that the text "writes itself" - letter by letter.
  
  To do this I was able to do something like this:
  
  ```
  -vf "[in]drawtext=text='a':fontfile='/Windows/Fonts/arial.ttf'\
  :enable='between(t\,1\,1.5)':x=300:y=(h)-100-th, \
  drawtext=text='ab':fontfile='/Windows/Fonts/arial.ttf':enable='between(t\,1.5\,2)':\
  x=300:y=(h)-100-th"
  
  ```
  
  This replaces the text on screen with a new one every half a second adding a new character. ( `a` changes to `ab` ). Obviously if the texts are long than this line would be really long.
  
  I was able to do something similar and shorter with :
  
  ```
  -vf "[in]drawtext=fontsize=80:shadowcolor=Black:shadowx=2:shadowy=2:fontcolor=White:\
  fontfile='/Windows/Fonts/arial.ttf':text='%{expr\:if(gt(t\,1.5)\,12\,1)}':\
  x=300:y=(h)-100-th"
  
  ```
  
  Where the text itself is an expression dependent on time. However this only works for numbers: `1` changes to `12` (ignoring the numbers after the decimal point for now).
  
  Now the issue is that if I try to do the same expression for texts (`a->ab`) this fails. and I get:
  
  > Expression 'if(gt(t,1.5),ab,a)' for the expr text expansion function is not valid.
  
  The question is: Is it possible to have the expression return *the actual text* after expansion and **not** just *numbers*?.
  
  Thanks in advance for anyone helping!
  
  **Tags:** ffmpeg
  
  > **Comments:**
  > **username_1**: Try with `'if(gt(t,1.5),'ab','a')'`  
  > **username_0**: tried that (and with all conbinations of \, \' \" etc...) didn't help  
  > **username_1**: Other than the ultralong multiple drawtexts approach, your choice is to draw the full text to a blank canvas, animate a crop and overlay the result on the video.  
  > **username_0**: Thats an interesting idea.... But can I do it with a transparent background so to overlay just the text?  
  > **username_1**: Yeah, use `color=black@0.0:WxH`  
  > **username_0**: ah.... thats a little over my head. I assume I need to create a mov file that has an alpha channel somehow?  I trried this with no success:  ffmpeg -f lavfi -i color=c=0x00000000:s=320x240:d=2 -vcodec qtrle -pix_fmt argb -vf "drawtext=fontfile=/Windows/Fonts/arial.ttf:fontsize=30:fontcolor=white:x=(w-text_w)/2:y=(h-text_h-line_h)/2:text='Stack Overflow'" -y output.mov  
  > **username_1**: Give me till tomorrow. I'll work this out.  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2016-02-04. Score: 3
  
  Ok, it can be done, but it's inelegant and has limitations, which make it in the end, not worthwhile. The limitation is that this only properly works with fixed-width fonts. And due to a [still-unfixed-bug](https://trac.ffmpeg.org/ticket/3302) in ffmpeg, it will look somewhat ugly.
  
  But here it is,
  
  ```
  ffmpeg -i input.mp4 -lavfi "color=white:1280x120,fps=30[c]; \
  [c]format=rgba, \
  drawtext=fontfile=cour.ttf:fontcolor=red:fontsize=60:text='    A   AB  ABC ABCD':x=0:y=0, \
  crop=144:120:min(144*trunc(2*t)\,432):0, \
  colorkey=FFFFFF:0.01:1,setpts=PTS+(delay/TB)[tx]; \
  [0:v][tx]overlay=576:600[out]" \
  -map [out] -map 0:a -c:a copy output.mp4
  
  ```
  
  The basic flow is
  
  1. create an opaque canvas - I used full width as my video input and enough height to contain the text, and I used the same framerate as my video
  2. On this canvas, draw the text once. The basic method here is to animate the crop window. So if your text is 5 characters long, then your print string is `text=' 1 12 123 1234 12345'`. The idea is that the crop width is equal to the full string width and the crop source shifts one string width periodically, thus simulating typing, since each new cropped area contains one additional character. So, first 5 blank spaces for the 5 characters, then after the first `1` there are four spaces to pad out till a full string width is reached, then the 2nd stage text follows with 2 characters and 3 spaces, and so on. I've specified the color space of RGBA since it seemed to provide better results in the keying step further on.
  3. Now the canvas with text on it is cropped. Width is the full string width, and I've kept the same height, but as long it doesn't cut the text, doesn't matter. The crop offset X is animated as follows: `StringWidth * integer part of (time divided by period)`. This shifts the crop window right by one string width after every period i.e. 0.5 seconds in this case. Now, this is enclosed in a minimum function because we want the crop to stay still after all characters have been printed. So, the 2nd value is `stringWidth * (no. of characters - 1)`. Y isn't animated since this is one line only.
  4. The next part makes it ugly. Because of the bug, I kept the background opaque. So, now it has to be chroma keyed out. The filter looks for the BG color of white, and selects only that color (`0.01`) and fully blends it. I was hoping to smooth out the edges. But doesn't work very well.
  5. The setpts allows to set a delay in seconds. The first character will appear at `delay + period` seconds.
  6. Finally, we simply overlay the result on the video.
  
  > **Comments:**
  > **username_0**: ok this is really complicated.. I will check this and see if I can handle it. Could it have been done using several iterations and not trying to do it all in command pass. and (sorry if this is wrong etiquette) but are you available to do some freelance work on this project... it is clear that I am out of my league here.  
  > **username_0**: Well looks like ffmpeg is crashing after consuming too much memory every time I run this. And since I cannot use fixed width fonts I need to explore different routes. Can maybe I render a stand alone video that has the name, and a simple croping from left to right. Than overlay that video onto the other video. Maybe the first video has transperancy/alpha, or maybe just use chromakey (green screen) when overlaying with no need for alpha channel? Anyway, let me know if you are available for freelance or know anyone that is . Thanks for all the help...  
  > **username_1**: leave your email and I'll get in touch.  
  > **username_0**: eran_stackoverflow_nzxy at mailnicks dot org  
  
  ---
  
  