Skip to content

Commit 5b3ea38

Browse files
authored
More video info (#774)
* Add views, game, length, and length_custom filename parameters * Update translations Note: Google translate was used to check punctuation * Better memory performance when serializing FFmetadata * Bump ChatRootVersion
1 parent 0a1a97a commit 5b3ea38

25 files changed

+161
-61
lines changed

TwitchDownloaderCore/ChatDownloader.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,8 @@ public async Task DownloadAsync(IProgress<ProgressReport> progress, Cancellation
269269
double videoEnd = 0.0;
270270
double videoDuration = 0.0;
271271
double videoTotalLength;
272+
int viewCount;
273+
string game;
272274
int connectionCount = downloadOptions.ConnectionCount;
273275

274276
if (downloadType == DownloadType.Video)
@@ -286,6 +288,8 @@ public async Task DownloadAsync(IProgress<ProgressReport> progress, Cancellation
286288
videoStart = downloadOptions.CropBeginning ? downloadOptions.CropBeginningTime : 0.0;
287289
videoEnd = downloadOptions.CropEnding ? downloadOptions.CropEndingTime : videoInfoResponse.data.video.lengthSeconds;
288290
videoTotalLength = videoInfoResponse.data.video.lengthSeconds;
291+
viewCount = videoInfoResponse.data.video.viewCount;
292+
game = videoInfoResponse.data.video.game?.displayName ?? "Unknown";
289293

290294
GqlVideoChapterResponse videoChapterResponse = await TwitchHelper.GetVideoChapters(int.Parse(videoId));
291295
foreach (var responseChapter in videoChapterResponse.data.video.moments.edges)
@@ -325,6 +329,8 @@ public async Task DownloadAsync(IProgress<ProgressReport> progress, Cancellation
325329
videoStart = (int)clipInfoResponse.data.clip.videoOffsetSeconds;
326330
videoEnd = (int)clipInfoResponse.data.clip.videoOffsetSeconds + clipInfoResponse.data.clip.durationSeconds;
327331
videoTotalLength = clipInfoResponse.data.clip.durationSeconds;
332+
viewCount = clipInfoResponse.data.clip.viewCount;
333+
game = clipInfoResponse.data.clip.game?.displayName ?? "Unknown";
328334
connectionCount = 1;
329335
}
330336

@@ -334,6 +340,8 @@ public async Task DownloadAsync(IProgress<ProgressReport> progress, Cancellation
334340
chatRoot.video.start = videoStart;
335341
chatRoot.video.end = videoEnd;
336342
chatRoot.video.length = videoTotalLength;
343+
chatRoot.video.viewCount = viewCount;
344+
chatRoot.video.game = game;
337345
videoDuration = videoEnd - videoStart;
338346

339347
var tasks = new List<Task<List<Comment>>>();

TwitchDownloaderCore/Tools/FfmpegMetadata.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.IO;
4+
using System.Text;
45
using System.Threading;
56
using System.Threading.Tasks;
67
using TwitchDownloaderCore.TwitchObjects.Gql;
@@ -36,7 +37,7 @@ private static async Task SerializeGlobalMetadata(StreamWriter sw, string stream
3637

3738
private static async Task SerializeChapters(StreamWriter sw, List<VideoMomentEdge> videoMomentEdges, double startOffsetSeconds)
3839
{
39-
// Note: Ffmpeg automatically handles out of range chapters for us
40+
// Note: FFmpeg automatically handles out of range chapters for us
4041
var startOffsetMillis = (int)(startOffsetSeconds * 1000);
4142
foreach (var momentEdge in videoMomentEdges)
4243
{
@@ -64,11 +65,17 @@ private static string SanitizeKeyValue(string str)
6465
return str;
6566
}
6667

67-
return str
68+
if (str.AsSpan().IndexOfAny(@"=;#\") == -1)
69+
{
70+
return str;
71+
}
72+
73+
return new StringBuilder(str)
6874
.Replace("=", @"\=")
6975
.Replace(";", @"\;")
7076
.Replace("#", @"\#")
71-
.Replace(@"\", @"\\");
77+
.Replace(@"\", @"\\")
78+
.ToString();
7279
}
7380
}
7481
}

TwitchDownloaderCore/TwitchObjects/ChatRoot.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,8 @@ public class Video
198198
public double start { get; set; }
199199
public double end { get; set; }
200200
public double length { get; set; } = -1;
201+
public int viewCount { get; set; }
202+
public string game { get; set; }
201203
public List<VideoChapter> chapters { get; set; } = new();
202204

203205
#region DeprecatedProperties

TwitchDownloaderCore/TwitchObjects/ChatRootInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public class ChatRootVersion
1818
public int Minor { get; set; } = 0;
1919
public int Patch { get; set; } = 0;
2020

21-
public static ChatRootVersion CurrentVersion { get; } = new(1, 3, 0);
21+
public static ChatRootVersion CurrentVersion { get; } = new(1, 3, 1);
2222

2323
// Constructors
2424
/// <summary>

TwitchDownloaderCore/TwitchObjects/Gql/GqlClipResponse.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
using System;
2-
using System.Collections.Generic;
3-
using System.Text;
42

53
namespace TwitchDownloaderCore.TwitchObjects.Gql
64
{
@@ -15,6 +13,12 @@ public class ClipVideo
1513
public string id { get; set; }
1614
}
1715

16+
public class ClipGame
17+
{
18+
public string id { get; set; }
19+
public string displayName { get; set; }
20+
}
21+
1822
public class Clip
1923
{
2024
public string title { get; set; }
@@ -24,6 +28,8 @@ public class Clip
2428
public ClipBroadcaster broadcaster { get; set; }
2529
public int? videoOffsetSeconds { get; set; }
2630
public ClipVideo video { get; set; }
31+
public int viewCount { get; set; }
32+
public ClipGame game { get; set; }
2733
}
2834

2935
public class ClipData

TwitchDownloaderCore/TwitchObjects/Gql/GqlClipSearchResponse.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Text;
43

54
namespace TwitchDownloaderCore.TwitchObjects.Gql
65
{
6+
public class ClipNodeGame
7+
{
8+
public string id { get; set; }
9+
public string displayName { get; set; }
10+
}
11+
712
public class ClipNode
813
{
914
public string id { get; set; }
@@ -13,6 +18,7 @@ public class ClipNode
1318
public int durationSeconds { get; set; }
1419
public string thumbnailURL { get; set; }
1520
public int viewCount { get; set; }
21+
public ClipNodeGame game { get; set; }
1622
}
1723

1824
public class Edge

TwitchDownloaderCore/TwitchObjects/Gql/GqlVideoChapterResponse.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class GameChangeMomentDetails
2323

2424
public class VideoMoment
2525
{
26-
public VideoMomentConnection moments { get; set; } // seemingly always blank. Probably needs Oauth in the request to be populated
26+
public VideoMomentConnection moments { get; set; } // seemingly always blank. Oauth does not seem to make a difference
2727
public string id { get; set; }
2828
public int durationMilliseconds { get; set; }
2929
public int positionMilliseconds { get; set; }

TwitchDownloaderCore/TwitchObjects/Gql/GqlVideoResponse.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,21 @@ public class VideoOwner
99
public string displayName { get; set; }
1010
}
1111

12+
public class VideoGame
13+
{
14+
public string id { get; set; }
15+
public string displayName { get; set; }
16+
}
17+
1218
public class VideoInfo
1319
{
1420
public string title { get; set; }
1521
public List<string> thumbnailURLs { get; set; }
1622
public DateTime createdAt { get; set; }
1723
public int lengthSeconds { get; set; }
1824
public VideoOwner owner { get; set; }
25+
public int viewCount { get; set; }
26+
public VideoGame game { get; set; }
1927
}
2028

2129
public class VideoData

TwitchDownloaderCore/TwitchObjects/Gql/GqlVideoSearchResponse.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Text;
43

54
namespace TwitchDownloaderCore.TwitchObjects.Gql
65
{
6+
public class VideoNodeGame
7+
{
8+
public string id { get; set; }
9+
public string displayName { get; set; }
10+
}
11+
712
public class VideoNode
813
{
914
public string title { get; set; }
@@ -12,6 +17,7 @@ public class VideoNode
1217
public string previewThumbnailURL { get; set; }
1318
public DateTime createdAt { get; set; }
1419
public int viewCount { get; set; }
20+
public VideoNodeGame game { get; set; }
1521
}
1622

1723
public class VideoEdge

TwitchDownloaderWPF/PageChatDownload.xaml.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ public partial class PageChatDownload : Page
3333
public int streamerId;
3434
public DateTime currentVideoTime;
3535
public TimeSpan vodLength;
36+
public int viewCount;
37+
public string game;
3638
private CancellationTokenSource _cancellationTokenSource;
3739

3840
public PageChatDownload()
@@ -136,6 +138,8 @@ private async Task GetVideoInfo()
136138
textCreatedAt.Text = Settings.Default.UTCVideoTime ? videoTime.ToString(CultureInfo.CurrentCulture) : videoTime.ToLocalTime().ToString(CultureInfo.CurrentCulture);
137139
currentVideoTime = Settings.Default.UTCVideoTime ? videoTime : videoTime.ToLocalTime();
138140
streamerId = int.Parse(videoInfo.data.video.owner.id);
141+
viewCount = videoInfo.data.video.viewCount;
142+
game = videoInfo.data.video.game?.displayName ?? "Unknown";
139143
var urlTimeCodeMatch = Regex.Match(textUrl.Text, @"(?<=\?t=)\d+h\d+m\d+s");
140144
if (urlTimeCodeMatch.Success)
141145
{
@@ -469,7 +473,8 @@ private async void SplitBtnDownload_Click(object sender, RoutedEventArgs e)
469473

470474
saveFileDialog.FileName = FilenameService.GetFilename(Settings.Default.TemplateChat, textTitle.Text, downloadId, currentVideoTime, textStreamer.Text,
471475
checkCropStart.IsChecked == true ? new TimeSpan((int)numStartHour.Value, (int)numStartMinute.Value, (int)numStartSecond.Value) : TimeSpan.Zero,
472-
checkCropEnd.IsChecked == true ? new TimeSpan((int)numEndHour.Value, (int)numEndMinute.Value, (int)numEndSecond.Value) : vodLength);
476+
checkCropEnd.IsChecked == true ? new TimeSpan((int)numEndHour.Value, (int)numEndMinute.Value, (int)numEndSecond.Value) : vodLength,
477+
viewCount.ToString(), game);
473478

474479
if (saveFileDialog.ShowDialog() != true)
475480
{

0 commit comments

Comments
 (0)