Description
The buildTextFilter function in src/lib/text-overlay.ts generates an invalid FFmpeg drawtext filter string. It contains two bugs that silently break text rendering in all video exports.
Bug A — invalid fontweight= parameter
fontweight= is not a valid FFmpeg drawtext option. FFmpeg silently ignores unknown parameters, so bold text is never rendered bold in any export. The correct parameter is bold=1.
Bug B — fontfile= set to font name, not file path
For any overlay with a fontFamily, the filter appends fontfile='Arial' (or whatever the sanitised name is). FFmpeg expects a filesystem path here, not a font name. This causes FFmpeg to attempt to open a file literally named Arial, which fails silently.
For custom fonts, getFFmpegFontArg then appends the real fontfile= path immediately after, producing a duplicate key in the filter string.
Affected File
src/lib/text-overlay.ts — lines 92–102
Steps to Reproduce
- Upload any video and add a text overlay.
- Set the font weight to Bold.
- Export the video.
- Open the exported file — the text will not be bold.
For custom fonts, the export may fail with an FFmpeg filter error due to the duplicate fontfile= key.
Current Behaviour
// Generated filter (broken)
drawtext=...:fontweight=bold:fontfile='Arial'
// ↑ not a real FFmpeg param ↑ name, not a file path
Expected Behaviour
// Correct — bold flag only when needed
drawtext=...:bold=1
// For custom fonts, append only the real file path
drawtext=...:bold=1:fontfile=/tmp/MyFont.ttf
Suggested Fix
- Replace
:fontweight=${fontWeightParam} with :bold=1 when fontWeightParam === "bold", and omit it entirely for normal weight.
- Remove the block that appends
fontfile='${safeFontName}' for system fonts. System fonts do not require a fontfile path; use the font= option for the font family name instead.
- Keep the existing
fontFileParam path appended only for custom uploaded fonts.
// Before
let filter = `drawtext=...:fontweight=${fontWeightParam}`;
if (overlay.fontFamily) {
const safeFontName = overlay.fontFamily.replace(/[^a-zA-Z0-9-]/g, "");
filter += `:fontfile='${safeFontName}'`; // ❌ name, not a path
}
if (fontFileParam) filter += `:${fontFileParam}`; // ❌ duplicate fontfile key
// After
if (fontWeightParam === "bold") filter += `:bold=1`;
if (overlay.fontFamily && !fontFileParam) {
filter += `:font='${overlay.fontFamily}'`; // ✅ system font name
}
if (fontFileParam) filter += `:${fontFileParam}`; // ✅ custom font path only
Description
The
buildTextFilterfunction insrc/lib/text-overlay.tsgenerates an invalid FFmpegdrawtextfilter string. It contains two bugs that silently break text rendering in all video exports.Bug A — invalid
fontweight=parameterfontweight=is not a valid FFmpegdrawtextoption. FFmpeg silently ignores unknown parameters, so bold text is never rendered bold in any export. The correct parameter isbold=1.Bug B —
fontfile=set to font name, not file pathFor any overlay with a
fontFamily, the filter appendsfontfile='Arial'(or whatever the sanitised name is). FFmpeg expects a filesystem path here, not a font name. This causes FFmpeg to attempt to open a file literally namedArial, which fails silently.For custom fonts,
getFFmpegFontArgthen appends the realfontfile=path immediately after, producing a duplicate key in the filter string.Affected File
src/lib/text-overlay.ts— lines 92–102Steps to Reproduce
For custom fonts, the export may fail with an FFmpeg filter error due to the duplicate
fontfile=key.Current Behaviour
Expected Behaviour
Suggested Fix
:fontweight=${fontWeightParam}with:bold=1whenfontWeightParam === "bold", and omit it entirely for normal weight.fontfile='${safeFontName}'for system fonts. System fonts do not require afontfilepath; use thefont=option for the font family name instead.fontFileParampath appended only for custom uploaded fonts.