5

Does anyone have a good recipe for escaping all of the special characters (',%,\,:,{,}) from a String in java, that will be used in an ffmpeg drawtext filter chain? Trying to use replaceAll with different combinations of escaping has been an exercise in frustration!

String myTextString = "Bob's special\cool mix:stuff @ 40% off"; Runtime.getRuntime().exec(new String[] { "ffmpeg",...., "filter_complex", "drawtext=enable='between(t,0,10)':x=10:y=10:fontfile=Roboto-Black.ttf:text='" + myTextString + "':fontcolor=#a43ddb:fontsize=14", ... });

ffmpeg drawtext filter: https://ffmpeg.org/ffmpeg-filters.html#drawtext-1

ezwrighter
  • 997
  • 8
  • 18
  • Have you tried any regular expressions? – Ulises André Fierro Aug 03 '17 at 20:44
  • I have attempted a chain of replaceAll functions that replaced backslashes and then attempted to replace each special character. But all of the escaping between java, replaceAll, Strings, runtime exec, ffmpeg & drawtext....I think some miracle is needed to get it correct :-) Was hoping someone had already figured out the incantation needed. – ezwrighter Aug 03 '17 at 20:55
  • Have a look at https://stackoverflow.com/questions/13696461/replace-special-character-with-an-escape-preceded-special-character-in-java – Ulises André Fierro Aug 03 '17 at 20:56
  • Thanks Ulises...unfortunately, that doesn't really get to the crux of the issue with the combination of all the tools :-( – ezwrighter Aug 03 '17 at 21:09
  • You're concatenating strings and then need to escape a set of characters right? If that's the case, the logic can be applied to the scenario you presented – Ulises André Fierro Aug 03 '17 at 21:24
  • The logic is what eludes me...if you have an answer shoot :-) – ezwrighter Aug 03 '17 at 21:50

3 Answers3

12

Alright...after banging my head against a wall for getting the right escape patterns to satisfy both java and ffmpeg I came up with this:

MyDrawTextString.replaceAll("\\\\", "\\\\\\\\\\\\\\\\").replaceAll("'", "'\\\\\\\\\\\\\''").replaceAll("%", "\\\\\\\\\\\\%").replaceAll(":", "\\\\\\\\\\\\:");

Looks insane, but it works! Note: I had to double my backslashes in my answer here to get this to display correctly too :-P Dang those backslashes.

The key is ffmpeg drawtext needs 3 backslashes to escape (',%,:) and single quotes need to also be wrapped in a second pair of single quotes. Java String needs 2 backslashes to make one and java replaceAll regex needs to have 2 backslashes to make a single one in a string. Therefore you need (2+2)*3 backslashes to escape things in drawtext filter string!

ezwrighter
  • 997
  • 8
  • 18
  • I'm having a similar problem, except it's with the double quotes. How do you escape that? Is it the same as escaping single quotes? – NatashaC Jan 27 '18 at 17:11
2

Just put your text into a text file (e.g. myText.txt) and use the textfile option:

-> myText.txt:

This is my text with special characters: ,(,),'

Then instead of using:

ffmpeg -i test.mpg -vf drawtext="This is my text with special characters :,(,),'"

Use the following command:

ffmpeg -i test.mpg -vf drawtext=textfile=textFile.txt
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
Sina Gh
  • 39
  • 2
0

for Python (in Colab)

Hi, I ran into the same issue using Google Colab and Python. For those looking for a solution, this might help.

I execute the ffmpeg commandline as follows:

!ffmpeg ... -filter_complex "$texts" ...

... where texts refers to a string variable containing the mentioned filteres with drawtext option.

For me worked:

texts = ... # init

def normalize_text(t):
  return t\
  .replace("\\", "\\\\")\
  .replace('"', '""')\
  .replace("'", "''")\
  .replace("%", "\\%")\
  .replace(":", "\\:")

texts = normalize_text(texts) #normalize
!ffmpeg ... #execute

As you can see, escaping it once has worked for me. Note: this function might be extended to include certain other characters which will result in an error message being displayed upon execution, something along the lines of "filter could not be parsed" or "no option XXX" and more.

Thanks guys

товіаѕ
  • 2,881
  • 4
  • 23
  • 53