Skip to content

[BUG] buildTextFilter uses invalid FFmpeg fontweight parameter and sets fontfile to font name instead of path — bold text and custom fonts never render correctly #1414

@abhinav-atul

Description

@abhinav-atul

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

  1. Upload any video and add a text overlay.
  2. Set the font weight to Bold.
  3. Export the video.
  4. 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

Metadata

Metadata

Assignees

Labels

bugSomething isn't working correctlytype:bugBug fix

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions