Advertisement
VladislavSavvateev

Untitled

May 27th, 2021
1,077
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 7.90 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Drawing;
  5. using System.Drawing.Imaging;
  6. using System.IO;
  7. using System.Json;
  8. using System.Linq;
  9. using System.Net;
  10. using System.Text;
  11. using System.Text.RegularExpressions;
  12. using System.Threading;
  13.  
  14. namespace DictorWatch {
  15.     internal static class Program {
  16.         private static readonly string[] RequiredPrograms = {"youtube-dl.exe", "ffmpeg.exe", "ffprobe.exe"};
  17.  
  18.         private static readonly string[] FunnyTracksIGuess = {
  19.             "https://www.youtube.com/watch?v=tw7HHUItwAg",
  20.             "https://www.youtube.com/watch?v=pqQq4hla0xo"
  21.         };
  22.  
  23.         static void Main(string[] args) {
  24.             if (RequiredPrograms.Any(p => !IsItInstalled(p))) {
  25.                 Console.WriteLine("ERR: {0} is not installed!",
  26.                     string.Join(", ", RequiredPrograms.Where(p => !IsItInstalled(p))));
  27.                 return;
  28.             }
  29.            
  30.             var filename = RandomString();
  31.            
  32.             Console.Write("Enter YouTube URL: ");
  33.             var ytUrl = Console.ReadLine();
  34.             if (ytUrl == null) {
  35.                 Console.WriteLine("ERR: Provide an Youtube URL!");
  36.                 return;
  37.             }
  38.            
  39.             Log("Downloading the source video...");
  40.             var videoName = DownloadYouTubeVideo(ytUrl, filename);
  41.             DoSomeFfmpeg(filename, videoName);
  42.         }
  43.  
  44.         private static string DownloadYouTubeVideo(string url, string outputFile) {
  45.             var proc = Process.Start(new ProcessStartInfo {
  46.                 FileName = "youtube-dl.exe",
  47.                 Arguments = $"{url} -o {outputFile}",
  48.                 WorkingDirectory = Directory.GetCurrentDirectory(),
  49.                 RedirectStandardOutput = true,
  50.                 RedirectStandardError = true
  51.             });
  52.             var result = proc.StandardOutput.ReadToEnd();
  53.             return new Regex("Merging formats into \"(.*\\..*)\"").Match(result).Groups[1].Value;
  54.         }
  55.  
  56.         private static void DoSomeFfmpeg(string filename, string source) {
  57.             var proc = Process.Start(new ProcessStartInfo {
  58.                 FileName = "ffprobe.exe",
  59.                 Arguments = source,
  60.                 WorkingDirectory = Directory.GetCurrentDirectory(),
  61.                 RedirectStandardError = true
  62.             });
  63.             if (proc == null) throw new Exception("Something happened with ffprobe!");
  64.            
  65.             var output = proc.StandardError.ReadToEnd();
  66.             var regex = new Regex(@"DURATION.+(\d\d:\d\d:\d\d.\d{9})");
  67.             var match = regex.Match(output);
  68.             var duration = TimeSpan.Parse(match.Groups[1].Value[..match.Groups[1].Value.IndexOf('.')]);
  69.             var framerate = int.Parse(new Regex(@"(\d*) fps").Match(output).Groups[1].Value);
  70.            
  71.             Log("Getting frames...");
  72.  
  73.             proc = Process.Start(new ProcessStartInfo {
  74.                 FileName = "ffmpeg.exe",
  75.                 Arguments = $"-i \"{source}\" -ss {new Random().Next((int) duration.TotalSeconds - 60)} -t 15 -r {framerate / 12} {filename}_%03d.png",
  76.                 WorkingDirectory = Directory.GetCurrentDirectory()
  77.             });
  78.             proc.WaitForExit();
  79.  
  80.             var filesToDelete = new List<string>();
  81.  
  82.             var files = Directory.EnumerateFiles(Directory.GetCurrentDirectory(), $"{filename}_*.png").ToList();
  83.            
  84.             Log("Processing images through Face API. This might take a while...");
  85.  
  86.             for (var i = 0; i < files.Count; i++) {
  87.                 Console.WriteLine("Processing {0} of {1}...", i + 1, files.Count);
  88.  
  89.                 var path = files[i];
  90.  
  91.                 var facePos = GetFacePositions(path).ToList();
  92.                 if (facePos.Count == 0) {
  93.                     filesToDelete.Add(path);
  94.                     Thread.Sleep(4000);
  95.                     continue;
  96.                 }
  97.  
  98.                 Bitmap cropped;
  99.  
  100.                 using (var bmp = new Bitmap(path)) cropped = bmp.Clone(facePos[0], PixelFormat.Format24bppRgb);
  101.                
  102.                 cropped.Save(path);
  103.                
  104.                 Thread.Sleep(4000);
  105.             }
  106.  
  107.             foreach (var file in filesToDelete) File.Delete(file);
  108.            
  109.             Log("Downloading funny audio...");
  110.            
  111.             // download audio
  112.             var audioFromYT = DownloadYouTubeVideo(FunnyTracksIGuess[new Random().Next(FunnyTracksIGuess.Length)], $"{filename}.audio");
  113.             proc = Process.Start(new ProcessStartInfo {
  114.                 FileName = "ffmpeg.exe",
  115.                 Arguments = $"-i \"{audioFromYT}\" {filename}.mp3",
  116.                 WorkingDirectory = Directory.GetCurrentDirectory()
  117.             });
  118.             proc.WaitForExit();
  119.            
  120.             Log("Generating gif...");
  121.            
  122.             // generate gif (or yi-ff, whatever)
  123.             proc = Process.Start(new ProcessStartInfo {
  124.                 FileName = "ffmpeg.exe",
  125.                 Arguments = $"-i {filename}_%03d.png -pix_fmt rgb24 {filename}.gif",
  126.                 WorkingDirectory = Directory.GetCurrentDirectory()
  127.             });
  128.             proc.WaitForExit();
  129.            
  130.             Log("Generating the result...");
  131.            
  132.             // generate result
  133.             proc = Process.Start(new ProcessStartInfo {
  134.                 FileName = "ffmpeg.exe",
  135.                 Arguments = $"-stream_loop -1 -i {filename}.gif -i {filename}.mp3 -shortest {filename}.mp4",
  136.                 WorkingDirectory = Directory.GetCurrentDirectory()
  137.             });
  138.             proc.WaitForExit();
  139.            
  140.             Log("Cleaning after ourselves...");
  141.  
  142.             foreach (var path in Directory.GetFiles(Directory.GetCurrentDirectory(), $"{filename}*"))
  143.                 if (!path.EndsWith($"{filename}.mp4")) File.Delete(path);
  144.         }
  145.  
  146.         private static void Log(string log) {
  147.             var oldColor = Console.ForegroundColor;
  148.             Console.ForegroundColor = ConsoleColor.DarkGreen;
  149.             Console.WriteLine(log);
  150.             Console.ForegroundColor = oldColor;
  151.         }
  152.  
  153.         private static string RandomString() {
  154.             var bytes = new byte[16];
  155.             new Random().NextBytes(bytes);
  156.             return bytes.Aggregate("", (s, b) => $"{s}{b:x2}");
  157.         }
  158.  
  159.         private static bool IsItInstalled(string program) {
  160.             try {
  161.                 Process.Start(new ProcessStartInfo {
  162.                     FileName = program,
  163.                     RedirectStandardOutput = true,
  164.                     RedirectStandardError = true
  165.                 });
  166.                 return true;
  167.             } catch { return false; }
  168.         }
  169.        
  170.         static IEnumerable<Rectangle> GetFacePositions(string path) {
  171.             var req = WebRequest.Create("https://westeurope.api.cognitive.microsoft.com/face/v1.0/detect");
  172.             req.Method = "POST";
  173.             req.ContentType = "application/octet-stream";
  174.             req.Headers["Ocp-Apim-Subscription-Key"] = "some_key";
  175.            
  176.             using (var stream = req.GetRequestStream())
  177.             using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
  178.                 fs.CopyTo(stream);
  179.  
  180.             var res = req.GetResponse();
  181.  
  182.             var resStream = res.GetResponseStream();
  183.             if (resStream == null) yield break;
  184.  
  185.             using (var sr = new StreamReader(resStream, Encoding.UTF8)) {
  186.                 if (JsonValue.Parse(sr.ReadToEnd()) is not JsonArray json) yield break;
  187.                 foreach (var face in json.OfType<JsonObject>()) {
  188.                     if (face["faceRectangle"] is not JsonObject faceRectangle) continue;
  189.  
  190.                     yield return new Rectangle(faceRectangle["left"], faceRectangle["top"], faceRectangle["width"],
  191.                         faceRectangle["height"]);
  192.                 }
  193.             }
  194.         }
  195.     }
  196. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement