58e11ba4e3
New "Video | Shorts" tab strip on the main page. The existing Video tab and its render pipeline are unchanged; Shorts is a new, independent workflow sharing the same render-progress/log/output controls. - Services/ShortsPipeline.cs: C# port of amigadb-short.sh rather than shelling out to bash — end users on plain Windows don't have bash/WSL, and shipping this as a native part of the app keeps distribution self-contained. All 19 visual style filtergraphs (brand, pixel, mirror, crop, workbench, blur, crt, copper, stars, grid, tiles, scan, starfield, plasma, rasterbars, vhs, monitor, split, spectrum) are copied verbatim from the bash heredocs. Per explicit decision, kept parity with the script's actual behavior where the brand-style HOOK_BOX_Y/INFO_BOX_Y/font-size variables are computed but never actually used in the final filter (dead code in the original) rather than "fixing" it and changing rendered output. Reuses ToolExtractor/MediaProbe/ProcessRunner exactly as RenderPipeline does, so FFmpeg resolution and NVENC fallback behave identically. - Models/ShortSettings.cs: job parameters + ShortStyle enum. - AppSettings gains sticky Shorts defaults (style, hook, website, font, background image, CRF, preset) alongside the existing Video defaults. - MainPage: Video/Shorts tab buttons toggle two content panels; the background-image field auto-hides for non-brand styles; font field defaults to the first bold system font found (Segoe UI Bold, Segoe UI Semibold, Arial Bold, Calibri Bold); blank output path is auto-derived from the input filename and style, matching the script's default. - 13 new unit tests (escaping order, meta-line joining, validation, every style producing a non-empty filter, the drawtext trailer's timing gates). Full run is 72/72 passing. - Fixed a bug caught during manual testing: MainPage.Resources["PrimaryButtonStyle"] looked in the Page's own (empty) resource dictionary instead of Application.Current.Resources, throwing on every tab switch. Verified end-to-end: rendered a real Short from an existing video through the actual running app (not just unit tests) and inspected extracted frames — hook/title/meta/website text overlays appear and disappear at the correct timestamps with correct styling. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
200 lines
8.0 KiB
Markdown
200 lines
8.0 KiB
Markdown
# AmiReel
|
||
|
||
AmiReel is a Windows desktop app for turning Amiga (or any) screen recordings into:
|
||
|
||
- a 4K 50 FPS final video,
|
||
- PNG/JPG thumbnails,
|
||
- an animated WebP preview,
|
||
- a vertical (1080×1920, 50 FPS) YouTube Short with a styled title card.
|
||
|
||
Built with **WinUI 3** on the Windows App SDK, driving FFmpeg under the hood. The app has two
|
||
tabs — **Video** (the full-length render pipeline above) and **Shorts** (see below) — sharing
|
||
the same render progress, log, and output controls.
|
||
|
||
## Features
|
||
|
||
### Video tab
|
||
- Multiple ordered video inputs — `.avi`, `.mp4`, `.m4v`, `.mov`, `.mkv`, `.webm`, `.wmv`, `.flv`, `.mpg`, `.mpeg`, `.ts`, `.3gp`
|
||
- Drag-and-drop or file-picker source selection
|
||
- 3840×2160 output at 50 FPS
|
||
- Configurable trim, fade, end-card hold, and thumbnail interval
|
||
- Optional end-card image
|
||
- Optional move of source recordings into `originals/` in the output folder
|
||
|
||
### Shorts tab
|
||
- Turns one source video into a vertical YouTube Short with an opening hook, title/group/year/
|
||
type card, and closing website call-to-action, all as timed text overlays
|
||
- 19 visual styles ported from `amigadb-short.sh` — `brand` (title card image), `pixel`,
|
||
`mirror`, `crop`, `workbench`, `blur`, `crt`, `copper`, `stars`, `grid`, `tiles`, `scan`,
|
||
`starfield`, `plasma`, `rasterbars`, `vhs`, `monitor`, `split`, `spectrum` (needs audio)
|
||
— see [`Services/ShortsPipeline.cs`](Services/ShortsPipeline.cs) for the exact FFmpeg filtergraphs
|
||
- Configurable clip start/duration, CRF, and x264 preset
|
||
- Style, font, background image, hook, and website text are sticky across launches
|
||
|
||
### Shared
|
||
- NVIDIA NVENC with automatic CPU `libx264` fallback
|
||
- Live render progress with frame counters and FFmpeg log output
|
||
- Source and final-render preview (built-in or a custom player)
|
||
- Dark and light themes
|
||
- Optional custom `ffmpeg.exe` / `ffprobe.exe` paths, with automatic detection from `PATH`
|
||
- Self-contained single-file publish for easy distribution
|
||
|
||
## Project Layout
|
||
|
||
```
|
||
AmiReel.csproj Project file
|
||
AmiReel.slnx Solution file
|
||
App.xaml(.cs) Application entry point
|
||
MainWindow.xaml(.cs) Window shell: custom title bar, theming, exit confirmation
|
||
MainPage.xaml(.cs) Main UI: source list, settings, render controls
|
||
DialogHelper.cs Shared ContentDialog styling (Settings, exit, error dialogs)
|
||
Package.appxmanifest MSIX packaging identity and tile/icon declarations
|
||
app.manifest Win32 manifest (DPI awareness, OS compatibility)
|
||
Assets/ Packaged app icons and tiles (all required sizes)
|
||
branding/ Source artwork the Assets/ tiles are generated from
|
||
Models/
|
||
AppSettings.cs Persisted user settings (Video + Shorts defaults)
|
||
RenderSettings.cs Video render job parameters
|
||
ShortSettings.cs Shorts render job parameters, ShortStyle enum
|
||
SupportedVideoFormats.cs Accepted input file extensions
|
||
Services/
|
||
RenderPipeline.cs Video render workflow (FFmpeg orchestration)
|
||
ShortsPipeline.cs Shorts render workflow; the 19 style filtergraphs live here
|
||
ProcessRunner.cs FFmpeg process execution and progress parsing
|
||
FfmpegProgressParser.cs Parses time=/frame=/fps=/speed= from FFmpeg output lines
|
||
FfmpegOutputFilter.cs Shared FFmpeg banner/boilerplate line filtering
|
||
ToolExtractor.cs FFmpeg resolution, extraction, and fallback logic
|
||
MediaProbe.cs Duration/audio-stream probing via ffprobe
|
||
FfmpegLibraryProbe.cs NVENC capability probing
|
||
AppSettingsStore.cs Settings load/save (JSON in %LOCALAPPDATA%)
|
||
UserFacingErrors.cs Exception-to-message translation
|
||
Properties/
|
||
AssemblyInfo.cs InternalsVisibleTo AmiReel.Tests
|
||
launchSettings.json
|
||
PublishProfiles/ win-x64/x86/arm64 publish profiles
|
||
AmiReel.Tests/ Unit tests (MSTest), mirrors Models/ and Services/
|
||
amigadb-short.sh Original bash/FFmpeg script that ShortsPipeline.cs is a C# port of
|
||
ThirdParty/ Embedded ffmpeg.exe / ffprobe.exe (not checked in, see below)
|
||
publish-win-x64.ps1 Publish script
|
||
```
|
||
|
||
## Requirements
|
||
|
||
For development:
|
||
|
||
- Windows 10 or Windows 11
|
||
- .NET 10 SDK with WinUI 3 / Windows App SDK workload
|
||
- Windows x64 FFmpeg binaries in `ThirdParty/`:
|
||
- `ThirdParty\ffmpeg.exe`
|
||
- `ThirdParty\ffprobe.exe`
|
||
|
||
For end users:
|
||
|
||
- Windows 10 or Windows 11 x64
|
||
- The published `AmiReel.exe` — FFmpeg is not required separately if you distribute AmiReel with the embedded `ThirdParty` binaries
|
||
|
||
## Run in Development
|
||
|
||
```powershell
|
||
dotnet build .\AmiReel.csproj
|
||
dotnet run --project .\AmiReel.csproj
|
||
```
|
||
|
||
## Run Tests
|
||
|
||
Unit tests live in `AmiReel.Tests/` (MSTest), covering the pure logic in `Models/` and
|
||
`Services/` — settings normalization, supported-format detection, FFmpeg output parsing/
|
||
filtering, render-settings validation, moving source files into `originals/`, and the Shorts
|
||
filtergraph/escaping/validation logic.
|
||
|
||
```powershell
|
||
dotnet test .\AmiReel.Tests\AmiReel.Tests.csproj
|
||
```
|
||
|
||
UI code-behind (`App`, `MainWindow`, `MainPage`) and anything that spawns an actual FFmpeg
|
||
process are intentionally left to manual/integration testing rather than unit tests.
|
||
|
||
## Publish
|
||
|
||
```powershell
|
||
.\publish-win-x64.ps1
|
||
```
|
||
|
||
This publishes a self-contained, single-file `win-x64` executable. At the end of the script
|
||
you'll see the release folder and final executable path, for example:
|
||
|
||
```text
|
||
bin\Release\net10.0-windows10.0.26100.0\win-x64\publish\AmiReel.exe
|
||
```
|
||
|
||
## Installation
|
||
|
||
### For developers
|
||
|
||
1. Clone the repository.
|
||
2. Add `ffmpeg.exe` and `ffprobe.exe` to `ThirdParty\`.
|
||
3. Restore and build:
|
||
|
||
```powershell
|
||
dotnet build .\AmiReel.slnx
|
||
```
|
||
|
||
### For end users
|
||
|
||
1. Copy the published `AmiReel.exe` to any location, for example `C:\Apps\AmiReel\`.
|
||
2. Double-click `AmiReel.exe`.
|
||
3. If FFmpeg is embedded in the build, no extra setup is required.
|
||
4. To use your own FFmpeg build instead, open **Settings** and set:
|
||
- `ffmpeg.exe` path
|
||
- `ffprobe.exe` path
|
||
|
||
### Optional desktop shortcut
|
||
|
||
Right-click `AmiReel.exe` → **Send to** → **Desktop (create shortcut)**.
|
||
|
||
## FFmpeg Behavior
|
||
|
||
AmiReel resolves FFmpeg in this order:
|
||
|
||
1. Custom paths from Settings
|
||
2. `ffmpeg.exe` / `ffprobe.exe` found on the system `PATH`
|
||
3. Embedded `ThirdParty` binaries (extracted to `%LOCALAPPDATA%\AmiReel\tools` on first use)
|
||
|
||
If NVENC cannot be initialized, AmiReel automatically falls back to CPU `libx264`.
|
||
|
||
## Settings Location
|
||
|
||
User settings are stored in:
|
||
|
||
```text
|
||
%LOCALAPPDATA%\AmiReel\settings.json
|
||
```
|
||
|
||
This includes: output folder, end-card path, FFmpeg/preview-player paths, theme, encoder
|
||
selection, timing settings, whether source videos are moved into `originals/` after a
|
||
successful render, and the Shorts tab's sticky defaults (style, font, background image, CRF,
|
||
preset, hook, and website text).
|
||
|
||
## Notes for Distribution
|
||
|
||
- If you distribute FFmpeg binaries with AmiReel, you are responsible for complying with the
|
||
license terms of the FFmpeg build you use. Keep any required notices, source offer, or
|
||
attribution required by that distribution.
|
||
- Windows Explorer may cache executable icons. If a freshly published build still shows an old
|
||
icon, rename the file or refresh the icon cache before assuming the embed failed.
|
||
- `Package.appxmanifest` currently has a placeholder `Identity` (a random GUID `Name` and
|
||
`Publisher="CN=AppPublisher"`). That's fine for local unpackaged builds, but before signing
|
||
an MSIX for real distribution, replace them with a real publisher identity and generate a
|
||
matching signing certificate (`winapp cert generate`, see `AGENTS.md`).
|
||
|
||
## Troubleshooting
|
||
|
||
**App falls back to CPU instead of NVENC** — FFmpeg could not initialize `h264_nvenc`. AmiReel
|
||
continues automatically with CPU encoding.
|
||
|
||
**FFmpeg tool error** — If the embedded FFmpeg is missing or broken, AmiReel tries configured
|
||
tool paths, then FFmpeg from `PATH`. Set the paths manually in **Settings** if needed.
|
||
|
||
**Render failed popup** — Shows a short human-readable summary. Full technical details remain
|
||
available in the **FFmpeg log** panel.
|