ffmpeg burned-in subtitles render in the wrong font - python

Trying to burn in subtitles to a video in FFMPEG in GothamProBold font. No matter what I do it keeps reverting to Helvetica. From the console, I see that FFMPEG seems to load the font without error. Then switches over to font provider "coretext"
[Parsed_subtitles_0 # 0x7fed054048c0] Loading font file '/Projects/Fonts/GothaProBol.otf'
[Parsed_subtitles_0 # 0x7fed054048c0] Using font provider coretext
[Parsed_subtitles_0 # 0x7fed054048c0] fontselect: (GothaProBol.otf, 400, 0) -> /System/Library/Fonts/Helvetica.ttc, -1, Helvetica
It seems like it has my font loaded, then loads what is likely a system default of Helvetica instead. My guess is that my chosen font isn't actually loading after all.
FFMPEG command (called from python) is as follows:
ffmpeg_cmd = ["ffmpeg",
"-i", self.source_video_uri,
"-y",
"-c:v", "prores", "-profile:v", "1",
"-c:a", "pcm_s16be",
"-vf", f"subtitles={srt_uri}:fontsdir=/Projects/Fonts:force_style='Fontname=GothaProBol.otf'",
f"{self.source_video_uri}_render.mov"]
subprocess.call(ffmpeg_cmd)
Any ideas?
UPDATE: Found this setting in libass header file "ass.h" - which ffmpeg calls when using the subtitle filter. Don't know how to actually set this variable when ffmpeg calls libass, but here it is. Line 182:
* \brief Default Font provider to load fonts in libass' database
*
* NONE don't use any default font provider for font lookup
* AUTODETECT use the first available font provider
* CORETEXT force a CoreText based font provider (OS X only)
* FONTCONFIG force a Fontconfig based font provider
*
* libass uses the best shaper available by default.
*/
typedef enum {
ASS_FONTPROVIDER_NONE = 0,
ASS_FONTPROVIDER_AUTODETECT = 1,
ASS_FONTPROVIDER_CORETEXT,
ASS_FONTPROVIDER_FONTCONFIG,
ASS_FONTPROVIDER_DIRECTWRITE,
} ASS_DefaultFontProvider;
RE: ANSWER BELOW: For the most part, it seems that if your font is installed in /System/Fonts or /Library/Fonts then CoreText can find it. Though in some cases, the naming conventions can be quite particular and non-intuitive. It also can't seem to find all fonts, necessarily.
For example: Gotham Pro Bold, in the /Library/Fonts folder on my system, file named "GothaProBol.otf" is correctly passed to fontname as: GothamPro-Bold or just Gotham Pro. Gotham Pro Bold, GothamPro, Gotham Pro-Bold, GothaProBol, and GothaProBol.otf do NOT work.
For most fonts it seems the preferred convention is {FontName}-{Style/Weight} as displayed in Mac OS's FontBook, not the filename.
That said, I have a novelty 'Game of Thrones.ttf' font in the same folder as Gotham Pro, and I can't get CoreText to connect to it under any of the above naming conventions.

Do not put the file extension in the font name:
force_style='fontname=GothamPro-Bold'
In my case I got a file called GothamPro-Bold.otf and the output was like this:
[Parsed_subtitles_0 # 0x55c809fd73c0] Shaper: FriBidi 0.19.7 (SIMPLE) HarfBuzz-ng 2.6.4 (COMPLEX)
[Parsed_subtitles_0 # 0x55c809fd73c0] Loading font file './fonts/GothamPro-Bold.otf'
[Parsed_subtitles_0 # 0x55c809fd73c0] Using font provider fontconfig
[Parsed_subtitles_0 # 0x55c809fd73c0] fontselect: (GothamPro-Bold, 400, 0) -> GothamPro-Bold, 0, GothamPro-Bold

I got the custom fonts working in FFMPEG subtitles filter. 🎉
(I'm using a Mac and FFMPEG-PYTHON which is just a wrapper around FFMPEG).
I also have the font files in a folder local to my project.(./fonts) and changing the font file name or using the font name shown in Mac's Font-Book doesn't work.
So here is how I got it working...
Open the font file in Font Forge you can download it here - FontForge.
Click on the Elements tab and then Font Info
You can see the font name on the top
Use the font name exactly as you see it as the FFMPEG force_style args
fontsdir='./fonts',force_style='FontName=HelveticaRoundedLTStd-BdCn,PrimaryColour=0x7FFFD4,Fontsize= 26
Here are my terminal logs showing that it's loading the custom font.
Hope this helps 🚀🚀🚀

I've been trying to solve the same problem all evening, finally figured it out.
OP said that 'Game of Thrones.ttf' didn't work but 'GothaProBol.otf' did.
So I used an online tool to convert my custom font from .ttf to .otf
Then copied my custom font into /Library/Fonts/fontname.otf
Then used the POSTSCRIPT-NAME from Font Book and it worked beautifully :-)
ffmpeg -i input.mp4 -vf "subtitles=subtitle.ass:force_style='Fontname=CUSTOMfontBlack-Regular'" output.mp4

Related

Specifying a Font from a file location ptext in pygame

I understand how to use a font from the .ttf file in normal python.
font1 = pygame.font.Font("/resources/fonts/robotoThin.ttf")
but I could not find in the documentation of ptext, or on the web how to specify the font when using
ptext.draw(text,(x,y))
Using pycharm
According to the ptext repo's README, you can specify the fontname parameter in your call to ptext.draw like so:
ptext.draw(text, (x,y), fontname="fonts/Viga.ttf")
There are also options for creating templates for the fontname (see the link above) but I'm not seeing a way to save the font as a variable to avoid reloading it every time.

Use matplotlib.pyplot.rcparams with a custom font which is not installed

I'm trying to use a custom ttf font not installed in the system for text element in the matplotlib figure.
with plt.style.context('mplparams.mplstyle'):
plt.plot(np.sin(np.linspace(0, 3 * np.pi)), '-o')
I know I can change the text properties with FontManager but I'm looking for a solution which only involves an external config file.
At the moment I only know that i can change font.sans-serif to a font name, not font path.
Is this possible?
The font to be used has to be known to the Fontmanager, otherwise you cannot get it into the plot. In order to specify a font through rcParams this font must be found in a folder matplotlib would look for it. In case you don't want to install anything, you may copy the .ttf file to the matplotlib font folder. In my case this is
python\Lib\site-packages\matplotlib\mpl-data\fonts
Then you need to clear the font.chache. Find out its path via print(matplotlib.get_cachedir()) and delete the fontList files. (Or make a backup first if you like).
Then run your script which has the rcParam specified
font.sans-serif : <name of font>
or use
plt.rcParams['font.sans-serif'] = "<name of font>"
Also see this question.

Get font file from font family

Having a difficult time trying to get the proper .ttf file from the font family.
Currently trying to use pygame to work on some graphics and it has its own internal search function to find a font file from the Font Family but it's not correct.
Also tried using matplotlib.font_manager. This also is not correct.
import matplotlib.font_manager as font_manager
import pygame
pygame.font.init()
print(font_manager.findfont('Segoe UI'))
> C:\WINDOWS\Fonts\seguisb.ttf
print(pygame.font.match_font('Segoe UI'))
> C:\WINDOWS\Fonts\segoeuil.ttf
print(font_manager.findfont('Arial'))
> C:\WINDOWS\Fonts\arial.ttf
print(pygame.font.match_font('Arial'))
> C:\WINDOWS\Fonts\ARIALN.TTF
I'm hoping there's something I missed and there is a way to get a complete match on the search, not a partial match (I'm guessing both methods used are reading the byte array and returning the closest matching font based on the Family. I.e., 'Segoe UI' is in 'Segoe UI Bold' so it was returned as the match).
I recommend to use pygame.font.SysFont():
Return a new Font object that is loaded from the system fonts. The font will match the requested bold and italic flags. Pygame uses a small set of common font aliases. If the specific font you ask for is not available, a reasonable alternative may be used. If a suitable system font is not found this will fall back on loading the default pygame font.

Creating a lightweight fallback font with fontforge and fonttools

For a webapp I need a way to prevent that a browser falls back to another font if my web font doesn't include a character. It seems the only way to do this is to add another font to the fontstack which includes "all" possible characters 1.
There are already existing fallback fonts, but those are more debug helpers as they show the codepoint as number, therefore they are much to heavy (>2MB).
The fallback font for my usecase should just show something like a box to signal a missing character.
My idea was to generate a simple font with only one glyph and apply a feature file which will replace all glyphs with this one.
My script for fontforge:
import fontforge
import fontTools.feaLib.builder as feaLibBuilder
from fontTools.ttLib import TTFont
font_name = 'maeh.ttf'
font = fontforge.font()
glyph = font.createChar(33, "theone")
pen = glyph.glyphPen()
pen.moveTo((100,100))
pen.lineTo((100,500))
pen.lineTo((500,500))
pen.lineTo((500,100))
pen.closePath()
for i in range(34, 99):
glyph = font.createChar(i)
glyph.width=10
font.cidConvertTo('Adobe', 'Identity', 0) # doesn't make a difference
font.generate(font_name)
font = TTFont(font_name)
feaLibBuilder.addOpenTypeFeatures(font, 'fallback.fea')
font.save("fea_"+font_name)
My feature file:
languagesystem DFLT dflt;
#all=[\00035-\00039];
##all=[A-Z] this works
feature liga {
sub #all by theone;
} liga;
But the above results in a
KeyError: ('cid00037', 'SingleSubst[0]', 'Lookup[0]', 'LookupList')
with changing numbers for cid00037.
If I use the out commented A-Z from the Feature file it works, so this approach doesn't seem to be completely wrong.
Why can't fonttools find the glyphs if I specify the range in CID notation?
Is there another way to crate a class for the OpenType feature file which includes all glyphs?
While working on the above problem, somebody hinted me to the Adobe NotDef font, which is pretty much what I was looking for. For some reason I wasn't able to convert the .otf of the Adobe NotDef to woff or woff2 with fontforge. Also all the online tools to create the web font files like fontsquirrel failed. To create the woff file I used sfnt2woff from the woff-tools package. For the woff2 file I used https://github.com/google/woff2.

What's the name of this font used in this figure?

I want to use this font in matplotlib plotting, but I can not find out the name. Does anyone know?
This figure is got by IDL plotting on Mac OS (10.9) like:
filename = 'name.eps'
myDevice = !D.NAME
SET_PLOT,'ps'
DEVICE,DECOMPOSED=1,ENCAPSULATED=1,/COLOR,FILENAME=filename
......
DEVICE, /CLOSE
SET_PLOT, myDevice
I'm not a font expert, but this looks a lot to me like the font that was used with pen plotters. Looking around for "pen plotter font", turns up "Hershey Vector Font", which looks quite close.
The font is indeed a Hershey vector font: Hershey Simplex Light. This user on Github has the font definition files (otf) that you can copy/clone into your system and set as the default fonts in your matplotlibrc. Not all the characters are included, but you can use fontforge to open the otf and/or sfd files and merge/copy/create missing glyphs.
(updated in 2022)
I think this font is a kind of vector font belonging to the Hershey family.
Here is a set of TTF fonts that are based on the Hershey font https://github.com/yangcht/Hershey_font_TTF.
You can download them and load them when you make plots.

Categories

Resources