Repository navigation
fix(ffmpeg): escape filter and concat paths for FFmpeg's parsers - #43
Merged
Merged
Conversation
fix(ffmpeg): preserve paths through filter and concat parsers
Builds on #40. A filter option value is read twice: the filtergraph parser strips one layer of quoting, then the option parser splits on `:` and strips another. `quoteFilterArg` now escapes for the option parser first and quotes that for the graph parser, so Windows drive colons, apostrophes and `[],;` survive, and a value can no longer close its quote and add a filter. It also escapes edge whitespace, which the option parser otherwise trims (a file name ending in a space was not found). Concat-list paths get their own single-layer `quoteConcatPath`; a path with a line break or NUL throws `ConcatPathError` naming it. Tests read escaped output back through a port of FFmpeg's `av_get_token` instead of comparing strings, and CI-only tests run the cases through the real FFmpeg binary. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Linux ffmpeg-static binary in CI has no drawtext filter, so every drawtext case failed with "No such filter". The same paths now also go through `movie`, which every FFmpeg build has and which reads its path through the same two parse steps; the drawtext cases run only where the binary has drawtext. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Since FFmpeg 6.1, drawtext needs libharfbuzz as well as libfreetype, and the Linux FFmpeg 7.0.2 build that ffmpeg-static 5.3.0 installs has no harfbuzz. add_text, add_captions, add_title_card and timeline text clips died there with FFmpeg's raw "No such filter: 'drawtext'". List the resolved FFmpeg's filters once per process and throw MissingFilterError before any text render, naming the binary and how to point MAKEMYCLIP_FFMPEG_PATH at a build that has drawtext. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hoice Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix(ffmpeg): fail fast when ffmpeg lacks the drawtext filter
|
🎉 This PR is included in version 0.3.1 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Fixes how file paths and other values are escaped inside FFmpeg filtergraphs and concat lists. This builds on #40, by @eliasruntime, which is merged into this branch. Thanks for finding the Windows drive-colon bug and the concat quoting split.
The bug. FFmpeg reads a filter option value twice, and each read (
av_get_token) strips one layer of quoting:[],;.:.The old
quoteFilterArghandled only one layer, so:C:\…) split at the drive colon, andadd_textfailed with "Both text and text file provided";x',drawtext=…could close its quote and add a filter.Concat lists reused the same quoting even though the concat demuxer reads its list once, so apostrophes and backslashes in clip paths broke.
The fix (
src/ffmpeg/escape.ts):quoteFilterArgescapes\ ' :for the option parser, then single-quotes the result for the graph parser.quoteConcatPathdoes single-layer quoting for concat lists. A path with a line break or NUL throwsConcatPathErrornaming the path.quoteFilterArgis exported, and its output changes for values containing:,'or edge whitespace. Plain values stay readable ('/tmp/x.txt'), so existing assertions likefontcolor='white'are unchanged.Tests:
tests/ffmpeg-parse.tsportsav_get_token, the graph-then-option parse, and the concat-line parse.quoteFilterArgitself.tests/integration/filter-escape.test.tsruns awkward file names through the real FFmpeg binary. It's CI-only (skips unlessCI=true), like fix(ffmpeg): preserve paths through filter and concat parsers #40's version.moviefilter, which every FFmpeg build has and which reads its path through the same two parse steps.drawtext, but only where the binary has it. The Linuxffmpeg-staticbinary in CI has no libharfbuzz, which drawtext needs since FFmpeg 6.1, so it has nodrawtext.MissingFilterErrorand its fix (MAKEMYCLIP_FFMPEG_PATH) instead of FFmpeg'sNo such filter. Swapping in a Linux build with drawtext was decided against for now; seedocs/backlog/drawtext-on-linux.md.tests/integration/again.Release
Merging this cuts v0.3.1: the
fix(ffmpeg)commits trigger a patch release. It also ships #44's drawtext check, plus the dependency bump (#42) and the docs refresh (#41), which merged without releasing. This is the first real npm publish through the bumped release chain (setup-node v7, pnpm 12, semantic-release 25), so watch that run.Checks
Re-run after #44 merged, on tip
fc79352(same tree as #44's last commit50d970f), Node 24.15.0 and pnpm 12.16.1:pnpm lint: 0 errors, 7 warnings.pnpm type-checkandpnpm build: ok.CI=true pnpm teston macOS (FFmpeg 6.0): 587 passed, 1 skipped (the no-drawtext case).npm pack --dry-run: 11 files (LICENSE, README.md, SKILL.md, package.json and 7 indist/), the same count as 0.3.0.fix(ffmpeg)and nofeatorBREAKING CHANGE, so semantic-release cuts 0.3.1.main(6fe8d53) loaded every plugin and stopped at "no relevant changes". Its runner has Node 24.22.1 and npm 11.19.1; trusted publishing needs npm 11.5.1 or later, and@semantic-release/changelog7 needs Node 24.15 or later. Prepare and publish haven't run since the bumps.mainbefore fix(ffmpeg): fail fast when ffmpeg lacks the drawtext filter #44 (below), and fix(ffmpeg): fail fast when ffmpeg lacks the drawtext filter #44's diff against this branch. Neither review had findings.Run on
e916515, before #44 merged, with Node 24.15.0 and pnpm 12.16.1:pnpm lint: 0 errors, 7 warnings (the same 7 asmain)pnpm type-check: okpnpm build: okpnpm testpasses 571, and skips 6, the CI-only integration tests.CI=true vitest run tests/integrationpasses 11/11:movieanddrawtexteach read 5 names:plain,O'Brien, [notes]; v1,drive:path, one ending in a space, andback\slash'quote;O'Brien, [clip]; take 2.mp4.moviecase fails on both the apostrophe name and the colon name, so the CI test catches the bug even wheredrawtextis missing.main: 2/8 round-trip (fails on quotes, colons, the Windows path, the injection value and edge whitespace)codex review --base origin/main, gpt-6.1-sol): no actionable regressions, no findings to fix or rebut.src/tools/concat.tskeeps its two-line change.