Add YouTube Shorts tab (C# port of amigadb-short.sh)
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>
This commit is contained in:
+140
-4
@@ -9,13 +9,19 @@
|
||||
|
||||
<Grid x:Name="RootGrid" Padding="20" RowSpacing="16" Background="{ThemeResource PageBrush}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Grid.Row="0" ColumnSpacing="16">
|
||||
<StackPanel Grid.Row="0" Orientation="Horizontal" Spacing="8">
|
||||
<Button x:Name="VideoTabButton" Content="Video" Click="VideoTab_Click" Style="{StaticResource PrimaryButtonStyle}" MinWidth="120" />
|
||||
<Button x:Name="ShortsTabButton" Content="Shorts" Click="ShortsTab_Click" MinWidth="120" />
|
||||
</StackPanel>
|
||||
|
||||
<Grid Grid.Row="1" ColumnSpacing="16" x:Name="VideoContentPanel">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
@@ -72,7 +78,137 @@
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<Border Grid.Row="1" Padding="18" Style="{StaticResource CardBorderStyle}">
|
||||
<Grid Grid.Row="1" RowSpacing="16" x:Name="ShortsContentPanel" Visibility="Collapsed">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid ColumnSpacing="16">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<Border Grid.Column="0" Padding="18" Style="{StaticResource CardBorderStyle}">
|
||||
<StackPanel Spacing="12">
|
||||
<TextBlock Text="Short source and clip" Style="{StaticResource SectionTitleStyle}" />
|
||||
<Grid ColumnSpacing="10" RowSpacing="10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBox x:Name="ShortInputBox" Grid.Row="0" MinHeight="40" ToolTipService.ToolTip="Source video for this Short" />
|
||||
<Button Grid.Row="0" Grid.Column="1" Content="Browse..." Click="BrowseShortInput_Click" VerticalAlignment="Stretch" MinWidth="120" />
|
||||
<TextBox x:Name="ShortOutputBox" Grid.Row="1" MinHeight="40" ToolTipService.ToolTip="Output .mp4 path" />
|
||||
<Button Grid.Row="1" Grid.Column="1" Content="Browse..." Click="BrowseShortOutput_Click" VerticalAlignment="Stretch" MinWidth="120" />
|
||||
</Grid>
|
||||
<Grid ColumnSpacing="10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock Text="Start (HH:MM:SS)" Style="{StaticResource FieldLabelStyle}" />
|
||||
<TextBox x:Name="ShortStartBox" Text="00:00:00" />
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="1">
|
||||
<TextBlock Text="Duration (seconds)" Style="{StaticResource FieldLabelStyle}" />
|
||||
<TextBox x:Name="ShortDurationBox" Text="30" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Button x:Name="PreviewShortSourceButton" Content="Preview source" Click="PreviewShortSource_Click" HorizontalAlignment="Left" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<Border Grid.Column="1" Padding="18" Style="{StaticResource CardBorderStyle}">
|
||||
<StackPanel Spacing="12">
|
||||
<TextBlock Text="Title card" Style="{StaticResource SectionTitleStyle}" />
|
||||
<TextBox x:Name="ShortTitleBox" Header="Title" ToolTipService.ToolTip="Production title, e.g. Ami-Back V1.04A" />
|
||||
<Grid ColumnSpacing="10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox x:Name="ShortGroupBox" Grid.Column="0" Header="Group" />
|
||||
<TextBox x:Name="ShortYearBox" Grid.Column="1" Header="Year" />
|
||||
<TextBox x:Name="ShortTypeBox" Grid.Column="2" Header="Type" />
|
||||
</Grid>
|
||||
<TextBox x:Name="ShortHookBox" Header="Opening hook" />
|
||||
<TextBox x:Name="ShortWebsiteBox" Header="Closing website text" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<Border Grid.Row="1" Padding="18" Style="{StaticResource CardBorderStyle}">
|
||||
<StackPanel Spacing="12">
|
||||
<TextBlock Text="Style and encoding" Style="{StaticResource SectionTitleStyle}" />
|
||||
<Grid ColumnSpacing="10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ComboBox x:Name="ShortStyleBox" Grid.Column="0" Header="Style" SelectionChanged="ShortStyleBox_SelectionChanged" HorizontalAlignment="Stretch">
|
||||
<ComboBoxItem Content="Brand (title card image)" Tag="Brand" />
|
||||
<ComboBoxItem Content="Pixel" Tag="Pixel" />
|
||||
<ComboBoxItem Content="Mirror" Tag="Mirror" />
|
||||
<ComboBoxItem Content="Crop" Tag="Crop" />
|
||||
<ComboBoxItem Content="Workbench" Tag="Workbench" />
|
||||
<ComboBoxItem Content="Blur" Tag="Blur" />
|
||||
<ComboBoxItem Content="CRT" Tag="Crt" />
|
||||
<ComboBoxItem Content="Copper bars" Tag="Copper" />
|
||||
<ComboBoxItem Content="Stars" Tag="Stars" />
|
||||
<ComboBoxItem Content="Grid" Tag="Grid" />
|
||||
<ComboBoxItem Content="Tiles" Tag="Tiles" />
|
||||
<ComboBoxItem Content="Scanlines" Tag="Scan" />
|
||||
<ComboBoxItem Content="Starfield" Tag="Starfield" />
|
||||
<ComboBoxItem Content="Plasma" Tag="Plasma" />
|
||||
<ComboBoxItem Content="Rasterbars" Tag="Rasterbars" />
|
||||
<ComboBoxItem Content="VHS" Tag="Vhs" />
|
||||
<ComboBoxItem Content="Monitor" Tag="Monitor" />
|
||||
<ComboBoxItem Content="Split" Tag="Split" />
|
||||
<ComboBoxItem Content="Spectrum (needs audio)" Tag="Spectrum" />
|
||||
</ComboBox>
|
||||
<ComboBox x:Name="ShortPresetBox" Grid.Column="1" Header="x264 preset" HorizontalAlignment="Stretch">
|
||||
<ComboBoxItem Content="ultrafast" Tag="ultrafast" />
|
||||
<ComboBoxItem Content="superfast" Tag="superfast" />
|
||||
<ComboBoxItem Content="veryfast" Tag="veryfast" />
|
||||
<ComboBoxItem Content="faster" Tag="faster" />
|
||||
<ComboBoxItem Content="fast" Tag="fast" />
|
||||
<ComboBoxItem Content="medium" Tag="medium" />
|
||||
<ComboBoxItem Content="slow" Tag="slow" />
|
||||
<ComboBoxItem Content="slower" Tag="slower" />
|
||||
<ComboBoxItem Content="veryslow" Tag="veryslow" />
|
||||
</ComboBox>
|
||||
</Grid>
|
||||
<Grid x:Name="ShortBackgroundRow" ColumnSpacing="10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox x:Name="ShortBackgroundBox" Grid.Column="0" Header="Background image (brand style)" />
|
||||
<Button Grid.Column="1" Content="Browse..." Click="BrowseShortBackground_Click" VerticalAlignment="Bottom" MinWidth="120" />
|
||||
</Grid>
|
||||
<Grid ColumnSpacing="10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="120" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox x:Name="ShortFontBox" Grid.Column="0" Header="Bold font file (.ttf/.otf)" />
|
||||
<Button Grid.Column="1" Content="Browse..." Click="BrowseShortFont_Click" VerticalAlignment="Bottom" MinWidth="120" />
|
||||
<TextBox x:Name="ShortCrfBox" Grid.Column="2" Header="CRF" />
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<Border Grid.Row="2" Padding="18" Style="{StaticResource CardBorderStyle}">
|
||||
<StackPanel Spacing="12">
|
||||
<TextBlock Text="Render progress" Style="{StaticResource SectionTitleStyle}" />
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
@@ -84,7 +220,7 @@
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<Border Grid.Row="2" Padding="18" Style="{StaticResource CardBorderStyle}">
|
||||
<Border Grid.Row="3" Padding="18" Style="{StaticResource CardBorderStyle}">
|
||||
<StackPanel Spacing="12">
|
||||
<TextBlock Text="FFmpeg log" Style="{StaticResource SectionTitleStyle}" />
|
||||
<TextBox x:Name="LogBox"
|
||||
@@ -100,7 +236,7 @@
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<Grid Grid.Row="3">
|
||||
<Grid Grid.Row="4">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
|
||||
Reference in New Issue
Block a user