Skip to content

Commit

Permalink
Add luma mask option
Browse files Browse the repository at this point in the history
  • Loading branch information
lay295 committed Aug 20, 2020
1 parent 4bc54e9 commit b986854
Show file tree
Hide file tree
Showing 11 changed files with 104 additions and 6 deletions.
2 changes: 2 additions & 0 deletions TwitchDownloaderCLI/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ class Options
public bool FfzEmotes { get; set; }
[Option("outline", Default = false, HelpText = "Enable outline in chat render.")]
public bool Outline { get; set; }
[Option("generate-mask", Default = false, HelpText = "Generates a mask file in addition to the regular chat file.")]
public bool GenerateMask { get; set; }
[Option("outline-size", Default = 4, HelpText = "Size of outline in chat render.")]
public double OutlineSize { get; set; }
[Option('f', "font", Default = "ariel", HelpText = "Font to use in chat render.")]
Expand Down
1 change: 1 addition & 0 deletions TwitchDownloaderCLI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ private static void RenderChat(Options inputOptions)
renderOptions.UpdateRate = inputOptions.UpdateRate;
renderOptions.PaddingLeft = inputOptions.PaddingLeft;
renderOptions.Framerate = inputOptions.Framerate;
renderOptions.GenerateMask = inputOptions.GenerateMask;
renderOptions.InputArgs = inputOptions.InputArgs;
renderOptions.OutputArgs = inputOptions.OutputArgs;
renderOptions.FfmpegPath = inputOptions.FfmpegPath == null || inputOptions.FfmpegPath == "" ? ffmpegPath : inputOptions.FfmpegPath;
Expand Down
5 changes: 4 additions & 1 deletion TwitchDownloaderCLI/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Extra example, if I wanted only seconds 3-6 in a 10 second stream I would do -b
**-t/-\-threads**
(Default: 10) Number of download threads.

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

**-\-generate-mask**
Generates a mask file in addition to the regular chat file.

**-\-framerate**
(Default: 30) Framerate of chat render output.

Expand Down
48 changes: 48 additions & 0 deletions TwitchDownloaderCore/ChatRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,36 @@ private void RenderVideo(ChatRenderOptions renderOptions, Queue<TwitchComment> f
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();

Process maskProcess = null;
BinaryWriter maskStream = null;
if (renderOptions.GenerateMask)
{
string outputArgsMask = renderOptions.OutputArgs.Replace("{fps}", renderOptions.Framerate.ToString())
.Replace("{height}", renderOptions.ChatHeight.ToString()).Replace("{width}", renderOptions.ChatWidth.ToString())
.Replace("{save_path}", renderOptions.OutputFileMask).Replace("{max_int}", int.MaxValue.ToString());
maskProcess = new Process
{
StartInfo =
{
FileName = ffmpegFile,
Arguments = $"{inputArgs} {outputArgsMask}",
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true
}
};

if (File.Exists(renderOptions.OutputFileMask))
File.Delete(renderOptions.OutputFileMask);

maskProcess.Start();
maskProcess.BeginErrorReadLine();
maskProcess.BeginOutputReadLine();
maskStream = new BinaryWriter(maskProcess.StandardInput.BaseStream);
}

using (var ffmpegStream = new BinaryWriter(process.StandardInput.BaseStream))
{
bufferCanvas.Clear(renderOptions.BackgroundColor);
Expand Down Expand Up @@ -363,6 +393,19 @@ private void RenderVideo(ChatRenderOptions renderOptions, Queue<TwitchComment> f
var data = SKData.Create(pix.GetPixels(), pix.Info.BytesSize);
var bytes = data.ToArray();
ffmpegStream.Write(bytes);
if (renderOptions.GenerateMask)
{
SKBitmap maskBitmap = new SKBitmap(renderOptions.ChatWidth, renderOptions.ChatHeight);
using (SKCanvas maskCanvas = new SKCanvas(maskBitmap))
{
maskCanvas.Clear(SKColors.White);
maskCanvas.DrawBitmap(bufferBitmap, 0, 0, new SKPaint() { BlendMode = SKBlendMode.DstIn });
}
var pixMask = maskBitmap.PeekPixels();
var dataMask = SKData.Create(pixMask.GetPixels(), pixMask.Info.BytesSize);
var bytesMask = dataMask.ToArray();
maskStream.Write(bytesMask);
}

foreach (var emote in displayedGifs)
{
Expand All @@ -381,6 +424,11 @@ private void RenderVideo(ChatRenderOptions renderOptions, Queue<TwitchComment> f
}
}
}
if (renderOptions.GenerateMask)
{
maskStream.Dispose();
maskProcess.WaitForExit();
}
stopwatch.Stop();
progress.Report(new ProgressReport() { reportType = ReportType.Log, data = $"FINISHED. RENDER TIME: {(int)stopwatch.Elapsed.TotalSeconds}s SPEED: {(duration / stopwatch.Elapsed.TotalSeconds).ToString("0.##")}x" });
process.WaitForExit();
Expand Down
14 changes: 14 additions & 0 deletions TwitchDownloaderCore/Options/ChatRenderOptions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace TwitchDownloaderCore.Options
Expand Down Expand Up @@ -49,6 +50,19 @@ public int UpdateFrame
return (int)Math.Floor(UpdateRate / (1.0 / Framerate));
}
}
public bool GenerateMask { get; set; }
public string OutputFileMask
{
get
{
if (OutputFile == "" || GenerateMask == false)
return OutputFile;

string extension = Path.GetExtension(OutputFile);
int lastIndex = OutputFile.LastIndexOf(extension);
return OutputFile.Substring(0, lastIndex) + "_mask" + extension;
}
}
public string InputArgs { get; set; }
public string OutputArgs { get; set; }
public string FfmpegPath { get; set; }
Expand Down
5 changes: 4 additions & 1 deletion TwitchDownloaderWPF/App.config
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,14 @@
<value>255</value>
</setting>
<setting name="OAuth" serializeAs="String">
<value/>
<value />
</setting>
<setting name="EncodeCFR" serializeAs="String">
<value>False</value>
</setting>
<setting name="GenerateMask" serializeAs="String">
<value>False</value>
</setting>
</TwitchDownloader.Properties.Settings>
</userSettings>
</configuration>
2 changes: 1 addition & 1 deletion TwitchDownloaderWPF/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TwitchDownloaderWPF"
mc:Ignorable="d"
Title="Twitch Downloader" Height="450" Width="800" Loaded="Window_Loaded" Closing="Window_Closing">
Title="Twitch Downloader" Height="450" Width="850" Loaded="Window_Loaded" Closing="Window_Closing">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="10" />
Expand Down
2 changes: 2 additions & 0 deletions TwitchDownloaderWPF/PageChatRender.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,14 @@
<TextBlock Text="Live Preview:" HorizontalAlignment="Right" Margin="0,6,0,0"/>
<TextBlock Text="File Format:" HorizontalAlignment="Right" Margin="0,12,0,0"/>
<TextBlock Text="Codec:" HorizontalAlignment="Right" Margin="0,12,0,0"/>
<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>
<TextBlock Text="FFmpeg&#x0a;Arguments:" HorizontalAlignment="Right" Margin="0,12,0,0"/>
</StackPanel>
<StackPanel Orientation="Vertical">
<Button x:Name="btnPreview" Width="50" Content="View" HorizontalAlignment="Left" Margin="0,5,0,0" Click="btnPreview_Click"/>
<ComboBox x:Name="comboFormat" MinWidth="70" Margin="0,5,0,0"/>
<ComboBox x:Name="comboCodec" MinWidth="70" Margin="0,5,0,0"/>
<CheckBox x:Name="checkMask" Margin="0,6,0,0" Checked="UpdateCheckbox" Unchecked="UpdateCheckbox"/>
<Button x:Name="btnFfmpeg" Width="50" Content="Edit" HorizontalAlignment="Left" Margin="0,15,0,0" Click="btnFfmpeg_Click"/>
</StackPanel>
</StackPanel>
Expand Down
14 changes: 12 additions & 2 deletions TwitchDownloaderWPF/PageChatRender.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using TwitchDownloaderCore;
using System.Threading;
using TwitchDownloaderCore.TwitchObjects;
using System.Windows.Navigation;

namespace TwitchDownloaderWPF
{
Expand Down Expand Up @@ -89,7 +90,8 @@ private async void btnRender_Click(object sender, RoutedEventArgs e)
InputArgs = Settings.Default.FfmpegInputArgs,
OutputArgs = Settings.Default.FfmpegOutputArgs,
MessageFontStyle = SKFontStyle.Normal,
UsernameFontStyle = SKFontStyle.Bold
UsernameFontStyle = SKFontStyle.Bold,
GenerateMask = (bool)checkMask.IsChecked
};
options.PaddingLeft = (int)Math.Floor(2 * options.EmoteScale);

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

foreach (VideoContainer container in comboFormat.Items)
{
Expand All @@ -169,6 +172,12 @@ private void LoadSettings()
catch { }
}

private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
e.Handled = true;
}

private void ComboCodecOnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (comboCodec.SelectedItem != null)
Expand Down Expand Up @@ -208,6 +217,7 @@ private void SaveSettings()
Settings.Default.FontColorR = colorFont.SelectedColor.Value.R;
Settings.Default.FontColorG = colorFont.SelectedColor.Value.G;
Settings.Default.FontColorB = colorFont.SelectedColor.Value.B;
Settings.Default.GenerateMask = (bool)checkMask.IsChecked;
if (comboFormat.SelectedItem != null)
Settings.Default.VideoContainer = ((VideoContainer)comboFormat.SelectedItem).Name;
if (comboCodec.SelectedItem != null)
Expand Down Expand Up @@ -248,7 +258,7 @@ private bool ValidateInputs()

if (colorBackground.SelectedColor.Value.A < 255)
{
if ((((VideoContainer)comboFormat.SelectedItem).Name == "MOV" && ( ((Codec)comboCodec.SelectedItem).Name == "RLE") || ((Codec)comboCodec.SelectedItem).Name == "ProRes") || ((VideoContainer)comboFormat.SelectedItem).Name == "WEBM")
if ((((VideoContainer)comboFormat.SelectedItem).Name == "MOV" && ( ((Codec)comboCodec.SelectedItem).Name == "RLE") || ((Codec)comboCodec.SelectedItem).Name == "ProRes") || ((VideoContainer)comboFormat.SelectedItem).Name == "WEBM" || (bool)checkMask.IsChecked)
{
return true;
}
Expand Down
14 changes: 13 additions & 1 deletion TwitchDownloaderWPF/Properties/Settings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions TwitchDownloaderWPF/Properties/Settings.settings
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,8 @@
<Setting Name="EncodeCFR" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="GenerateMask" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
</Settings>
</SettingsFile>

0 comments on commit b986854

Please sign in to comment.