diff --git a/TwitchDownloaderCLI/Program.cs b/TwitchDownloaderCLI/Program.cs index d3b327f5..edabf087 100644 --- a/TwitchDownloaderCLI/Program.cs +++ b/TwitchDownloaderCLI/Program.cs @@ -1,4 +1,5 @@ using CommandLine; +using Mono.Unix; using SkiaSharp; using System; using System.IO; @@ -13,6 +14,8 @@ namespace TwitchDownloaderCLI { class Program { + static string previousStatus = ""; + static string ffmpegPath = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "ffmpeg.exe" : "ffmpeg"; static void Main(string[] args) { if (args.Any(x => x.Equals("--download-ffmpeg"))) @@ -21,6 +24,13 @@ static void Main(string[] args) if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { FFmpegDownloader.GetLatestVersion(FFmpegVersion.Official).Wait(); + try + { + var filePermissions = new Mono.Unix.UnixFileInfo("ffmpeg"); + filePermissions.FileAccessPermissions = FileAccessPermissions.UserRead | FileAccessPermissions.UserWrite| FileAccessPermissions.GroupRead| FileAccessPermissions.OtherRead | FileAccessPermissions.UserExecute | FileAccessPermissions.GroupExecute | FileAccessPermissions.OtherExecute; + filePermissions.Refresh(); + } + catch { } } else FFmpegDownloader.GetLatestVersion(FFmpegVersion.Full).Wait(); @@ -33,10 +43,10 @@ static void Main(string[] args) if (optionsResult.Tag == ParserResultType.NotParsed) Environment.Exit(1); - string ffmpegPath = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "ffmpeg.exe" : "ffmpeg"; + if (!File.Exists(ffmpegPath)) { - Console.WriteLine("[ERROR] - Unable to find ffmpeg, exiting"); + Console.WriteLine("[ERROR] - Unable to find ffmpeg, exiting. You can download ffmpeg automatically with the argument --download-ffmpeg"); Environment.Exit(1); } @@ -76,7 +86,7 @@ private static void DownloadVideo(Options inputOptions) downloadOptions.CropBeginningTime = inputOptions.CropBeginningTime; downloadOptions.CropEnding = inputOptions.CropEndingTime == 0.0 ? false : true; downloadOptions.CropEndingTime = inputOptions.CropEndingTime; - downloadOptions.FfmpegPath = inputOptions.FfmpegPath; + downloadOptions.FfmpegPath = inputOptions.FfmpegPath == null || inputOptions.FfmpegPath == "" ? ffmpegPath : inputOptions.FfmpegPath; VideoDownloader videoDownloader = new VideoDownloader(downloadOptions); Progress progress = new Progress(); @@ -88,7 +98,7 @@ private static void DownloadClip(Options inputOptions) { ClipDownloadOptions downloadOptions = new ClipDownloadOptions(); - if (inputOptions.Id == "" || inputOptions.Id.All(Char.IsLetter)) + if (inputOptions.Id == "" || inputOptions.Id.Any(x => !Char.IsLetter(x))) { Console.WriteLine("[ERROR] - Invalid Clip ID, unable to parse. Must be only letters."); Environment.Exit(1); @@ -189,6 +199,7 @@ private static void RenderChat(Options inputOptions) renderOptions.Framerate = inputOptions.Framerate; renderOptions.InputArgs = inputOptions.InputArgs; renderOptions.OutputArgs = inputOptions.OutputArgs; + renderOptions.FfmpegPath = inputOptions.FfmpegPath == null || inputOptions.FfmpegPath == "" ? ffmpegPath : inputOptions.FfmpegPath; ChatRenderer chatDownloader = new ChatRenderer(renderOptions); Progress progress = new Progress(); @@ -198,9 +209,18 @@ private static void RenderChat(Options inputOptions) private static void Progress_ProgressChanged(object sender, ProgressReport e) { - if (e.reportType == ReportType.Percent) + if (e.reportType == ReportType.Message) + { + string currentStatus = "[STATUS] - " + e.data; + if (currentStatus != previousStatus) + { + previousStatus = currentStatus; + Console.WriteLine(currentStatus); + } + } + else if (e.reportType == ReportType.Log) { - Console.WriteLine(e.data); + Console.WriteLine("[LOG] - " + e.data); } } } diff --git a/TwitchDownloaderCLI/Properties/launchSettings.json b/TwitchDownloaderCLI/Properties/launchSettings.json new file mode 100644 index 00000000..3ccd7d10 --- /dev/null +++ b/TwitchDownloaderCLI/Properties/launchSettings.json @@ -0,0 +1,7 @@ +{ + "profiles": { + "TwitchDownloaderCLI": { + "commandName": "Project" + } + } +} \ No newline at end of file diff --git a/TwitchDownloaderCore/ChatRenderer.cs b/TwitchDownloaderCore/ChatRenderer.cs index 4e2cc776..ee17755e 100644 --- a/TwitchDownloaderCore/ChatRenderer.cs +++ b/TwitchDownloaderCore/ChatRenderer.cs @@ -218,6 +218,9 @@ private void RenderVideo(ChatRenderOptions renderOptions, Queue f process.BeginErrorReadLine(); process.BeginOutputReadLine(); + Stopwatch stopwatch = new Stopwatch(); + stopwatch.Start(); + using (var ffmpegStream = new BinaryWriter(process.StandardInput.BaseStream)) { bufferCanvas.Clear(renderOptions.BackgroundColor); @@ -372,10 +375,14 @@ private void RenderVideo(ChatRenderOptions renderOptions, Queue f if (progress != null) { progress.Report(new ProgressReport() { reportType = ReportType.Percent, data = percentInt }); - progress.Report(new ProgressReport() { reportType = ReportType.Message, data = $"Rendering Video {percentInt}%" }); + int timeLeftInt = (int)Math.Floor(100.0 / percentDouble * stopwatch.Elapsed.TotalSeconds) - (int)stopwatch.Elapsed.TotalSeconds; + TimeSpan timeLeft = new TimeSpan(0, 0, timeLeftInt); + progress.Report(new ProgressReport() { reportType = ReportType.Message, data = $"Rendering Video {percentInt}% ({timeLeft.ToString(@"h\hm\ms\s")} left)" }); } } } + 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(); } public static SKBitmap DrawTimestamp(SKBitmap sectionImage, List imageList, SKPaint messageFont, ChatRenderOptions renderOptions, Comment comment, Size canvasSize, ref Point drawPos, ref int default_x) @@ -532,13 +539,13 @@ public static SKBitmap DrawMessage(SKBitmap sectionImage, List imageLi codepoint = codepoint.Replace("fe0f", ""); if (codepoint != "" && emojiCache.ContainsKey(codepoint)) { + SKBitmap emojiBitmap = emojiCache[codepoint]; + float emojiSize = (emojiBitmap.Width / 4) * (float)renderOptions.EmoteScale; + if (drawPos.X + (20 * renderOptions.EmoteScale) + 3 > canvasSize.Width) + sectionImage = AddImageSection(sectionImage, imageList, renderOptions, currentGifEmotes, canvasSize, ref drawPos, default_x); + using (SKCanvas sectionImageCanvas = new SKCanvas(sectionImage)) { - SKBitmap emojiBitmap = emojiCache[codepoint]; - float emojiSize = (emojiBitmap.Width / 4) * (float)renderOptions.EmoteScale; - if (drawPos.X + (20 * renderOptions.EmoteScale) + 3 > canvasSize.Width) - sectionImage = AddImageSection(sectionImage, imageList, renderOptions, currentGifEmotes, canvasSize, ref drawPos, default_x); - float emojiLeft = (float)drawPos.X; float emojiTop = (float)Math.Floor((renderOptions.SectionHeight - emojiSize) / 2.0); SKRect emojiRect = new SKRect(emojiLeft, emojiTop, emojiLeft + emojiSize, emojiTop + emojiSize);