Skip to content

Commit

Permalink
1.22
Browse files Browse the repository at this point in the history
  • Loading branch information
lay295 committed Apr 20, 2020
1 parent ccad2d9 commit ddb6473
Show file tree
Hide file tree
Showing 9 changed files with 278 additions and 40 deletions.
6 changes: 6 additions & 0 deletions TwitchDownloaderWPF/App.config
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@
<setting name="BackgroundColorA" serializeAs="String">
<value>255</value>
</setting>
<setting name="OAuth" serializeAs="String">
<value />
</setting>
<setting name="EncodeCFR" serializeAs="String">
<value>False</value>
</setting>
</TwitchDownloader.Properties.Settings>
</userSettings>
</configuration>
1 change: 1 addition & 0 deletions TwitchDownloaderWPF/ChatRoot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public class Emoticon2
public class Message
{
public string body { get; set; }
public int bits_spent { get; set; }
public List<Fragment> fragments { get; set; }
public bool is_action { get; set; }
public List<UserBadge> user_badges { get; set; }
Expand Down
4 changes: 2 additions & 2 deletions TwitchDownloaderWPF/InfoHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ public static async Task<JObject> GetVideoInfo(int videoId)
}
}

public static async Task<JObject> GetVideoToken(int videoId)
public static async Task<JObject> GetVideoToken(int videoId, string authToken)
{
using (WebClient client = new WebClient())
{
client.Encoding = Encoding.UTF8;
client.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko");
string response = await client.DownloadStringTaskAsync(String.Format("https://api.twitch.tv/api/vods/{0}/access_token", videoId));
string response = await client.DownloadStringTaskAsync(String.Format("https://api.twitch.tv/api/vods/{0}/access_token{1}", videoId, (authToken == "" ? "" : "?oauth_token=" + authToken)));
JObject result = JObject.Parse(response);
return result;
}
Expand Down
177 changes: 149 additions & 28 deletions TwitchDownloaderWPF/PageChatRender.xaml.cs

Large diffs are not rendered by default.

10 changes: 7 additions & 3 deletions TwitchDownloaderWPF/PageVodDownload.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,14 @@
<TextBox x:Name="textUrl" Margin="3" MinWidth="200" MaxWidth="400"/>
<Button x:Name="btnGetInfo" Margin="3" MinWidth="50" Content="Get Info" Click="btnGetInfo_Click"/>
</WrapPanel>
<StackPanel Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="2" Margin="0,20,20,0" Orientation="Horizontal" HorizontalAlignment="Center">
<StackPanel Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="2" Margin="0,15,20,0" Orientation="Horizontal" HorizontalAlignment="Center">
<StackPanel HorizontalAlignment="Left">
<TextBlock Text="Length:" HorizontalAlignment="Right"/>
<TextBlock Text="Quality:" HorizontalAlignment="Right" Margin="0,10,0,0"/>
<TextBlock Text="Crop Video:" HorizontalAlignment="Right" Margin="0,14,0,0"/>
<TextBlock Text="Download Threads:" HorizontalAlignment="Right" Margin="0,30,0,0"/>
<TextBlock HorizontalAlignment="Right" Margin="0,12,0,0">OAuth (optional) <Hyperlink NavigateUri="https://www.youtube.com/watch?v=1MBsUoFGuls" RequestNavigate="Hyperlink_RequestNavigate" ToolTipService.ShowDuration="30000"><Hyperlink.ToolTip>Only required for sub only VODs. All 3rd party OAuth tokens will not work. Click to see YouTube video on how to get OAuth token.</Hyperlink.ToolTip>(?)</Hyperlink>:</TextBlock>
<TextBlock HorizontalAlignment="Right" Margin="0,12,0,0">Re-encode to CFR <Hyperlink ToolTipService.ShowDuration="30000"><Hyperlink.ToolTip>Fixes de-sync in Adobe Premiere, will take significantly more time and may result in quality loss.</Hyperlink.ToolTip>(?)</Hyperlink>:</TextBlock>
</StackPanel>
<StackPanel>
<TextBlock x:Name="labelLength" Text="0:0:0" Margin="5,0,0,0"/>
Expand All @@ -77,11 +79,13 @@
<xctk:IntegerUpDown Margin="3,-1,0,0" Value="0" Name="numEndMinute" />
<xctk:IntegerUpDown Margin="3,-1,0,0" Value="0" Name="numEndSecond" />
</StackPanel>
<xctk:IntegerUpDown IsEnabled="False" Margin="2,5,0,0" Value="10" Width="40" x:Name="numDownloadThreads" HorizontalAlignment="Left" ValueChanged="numDownloadThreads_ValueChanged" />
<xctk:IntegerUpDown Margin="2,5,0,0" Value="10" Width="40" x:Name="numDownloadThreads" HorizontalAlignment="Left" ValueChanged="numDownloadThreads_ValueChanged" />
<TextBox x:Name="textOauth" Margin="0,8,3,3" MinWidth="200" MaxWidth="400" TextChanged="textOauth_TextChanged"/>
<CheckBox x:Name="checkCFR" Margin="0,2,0,0" Checked="checkCFR_Changed" Unchecked="checkCFR_Changed"></CheckBox>
</StackPanel>
</StackPanel>
</StackPanel>
<Button x:Name="btnDownload" Grid.Row="3" Grid.Column="2" Grid.ColumnSpan="2" Content="Download" Height="50" Width="100" Click="btnDownload_Click" Margin="0,0,0,20" VerticalAlignment="Bottom"/>
<Button x:Name="btnDownload" Grid.Row="3" Grid.Column="2" Grid.ColumnSpan="2" Content="Download" Height="50" Width="100" Click="btnDownload_Click" Margin="0,0,0,10" VerticalAlignment="Bottom"/>
<!-- RIGHT -->
<StackPanel Grid.Column="4" Grid.Row="2" Grid.RowSpan="2">
<TextBlock Text="Log:"/>
Expand Down
87 changes: 81 additions & 6 deletions TwitchDownloaderWPF/PageVodDownload.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.Linq;
Expand All @@ -27,6 +28,7 @@
using Xabe.FFmpeg;
using WpfAnimatedGif;
using TwitchDownloader.Properties;
using Xabe.FFmpeg.Events;

namespace TwitchDownloaderWPF
{
Expand Down Expand Up @@ -55,7 +57,11 @@ private void SetEnabled(bool isEnabled)
numEndMinute.IsEnabled = isEnabled;
numEndSecond.IsEnabled = isEnabled;
btnDownload.IsEnabled = isEnabled;
numDownloadThreads.IsEnabled = isEnabled;
}
private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
e.Handled = true;
}

private async void btnGetInfo_Click(object sender, RoutedEventArgs e)
Expand All @@ -67,7 +73,7 @@ private async void btnGetInfo_Click(object sender, RoutedEventArgs e)
try
{
Task<JObject> taskInfo = InfoHelper.GetVideoInfo(videoId);
Task<JObject> taskAccessToken = InfoHelper.GetVideoToken(videoId);
Task<JObject> taskAccessToken = InfoHelper.GetVideoToken(videoId, textOauth.Text);
await Task.WhenAll(taskInfo, taskAccessToken);
string thumbUrl = taskInfo.Result["data"][0]["thumbnail_url"].ToString().Replace("%{width}", 512.ToString()).Replace("%{height}", 290.ToString());
Task<BitmapImage> thumbImage = InfoHelper.GetThumb(thumbUrl);
Expand Down Expand Up @@ -278,14 +284,67 @@ private void BackgroundDownloadManager_DoWork(object sender, DoWorkEventArgs e)
catch { }
}
}

(sender as BackgroundWorker).ReportProgress(0, "Finalizing MP4 (3/3)");

bool isVFR = false;
if (options.encode_cfr)
{
var process = new Process
{
StartInfo =
{
FileName = "ffmpeg.exe",
Arguments = $"-i \"" + Path.Combine(downloadFolder, "output.ts") + "\" -vf vfrdet -f null -",
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true
}
};
string output = "";
process.ErrorDataReceived += delegate(object o, DataReceivedEventArgs args)
{
if (args.Data != null && args.Data.Contains("Parsed_vfrdet"))
{
output += args.Data;
}
};
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
process.WaitForExit();
double VFR = double.Parse(output.Substring(output.IndexOf("VFR:") + 4, 8));
if (VFR == 0.0)
{
AppendLog("Constant framerate detected, no need to re-encode");
}
else
{
isVFR = true;
AppendLog("Detected variable framerate, re-encoding");
}
}

if (isVFR)
(sender as BackgroundWorker).ReportProgress(0, "Re-encoding MP4 (3/3)");
else
(sender as BackgroundWorker).ReportProgress(0, "Finalizing MP4 (3/3)");
string outputConvert = options.filename;
Task<IMediaInfo> info = MediaInfo.Get(Path.Combine(downloadFolder, "output.ts"));
Task.WaitAll(info);
double seekTime = options.crop_begin;
double seekDuration = info.Result.Duration.TotalSeconds - seekTime - options.crop_end;
Task<IConversionResult> conversionResult = Conversion.New().Start(String.Format("-y -i \"{0}\" -ss {1} -analyzeduration {2} -t {3} -avoid_negative_ts make_zero -vcodec copy \"{4}\"", Path.Combine(downloadFolder, "output.ts"), seekTime.ToString(), int.MaxValue, seekDuration.ToString(), outputConvert));
double seekDuration = Math.Round(info.Result.Duration.TotalSeconds - seekTime - options.crop_end);
Task<IConversionResult> conversionResult = null;
if (isVFR)
{
int newFps = (int)Math.Ceiling(info.Result.VideoStreams.First().FrameRate);
conversionResult = Conversion.New().Start(String.Format("-y -i \"{0}\" -ss {1} -analyzeduration {2} -t {3} -crf 20 -filter:v fps=fps={4} \"{5}\"", Path.Combine(downloadFolder, "output.ts"), seekTime.ToString(), int.MaxValue, seekDuration.ToString(), newFps, outputConvert));
}
else
{
conversionResult = Conversion.New().Start(String.Format("-y -i \"{0}\" -ss {1} -analyzeduration {2} -t {3} -avoid_negative_ts make_zero -acodec copy -vcodec copy \"{4}\"", Path.Combine(downloadFolder, "output.ts"), seekTime.ToString(), int.MaxValue, seekDuration.ToString(), outputConvert));
}

Task.WaitAll(conversionResult);
if (Directory.Exists(downloadFolder))
DeleteDirectory(downloadFolder);
Expand Down Expand Up @@ -477,6 +536,8 @@ private void Page_Initialized(object sender, EventArgs e)
SetEnabled(false);
WebRequest.DefaultWebProxy = null;
numDownloadThreads.Value = Settings.Default.VodDownloadThreads;
textOauth.Text = Settings.Default.OAuth;
checkCFR.IsChecked = Settings.Default.EncodeCFR;
}

private void numDownloadThreads_ValueChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
Expand All @@ -487,6 +548,18 @@ private void numDownloadThreads_ValueChanged(object sender, RoutedPropertyChange
Settings.Default.Save();
}
}

private void textOauth_TextChanged(object sender, TextChangedEventArgs e)
{
Settings.Default.OAuth = textOauth.Text;
Settings.Default.Save();
}

private void checkCFR_Changed(object sender, RoutedEventArgs e)
{
Settings.Default.EncodeCFR = (bool)checkCFR.IsChecked;
Settings.Default.Save();
}
}
}
public class ProgressReport
Expand Down Expand Up @@ -516,6 +589,7 @@ public class DownloadOptions
public TimeSpan cropped_end_time { get; set; }
public double crop_end { get; set; }
public int download_threads { get; set; }
public bool encode_cfr { get; set; }
public DownloadOptions()
{

Expand All @@ -535,5 +609,6 @@ public void UpdateValues(PageVodDownload currentPage)
crop_begin = 0.0;
crop_end = 0.0;
download_threads = (int)currentPage.numDownloadThreads.Value;
encode_cfr = (bool)currentPage.checkCFR.IsChecked;
}
}
24 changes: 24 additions & 0 deletions TwitchDownloaderWPF/Properties/Settings.Designer.cs

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

6 changes: 6 additions & 0 deletions TwitchDownloaderWPF/Properties/Settings.settings
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,11 @@
<Setting Name="BackgroundColorA" Type="System.Int32" Scope="User">
<Value Profile="(Default)">255</Value>
</Setting>
<Setting Name="OAuth" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
<Setting Name="EncodeCFR" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
</Settings>
</SettingsFile>
3 changes: 2 additions & 1 deletion TwitchDownloaderWPF/WindowPreview.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public void Update(PageChatRender pageChatRender)
SKBitmap sectionImage = new SKBitmap((int)canvasSize.Width, (int)canvasSize.Height);
List<GifEmote> currentGifEmotes = new List<GifEmote>();
List<SKBitmap> emoteList = new List<SKBitmap>();
List<CheerEmote> cheerEmotes = new List<CheerEmote>();
List<SKRect> emotePositionList = new List<SKRect>();
new SKCanvas(sectionImage).Clear(renderOptions.background_color);
Comment comment = new Comment();
Expand All @@ -93,7 +94,7 @@ public void Update(PageChatRender pageChatRender)
if (previewComment.badges != null)
sectionImage = DrawBadges(sectionImage, imageList, renderOptions, canvasSize, ref drawPos, previewComment);
sectionImage = pageChatRender.DrawUsername(sectionImage, imageList, renderOptions, nameFont, userName, userColor, canvasSize, ref drawPos);
sectionImage = pageChatRender.DrawMessage(sectionImage, imageList, renderOptions, currentGifEmotes, messageFont, emojiCache, chatEmotes, thirdPartyEmotes, comment, canvasSize, ref drawPos, emojiRegex, ref default_x, emoteList, emotePositionList);
sectionImage = pageChatRender.DrawMessage(sectionImage, imageList, renderOptions, currentGifEmotes, messageFont, emojiCache, chatEmotes, thirdPartyEmotes, cheerEmotes, comment, canvasSize, ref drawPos, emojiRegex, ref default_x, emoteList, emotePositionList);


int finalHeight = 0;
Expand Down

0 comments on commit ddb6473

Please sign in to comment.