feat(media): add a video file layer that decodes into the scene
TASK 21's picker slice: the decoder, manager, pacing and loop mechanism were
already shipped but nothing ever acquired a session, so a media Source rendered
nothing. Adds "Video File" to the (+) menu (video-filtered OpenFileDialog),
one decode session per distinct path with a HasSession guard, release when the
last scene reference goes, and a post-load reconcile. Loop is a manager-level
per-path answer ("any live reference loops") applied before StartAsync and
updated live via SetLooping. Properties panel shows the file with Change… and
Loop. Volume stays unwired: media audio rides the desktop loopback, TRAX-style.
Reference: OBS's media source (file → decode → composite into the scene) is the
established answer for this feature; the lifecycle shape mirrors this repo's
WebView2/ScreenCapture registration rather than inventing a new one.
Test: ytLive.Tests/MediaSourceAcquisitionTests.cs — add starts one decoder and
frames reach the layer, loop flip reaches the decoder, remove stops it.
Docs: task-21 closed, TASKS row + Day-4 row + stale 3·17 row corrected,
frame-pipeline acquisition note, HANDOFF rewritten. verify.sh green.
This commit is contained in:
@@ -70,6 +70,8 @@
|
||||
IsEnabled="{Binding CanAddWebcam}"
|
||||
ToolTip="{Binding WebcamAddToolTip}"/>
|
||||
<MenuItem Header="Image" Command="{Binding AddImageCommand}"/>
|
||||
<MenuItem Header="Video File" Command="{Binding AddMediaCommand}"
|
||||
ToolTip="Play a video file in the scene (mp4, mov, avi, mkv, webm)"/>
|
||||
<MenuItem Header="Text" Command="{Binding AddSourceCommand}" CommandParameter="{x:Static models:SourceType.TextOverlay}"/>
|
||||
<MenuItem Header="Countdown" Command="{Binding AddSourceCommand}" CommandParameter="{x:Static models:SourceType.Countdown}"
|
||||
Visibility="{Binding IsCountdownAvailable, Converter={StaticResource BoolToVis}}"
|
||||
@@ -725,6 +727,29 @@
|
||||
</DockPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Media (video file) config — TASK 21 -->
|
||||
<StackPanel Visibility="{Binding SelectedElement.IsMediaSource, Converter={StaticResource BoolToVis}}" Margin="0,0,0,8">
|
||||
<TextBlock Text="Video File" Style="{StaticResource PropertyHeader}"/>
|
||||
<Grid Margin="10,0,0,2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" Text="{Binding SelectedElement.MediaFileDisplay}"
|
||||
Style="{StaticResource PropertyFieldLabel}"
|
||||
TextTrimming="CharacterEllipsis" VerticalAlignment="Center"
|
||||
ToolTip="{Binding SelectedElement.MediaPath}"/>
|
||||
<Button Grid.Column="1" Content="Change…" Command="{Binding ChangeMediaFileCommand}"
|
||||
CommandParameter="{Binding SelectedElement}" Style="{StaticResource PropertyButton}"
|
||||
Margin="4,0,0,0" Padding="8,2" FontSize="11"/>
|
||||
</Grid>
|
||||
<CheckBox Style="{StaticResource PropertyPillCheck}" Margin="10,4,0,4"
|
||||
Content="Loop" IsChecked="{Binding SelectedElement.MediaIsLooping, Mode=TwoWay}"
|
||||
ToolTip="Restart from the beginning at the end of the file — for starting-soon and BRB loops"/>
|
||||
<TextBlock Text="Audio plays through your desktop audio, like TRAX."
|
||||
Style="{StaticResource PropertyHint}"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Chat box config -->
|
||||
<StackPanel Visibility="{Binding SelectedElement.IsChatBox, Converter={StaticResource BoolToVis}}" Margin="0,0,0,8">
|
||||
<TextBlock Text="Chat Overlay" Style="{StaticResource PropertyHeader}"/>
|
||||
|
||||
Reference in New Issue
Block a user