CLI tool
finnvoor/fx-upscale avatar
finnvoor/fx-upscale

fx-upscale and the case for a Metal-native video upscaler on a Mac

Metal-powered video upscaling

691 stars19 forksSwiftCC0-1.0

At a glance

What is it?
fx-upscale is a Swift command line tool that upscales a video using Metal, defaulting to a 2x increase and taking a URL and an optional width or height. Its interesting constraint is the one it documents about 4K output, where macOS playback limits force a format change.
Who is it for?
fx-upscale suits a Mac user who wants a higher resolution version of a video and would rather run one command than configure a filter graph, since the tool takes a URL and an optional dimension and does the rest. It does not suit a Linux or Windows user, because the implementation is Metal based, and it does not suit someone who needs the output to stay in h264 or hevc at high resolution, because above 4K the tool changes container and codec for you.
Can I use it commercially?
Yes. CC0-1.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 93 days ago.
What is it written in?
Mainly Swift, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One argument and two options, and a sensible 2x default

fx-upscale is a command line tool for Metal powered video upscaling, and its whole interface fits in a help screen:

code
USAGE: fx-upscale <url> [--width <width>] [--height <height>]

ARGUMENTS:
  <url>                   The video file to upscale

OPTIONS:
  -w, --width <width>     The output file width
  -h, --height <height>   The output file height
  -h, --help              Show help information.

The rules for what the two options do are stated plainly. If width and height are both given, they are used for the output dimensions. If only one of them is given, the other is inferred proportionally. And if neither is given, the video is upscaled by 2x.

That last default is the most useful design decision in the tool. Scaling by a factor rather than by a target resolution is the right choice for the common case, because a factor does not need to know the input dimensions and does not crop or distort when the source aspect ratio is unusual. A user who wants 4K from a 1080p source and a user who wants 2160p from a 720p source both get what they asked for from the same flag.

The proportional inference for the single-dimension case handles the other common case, which is fixing one dimension and keeping the aspect ratio. Combined, the two rules cover most of what someone would want without asking the tool to guess.

The primary language is Swift, and the project is built as a Swift package, with Package.swift and Package.resolved at the root alongside Sources/ and Tests/.

The 4K format change is the constraint that shapes real use

There is a note in the documentation that answers the question every upscaler has to face, and it is the most useful paragraph in the project.

When upscaling videos to more than 4K, mp4 files will be converted to mov, and h264 or hevc codecs will be re-encoded as proRes422. The reason given is that macOS struggles to play back more than 4K video in h264 and hevc, and that h264 and hevc codecs only support up to roughly 8K.

So there is a ceiling and it is a codec limit, not a performance limit. Push past it and the output format changes underneath you.

That is a real trade for a user. ProRes422 is an intermediate codec, and an intermediate codec is the right choice for editing and for files you will re-encode later, but it is a large file and it is not what a streaming service will accept. The documentation is direct about the consequence: if you have a use case for creating more than 4K h264 or hevc mp4 files, please open an issue.

So the tool makes a decision for you and asks you to complain if you wanted otherwise. For a person whose pipeline ends in a video player, that is a sensible default. For a person whose pipeline ends in a device that will only take mp4, it is a surprise waiting to happen, and the answer is to check the resolution before you start a long encode.

Three install routes, and the releases live under another name

Installation is offered three ways, and the manual route has a detail worth noticing.

Homebrew is first:

bash
brew install finnvoor/tools/fx-upscale

Then Mint:

bash
mint install finnvoor/fx-upscale

And the manual route says to download the latest release from the releases page. The link it points at is not the repository you are reading. It goes to the releases of Finnvoor/MetalFXUpscale, a different repository name from finnvoor/fx-upscale that the project itself lives in.

That is a small inconsistency, and it has a practical consequence. If you are following the manual instructions and your download page is not the one you expected, you are not doing anything wrong, and the packages under the two names are the same project. It also tells you something about the project's history, since the tool now carries a shorter name than the repository the release artefacts are published under.

The top-level tree is consistent with a Swift package rather than an application bundle: there is no Xcode project, no Info.plist and no app target, just a package manifest, a resolved dependency lock, Sources/ and Tests/. There is also a .swiftformat file, so the code is formatted with SwiftFormat, and a .github/ directory for the workflows.

The licence is CC0, which is a public domain dedication rather than an open source licence in the usual sense, and it is a fitting choice for a tool whose output is the point.

The comparison with ffmpeg upscaling is the argument for using this

The documentation includes a section titled ffmpeg upscaling versus fx-upscale with a comparison image, and the presence of that comparison is the clearest statement of intent in the project.

The ffmpeg approach is the baseline everybody knows: you reach for a scale filter in a filter graph, and you get a resampling operation that works everywhere. The problem with that baseline is quality, because conventional scaling filters do not add detail, they interpolate what is already there. A dedicated upscaler using a learned or reconstruction-based model produces edges that a bicubic filter cannot.

The comparison image is there to let you judge that difference on your own material rather than take the claim on trust, which is the right way to make it.

The other difference is integration. ffmpeg is a general tool that will do a hundred things, and the scale filter is one option among many in a filter graph you have to write. fx-upscale is one tool that does one thing, takes a URL, and produces a file. For a user who wants an upscaled file and does not want to assemble a graph, that is a real reduction in effort.

The cost of the specialisation is the same trade. You lose the ability to trim, concatenate, remux and filter in the same pass, and you gain a command that does exactly one transformation. Whether that is a good deal depends on whether the upscale is the step you were going to run anyway.

Where fx-upscale is the wrong tool

The first limit is the platform. This is a Metal based implementation, and the tool is for macOS with a Metal capable GPU. A Linux or Windows user has to look elsewhere, and there is no portable fallback path in the repository, which contains a Swift package manifest and Swift sources.

The second is the 4K behaviour again, from the other side. If your output has to remain an mp4 with an h264 or hevc stream, the tool will not give you that above 4K, and the documented path is to open an issue rather than to configure it. For a user with a fixed downstream requirement, that is a hard stop rather than an inconvenience.

The third is the size of the tool. It does one thing, and it does not compose with anything else. If your workflow needs the video trimmed first, or the audio re-encoded, or the result muxed with something else, you are running at least two tools, and the second one re-encodes what the first produced.

The fourth is maturity. The three most recent releases are all from the same day, 1.3.0, 1.3.1 and 1.3.2 on 2026-07-23, and the last push to the repository is on the same day. That looks like a release concentrated in a single afternoon rather than a project with a regular cadence, and it means the tagged version may not reflect much testing history.

There is also the app. The project points at a separate application, Unsqueeze, available on the App Store, described as an app based version of fx-upscale. If you want the upscaling without opening a terminal, that is the route, and it is a different product with its own release cycle.

Editorial conclusion

fx-upscale suits a Mac user who wants a higher resolution version of a video and would rather run one command than configure a filter graph, since the tool takes a URL and an optional dimension and does the rest. It does not suit a Linux or Windows user, because the implementation is Metal based, and it does not suit someone who needs the output to stay in h264 or hevc at high resolution, because above 4K the tool changes container and codec for you. Before you run it, check what your target resolution does to the output format, and note that the releases are published under a different repository name, that the last push was on 2026-07-23, and that the licence is CC0.

Frequently asked questions

What does fx-upscale do?

It is a Metal powered video upscaler for macOS that takes a video URL and produces a higher resolution version. If you give both width and height they are used directly, if you give one the other is inferred proportionally, and if you give neither the video is upscaled by 2x.

How do I install fx-upscale?

With brew install finnvoor/tools/fx-upscale, with mint install finnvoor/fx-upscale, or by downloading the latest release manually. The manual link points at the releases of the MetalFXUpscale repository rather than at this one, so the artefact names and the project name differ.

What happens when fx-upscale outputs more than 4K?

mp4 files are converted to mov and h264 or hevc are re-encoded as proRes422, because macOS struggles to play back more than 4K h264 and hevc and those codecs only support up to roughly 8K. The documentation asks you to open an issue if you need higher resolution h264 or hevc mp4 output.

How does fx-upscale compare with upscaling in ffmpeg?

The project includes a side by side comparison of ffmpeg upscaling against fx-upscale so you can judge the difference on your own footage. The trade is that ffmpeg composes into a filter graph with trimming and muxing, while fx-upscale does one transformation and takes a URL.

Is there an app version of fx-upscale?

Yes. The project points at Unsqueeze on the App Store as an app based version of fx-upscale, which is the route if you would rather not use the command line. The tool itself is released under CC0, and the repository holds Swift sources, a Swift package manifest and a Tests directory.

Official sources

  1. finnvoor/fx-upscale on GitHub
  2. Issues
  3. License: CC0-1.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/finnvoor-fx-upscale.svg)](https://hysenlabs.com/projects/finnvoor-fx-upscale)

Was this useful?