A small Windows Win32 GUI app that watches a queue folder for Topaz job JSON files and runs Topaz Video AI’s bundled ffmpeg.exe (with tvai_* filters) to upscale/repair videos automatically.
This project is intended to pair with a separate “MediaExplorer” tool that drops jobs into the queue folder.
Not affiliated with Topaz Labs. Requires a working Topaz Video AI installation.
- Scans
TopazUpscaleQueuefor*.jsonfiles - For each JSON, reads the required job fields:
input_file(string) – file name of the input video in the same queue folderprofile(string) – controls filter chain (repair/denoise/stabilize/etc.)target_w/target_h(ints) – output dimensionstarget(string) – used for output naming suffix (_4kor_8k)
- Runs Topaz's
ffmpeg.exewith a generated-filter_complexthat uses Topaztvai_*filters - Streams ffmpeg stdout/stderr into a per-job tab
- Writes output to a temp file in
TopazWorkingDir, then on success:- moves the output to
TopazUpscaleCompleted - deletes the input video + the
.json - closes the job tab
- moves the output to
The UI shows:
- Overview tab: queue/completed/working paths, pending/running counts, last scan time
- One tab per running job: live ffmpeg output
- Jobs are started up to
maxConcurrent
From your directory listing, the repo root is:
MediaServer.sln
MediaServer.cpp
MediaServer.vcxproj
MediaServer.vcxproj.filters
x64\Release\MediaServer.exe
x64\Release\mediaserver.ini
Visual Studio will also create build artifacts like .vs\, x64\, and MediaServer\x64\... which you typically do not commit.
- Windows 10/11
- Visual Studio 2022 (C++17), x64 build
- Topaz Video AI installed
- You must point
TopazFfmpegPathto Topaz’s bundledffmpeg.exe(not system ffmpeg)
- You must point
- If you keep the default encoder settings (
hevc_nvenc), you’ll want an NVIDIA GPU with NVENC (or editencoderArgs)
- Open
MediaServer.slnin Visual Studio 2022. - Select Release | x64 (or Debug | x64).
- Build.
The EXE will land in x64\Release\MediaServer.exe by default.
- Put
mediaserver.iniin the same folder as the EXE.- Your current layout already matches this:
x64\Release\mediaserver.ini
- Your current layout already matches this:
- Launch
MediaServer.exe. - The app will scan the queue immediately, then every ~1.5 seconds.
If loggingEnabled=1, the app writes:
x64\Release\logs\mediaserver.log
(That folder is created automatically next to the EXE.)
The app reads INI keys as key=value and ignores section headers (e.g. [general] is fine).
Minimum required:
TopazUpscaleQueue = C:\topaz_queue\pending
TopazUpscaleCompleted = C:\topaz_queue\completed
TopazWorkingDir = C:\topaz_queue\work
; Must be Topaz's bundled ffmpeg.exe, not system ffmpeg
TopazFfmpegPath = C:\Program Files\Topaz Labs LLC\Topaz Video\ffmpeg.exe
; Model folders (match Topaz resource/models folder)
TVAIModelDir = C:\ProgramData\Topaz Labs LLC\Topaz Video\models
TVAIModelDataDir = C:\ProgramData\Topaz Labs LLC\Topaz Video\models
maxConcurrent = 1
loggingEnabled = 1device(int)
Passed to Topaz filters. Default is-2(auto).vram(double),instances(int)
Also passed to Topaz filters.encoderArgs(string)
Appends these ffmpeg args after-filter_complex. Defaults use NVENC video (H.264 for 4K, AV1 for 8K) and AAC audio for MP4 compatibility.- Completion notifications:
enable_email(1/0, default0)Notification_Address(recipient)Notification_from_address(sender/from)Notification_Passwordenvironment variable (SMTP/app password)Notification_Smtp_Server(defaultsmtp.mail.yahoo.com)Notification_Smtp_Port(default587)Notification_Use_SSL(1/0, default1)Notification_Smtp_Username(optional; defaults to from-address)Notification_Timeout_ms(optional; default30000)enable_SMS(1/0, default0)SMS_PHONE_NUMBER(destination phone number)TEXTBELT_API_KEYenvironment variable (required when SMS is enabled)TEXTBELT_BASE_URLenvironment variable (optional; defaults tohttp://textbelt.comto match thesendtext.cppsample)- Define each notification key only once in the INI. If a key is repeated, the last value wins and the app logs a startup warning.
- Model selection keys:
modelGeneral(defaultprob-4)modelRepair(defaultiris-3)modelDenoise(defaultnyx-2)modelDeblur(defaultthm-2)modelDeinterlace(defaultiris-3)modelStabCpe(defaultcpe-1)modelStabRef(defaultref-2)
Each job is a *.json file in the queue directory.
Required fields:
input_file(string)target(string) – used for naming (4k/8k)profile(string)target_w(int)target_h(int)
Optional fields:
grain(number)gsize(int)
Example:
{
"input_file": "myclip.mp4",
"target": "4k",
"profile": "repair",
"target_w": 3840,
"target_h": 2160,
"grain": 0.0,
"gsize": 1
}For input myclip.mp4:
target=4k→myclip_4k.mp4target=8k→myclip_8k.mp4
If the output already exists in the completed folder, it auto-adds (1), (2), etc.
profile is lowercased and mapped to filter chains:
deinterlace_repair
bwdif→tvai_upusingmodelRepairstabilize(two-pass)- pre-pass
tvai_cpewrites a motion JSON in the working folder tvai_stbuses that file, then upscale withmodelGeneral
- pre-pass
deblur
tvai_upwithmodelDeblur, then upscale withmodelGeneraldenoise
upscale withmodelDenoiserepair_2pass
denoise → repairrepair/repair_grain
upscale withmodelRepair- anything else
upscale withmodelGeneral
After Topaz filters, the app runs:
scale(lanczos) preserving aspect ratio (decrease)padto the exact target size (black)
- If a JSON is malformed, it is renamed to
*.json.bad - If the input video is missing, the job is skipped (JSON remains in the queue)
- If ffmpeg returns non-zero:
- the job tab remains open
- the JSON remains in the queue
- you can fix the cause and rerun (restart the app, or requeue)
At minimum, ignore Visual Studio and build artifacts:
.vs/
x64/
MediaServer/x64/
*.ipch
*.obj
*.pdb
*.iobj
*.ipdb
*.tlog
*.log
logs/If you don’t want to commit machine-specific paths:
mediaserver.ini(Instead, commit mediaserver.ini.example.)
Add a LICENSE file that matches how you want to distribute this project.