Skip to content

Commit b986854

Browse files
committed
Add luma mask option
1 parent 4bc54e9 commit b986854

File tree

11 files changed

+104
-6
lines changed

11 files changed

+104
-6
lines changed

TwitchDownloaderCLI/Options.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ class Options
5151
public bool FfzEmotes { get; set; }
5252
[Option("outline", Default = false, HelpText = "Enable outline in chat render.")]
5353
public bool Outline { get; set; }
54+
[Option("generate-mask", Default = false, HelpText = "Generates a mask file in addition to the regular chat file.")]
55+
public bool GenerateMask { get; set; }
5456
[Option("outline-size", Default = 4, HelpText = "Size of outline in chat render.")]
5557
public double OutlineSize { get; set; }
5658
[Option('f', "font", Default = "ariel", HelpText = "Font to use in chat render.")]

TwitchDownloaderCLI/Program.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ private static void RenderChat(Options inputOptions)
197197
renderOptions.UpdateRate = inputOptions.UpdateRate;
198198
renderOptions.PaddingLeft = inputOptions.PaddingLeft;
199199
renderOptions.Framerate = inputOptions.Framerate;
200+
renderOptions.GenerateMask = inputOptions.GenerateMask;
200201
renderOptions.InputArgs = inputOptions.InputArgs;
201202
renderOptions.OutputArgs = inputOptions.OutputArgs;
202203
renderOptions.FfmpegPath = inputOptions.FfmpegPath == null || inputOptions.FfmpegPath == "" ? ffmpegPath : inputOptions.FfmpegPath;

TwitchDownloaderCLI/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Extra example, if I wanted only seconds 3-6 in a 10 second stream I would do -b
3838
**-t/-\-threads**
3939
(Default: 10) Number of download threads.
4040

41-
**-o/-\-oauth**
41+
**-\-oauth**
4242
OAuth to be passed when downloading a VOD. Used when downloading sub only VODs.
4343
## Arguments for mode ClipDownload
4444
**-u/-\-id**
@@ -109,6 +109,9 @@ Path to JSON chat file input.
109109
**-\-timestamp**
110110
Enables timestamps to left of messages, similar to VOD chat on Twitch.
111111

112+
**-\-generate-mask**
113+
Generates a mask file in addition to the regular chat file.
114+
112115
**-\-framerate**
113116
(Default: 30) Framerate of chat render output.
114117

TwitchDownloaderCore/ChatRenderer.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,36 @@ private void RenderVideo(ChatRenderOptions renderOptions, Queue<TwitchComment> f
221221
Stopwatch stopwatch = new Stopwatch();
222222
stopwatch.Start();
223223

224+
Process maskProcess = null;
225+
BinaryWriter maskStream = null;
226+
if (renderOptions.GenerateMask)
227+
{
228+
string outputArgsMask = renderOptions.OutputArgs.Replace("{fps}", renderOptions.Framerate.ToString())
229+
.Replace("{height}", renderOptions.ChatHeight.ToString()).Replace("{width}", renderOptions.ChatWidth.ToString())
230+
.Replace("{save_path}", renderOptions.OutputFileMask).Replace("{max_int}", int.MaxValue.ToString());
231+
maskProcess = new Process
232+
{
233+
StartInfo =
234+
{
235+
FileName = ffmpegFile,
236+
Arguments = $"{inputArgs} {outputArgsMask}",
237+
UseShellExecute = false,
238+
CreateNoWindow = true,
239+
RedirectStandardInput = true,
240+
RedirectStandardOutput = true,
241+
RedirectStandardError = true
242+
}
243+
};
244+
245+
if (File.Exists(renderOptions.OutputFileMask))
246+
File.Delete(renderOptions.OutputFileMask);
247+
248+
maskProcess.Start();
249+
maskProcess.BeginErrorReadLine();
250+
maskProcess.BeginOutputReadLine();
251+
maskStream = new BinaryWriter(maskProcess.StandardInput.BaseStream);
252+
}
253+
224254
using (var ffmpegStream = new BinaryWriter(process.StandardInput.BaseStream))
225255
{
226256
bufferCanvas.Clear(renderOptions.BackgroundColor);
@@ -363,6 +393,19 @@ private void RenderVideo(ChatRenderOptions renderOptions, Queue<TwitchComment> f
363393
var data = SKData.Create(pix.GetPixels(), pix.Info.BytesSize);
364394
var bytes = data.ToArray();
365395
ffmpegStream.Write(bytes);
396+
if (renderOptions.GenerateMask)
397+
{
398+
SKBitmap maskBitmap = new SKBitmap(renderOptions.ChatWidth, renderOptions.ChatHeight);
399+
using (SKCanvas maskCanvas = new SKCanvas(maskBitmap))
400+
{
401+
maskCanvas.Clear(SKColors.White);
402+
maskCanvas.DrawBitmap(bufferBitmap, 0, 0, new SKPaint() { BlendMode = SKBlendMode.DstIn });
403+
}
404+
var pixMask = maskBitmap.PeekPixels();
405+
var dataMask = SKData.Create(pixMask.GetPixels(), pixMask.Info.BytesSize);
406+
var bytesMask = dataMask.ToArray();
407+
maskStream.Write(bytesMask);
408+
}
366409

367410
foreach (var emote in displayedGifs)
368411
{
@@ -381,6 +424,11 @@ private void RenderVideo(ChatRenderOptions renderOptions, Queue<TwitchComment> f
381424
}
382425
}
383426
}
427+
if (renderOptions.GenerateMask)
428+
{
429+
maskStream.Dispose();
430+
maskProcess.WaitForExit();
431+
}
384432
stopwatch.Stop();
385433
progress.Report(new ProgressReport() { reportType = ReportType.Log, data = $"FINISHED. RENDER TIME: {(int)stopwatch.Elapsed.TotalSeconds}s SPEED: {(duration / stopwatch.Elapsed.TotalSeconds).ToString("0.##")}x" });
386434
process.WaitForExit();

TwitchDownloaderCore/Options/ChatRenderOptions.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using SkiaSharp;
22
using System;
33
using System.Collections.Generic;
4+
using System.IO;
45
using System.Text;
56

67
namespace TwitchDownloaderCore.Options
@@ -49,6 +50,19 @@ public int UpdateFrame
4950
return (int)Math.Floor(UpdateRate / (1.0 / Framerate));
5051
}
5152
}
53+
public bool GenerateMask { get; set; }
54+
public string OutputFileMask
55+
{
56+
get
57+
{
58+
if (OutputFile == "" || GenerateMask == false)
59+
return OutputFile;
60+
61+
string extension = Path.GetExtension(OutputFile);
62+
int lastIndex = OutputFile.LastIndexOf(extension);
63+
return OutputFile.Substring(0, lastIndex) + "_mask" + extension;
64+
}
65+
}
5266
public string InputArgs { get; set; }
5367
public string OutputArgs { get; set; }
5468
public string FfmpegPath { get; set; }

TwitchDownloaderWPF/App.config

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,14 @@
8585
<value>255</value>
8686
</setting>
8787
<setting name="OAuth" serializeAs="String">
88-
<value/>
88+
<value />
8989
</setting>
9090
<setting name="EncodeCFR" serializeAs="String">
9191
<value>False</value>
9292
</setting>
93+
<setting name="GenerateMask" serializeAs="String">
94+
<value>False</value>
95+
</setting>
9396
</TwitchDownloader.Properties.Settings>
9497
</userSettings>
9598
</configuration>

TwitchDownloaderWPF/MainWindow.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
66
xmlns:local="clr-namespace:TwitchDownloaderWPF"
77
mc:Ignorable="d"
8-
Title="Twitch Downloader" Height="450" Width="800" Loaded="Window_Loaded" Closing="Window_Closing">
8+
Title="Twitch Downloader" Height="450" Width="850" Loaded="Window_Loaded" Closing="Window_Closing">
99
<Grid>
1010
<Grid.RowDefinitions>
1111
<RowDefinition Height="10" />

TwitchDownloaderWPF/PageChatRender.xaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,14 @@
6565
<TextBlock Text="Live Preview:" HorizontalAlignment="Right" Margin="0,6,0,0"/>
6666
<TextBlock Text="File Format:" HorizontalAlignment="Right" Margin="0,12,0,0"/>
6767
<TextBlock Text="Codec:" HorizontalAlignment="Right" Margin="0,12,0,0"/>
68+
<TextBlock HorizontalAlignment="Right" Margin="0,12,0,0">Generate Mask: <Hyperlink NavigateUri="https://www.youtube.com/watch?v=D-_TD1-w3fY" RequestNavigate="Hyperlink_RequestNavigate" ToolTipService.ShowDuration="30000"><Hyperlink.ToolTip>Generates a seperate video file as a mask for transparency. Click for a tutorial on how to use in Premiere and Vegas.</Hyperlink.ToolTip>(?)</Hyperlink></TextBlock>
6869
<TextBlock Text="FFmpeg&#x0a;Arguments:" HorizontalAlignment="Right" Margin="0,12,0,0"/>
6970
</StackPanel>
7071
<StackPanel Orientation="Vertical">
7172
<Button x:Name="btnPreview" Width="50" Content="View" HorizontalAlignment="Left" Margin="0,5,0,0" Click="btnPreview_Click"/>
7273
<ComboBox x:Name="comboFormat" MinWidth="70" Margin="0,5,0,0"/>
7374
<ComboBox x:Name="comboCodec" MinWidth="70" Margin="0,5,0,0"/>
75+
<CheckBox x:Name="checkMask" Margin="0,6,0,0" Checked="UpdateCheckbox" Unchecked="UpdateCheckbox"/>
7476
<Button x:Name="btnFfmpeg" Width="50" Content="Edit" HorizontalAlignment="Left" Margin="0,15,0,0" Click="btnFfmpeg_Click"/>
7577
</StackPanel>
7678
</StackPanel>

TwitchDownloaderWPF/PageChatRender.xaml.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
using TwitchDownloaderCore;
2424
using System.Threading;
2525
using TwitchDownloaderCore.TwitchObjects;
26+
using System.Windows.Navigation;
2627

2728
namespace TwitchDownloaderWPF
2829
{
@@ -89,7 +90,8 @@ private async void btnRender_Click(object sender, RoutedEventArgs e)
8990
InputArgs = Settings.Default.FfmpegInputArgs,
9091
OutputArgs = Settings.Default.FfmpegOutputArgs,
9192
MessageFontStyle = SKFontStyle.Normal,
92-
UsernameFontStyle = SKFontStyle.Bold
93+
UsernameFontStyle = SKFontStyle.Bold,
94+
GenerateMask = (bool)checkMask.IsChecked
9395
};
9496
options.PaddingLeft = (int)Math.Floor(2 * options.EmoteScale);
9597

@@ -147,6 +149,7 @@ private void LoadSettings()
147149
textUpdateTime.Text = Settings.Default.UpdateTime.ToString("0.##");
148150
colorFont.SelectedColor = System.Windows.Media.Color.FromRgb((byte)Settings.Default.FontColorR, (byte)Settings.Default.FontColorG, (byte)Settings.Default.FontColorB);
149151
textFramerate.Text = Settings.Default.Framerate.ToString();
152+
checkMask.IsChecked = Settings.Default.GenerateMask;
150153

151154
foreach (VideoContainer container in comboFormat.Items)
152155
{
@@ -169,6 +172,12 @@ private void LoadSettings()
169172
catch { }
170173
}
171174

175+
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
176+
{
177+
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
178+
e.Handled = true;
179+
}
180+
172181
private void ComboCodecOnSelectionChanged(object sender, SelectionChangedEventArgs e)
173182
{
174183
if (comboCodec.SelectedItem != null)
@@ -208,6 +217,7 @@ private void SaveSettings()
208217
Settings.Default.FontColorR = colorFont.SelectedColor.Value.R;
209218
Settings.Default.FontColorG = colorFont.SelectedColor.Value.G;
210219
Settings.Default.FontColorB = colorFont.SelectedColor.Value.B;
220+
Settings.Default.GenerateMask = (bool)checkMask.IsChecked;
211221
if (comboFormat.SelectedItem != null)
212222
Settings.Default.VideoContainer = ((VideoContainer)comboFormat.SelectedItem).Name;
213223
if (comboCodec.SelectedItem != null)
@@ -248,7 +258,7 @@ private bool ValidateInputs()
248258

249259
if (colorBackground.SelectedColor.Value.A < 255)
250260
{
251-
if ((((VideoContainer)comboFormat.SelectedItem).Name == "MOV" && ( ((Codec)comboCodec.SelectedItem).Name == "RLE") || ((Codec)comboCodec.SelectedItem).Name == "ProRes") || ((VideoContainer)comboFormat.SelectedItem).Name == "WEBM")
261+
if ((((VideoContainer)comboFormat.SelectedItem).Name == "MOV" && ( ((Codec)comboCodec.SelectedItem).Name == "RLE") || ((Codec)comboCodec.SelectedItem).Name == "ProRes") || ((VideoContainer)comboFormat.SelectedItem).Name == "WEBM" || (bool)checkMask.IsChecked)
252262
{
253263
return true;
254264
}

TwitchDownloaderWPF/Properties/Settings.Designer.cs

Lines changed: 13 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)