using MediaToolkit; using MediaToolkit.Model; using MediaToolkit.Options; using RyzStudio.Windows.Forms; using System; using System.Drawing; using System.IO; using System.Threading.Tasks; using System.Windows.Forms; namespace VideoPreview { public partial class MainForm : Form { protected readonly Random randy; protected OptionsForm optionsForm = null; protected bool isBusy = false; protected string videoFilename = null; protected TimeSpan videoDuration = TimeSpan.FromSeconds(0); public MainForm() { InitializeComponent(); randy = new Random(); textBox1.InnerTextBox.ReadOnly = true; textBox1.InnerTextBox.BackColor = Color.White; textBox1.InnerTextBox.TextChanged += textBox1_TextChanged; button2.DefaultImage = UIResource.cog2; button2.DownImage = button2.OverImage = UIResource.cog; button3.DefaultImage = UIResource.refresh2; button3.DownImage = button3.OverImage = UIResource.refresh; } protected override void OnFormClosing(FormClosingEventArgs e) { if (this.IsBusy) { e.Cancel = true; return; } base.OnFormClosing(e); } public bool IsBusy { get => isBusy; set { isBusy = value; ThreadControl.SetValue(pictureBox1, (isBusy ? AppResource.loading_block : null)); ThreadControl.SetEnable(textBox1, !isBusy); ThreadControl.SetEnable(button1, !isBusy); ThreadControl.SetEnable(button2, !isBusy); } } //private void button1_Click(object sender, EventArgs e) //{ // //string searchPattern = "*.avi|*.mp4|*.ogm|*.mkv"; // //string[] parts = searchPattern.Split(',', ';', '|'); // //var inputFile = new MediaFile { Filename = videoFilename }; // ////var outputFile = new MediaFile { Filename = @"N:\#\invincible.2021.s01e02.here.goes.nothing.720p.webrip.hevc.x265.mkv.jpg" }; // //using (var engine = new Engine()) // //{ // // engine.GetMetadata(inputFile); // // // Saves the frame located on the 15th second of the video. // // var options = new ConversionOptions { Seek = TimeSpan.FromSeconds(150) }; // // engine.GetThumbnail(inputFile, outputFile, options); // //} // //int i = 0; // //FFmpegLoader.FFmpegPath = @"L:\repos\WinFormsApp1\bin\Debug\net5.0-windows"; // //MediaFile file = MediaFile.Open(@"N:\#\invincible.2021.s01e03.who.you.calling.ugly.720p.webrip.hevc.x265.mkv"); // //FFMediaToolkit.Graphics.ImageData img; // //if (file.Video.TryGetNextFrame(out img)) // //{ // // //img..ToBitmap() // //} // //while (file.Video.TryGetNextFrame(out var imageData)) // //{ // // imageData.ToBitmap().Save($@"C:\images\frame_{i++}.png"); // // // See the #Usage details for example .ToBitmap() implementation // // // The .Save() method may be different depending on your graphics library // //} // //MessageBox.Show("!"); //} //private async void button2_Click(object sender, EventArgs e) //{ // //await Task.Run(() => // //{ // // if (string.IsNullOrWhiteSpace(textBox1.Text)) return; // // if (!Directory.Exists(textBox1.Text)) return; // // ThreadControl.Clear(richTextBox1); // // //string[] extensionFilters = new string[] { ".avi", ".mp4", ".ogm", ".mkv" }; // // ThreadControl.SetText(textBox1, @"C:\Windows"); // // List fileList = RyzStudio.IO.SmarterFileSystem.GetFiles(textBox1.Text, "*.avi|*.mp4|*.ogm|*.mkv", SearchOption.AllDirectories); // // //string[] fileList = Directory.GetFiles(textBox1.Text, "*.avi|*.mp4|*.ogm|*.mkv", SearchOption.TopDirectoryOnly); // // foreach (string item in fileList) // // { // // ThreadControl.AddLine(richTextBox1, item); // // //if (IsMatchExtension(item, extensionFilters)) // // //{ // // // ThreadControl.AddLine(richTextBox1, item); // // //} // // } // // MessageBox.Show("!"); // //}); //} //private bool IsMatchExtension(string filename, string[] extensionFilters) //{ // string ext = Path.GetExtension(filename)?.ToLower(); // foreach (var item in extensionFilters) // { // if (ext.Equals(item)) // { // return true; // } // } // return false; //} //private string[] Split(string lines) //{ // string[] rs = new string[0]; // foreach (string item in lines.Split(',', ';', '|')) // { // if (string.IsNullOrWhiteSpace(item)) // { // continue; // } // Array.Resize(ref rs, (rs.Length + 1)); // rs[(rs.Length - 1)] = item?.Trim(); // } // return rs; //} private void Form1_DragOver(object sender, DragEventArgs e) { e.Effect = (e.Data.GetDataPresent(DataFormats.FileDrop) ? DragDropEffects.Copy : DragDropEffects.None); } private async void Form1_DragDrop(object sender, DragEventArgs e) { string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[]; if (fileList == null) { return; } if (fileList.Length <= 0) { return; } await ReadVideoFile(fileList[0]); } private async void textBox1_TextChanged(object sender, EventArgs e) { await ReadVideoFile(textBox1.Text); } public AppSession CurrentSession { get; set; } = new AppSession(); private void button1_MouseClick(object sender, MouseEventArgs e) { this.Close(); } private void button2_MouseClick(object sender, MouseEventArgs e) { if (this.IsBusy) { return; } if (optionsForm == null) optionsForm = new OptionsForm(this.CurrentSession); if (optionsForm.ShowDialog() == DialogResult.OK) { this.CurrentSession = optionsForm.Session; this.TopMost = this.CurrentSession.AlwaysOnTop; } } private async void button3_MouseClick(object sender, MouseEventArgs e) { await ReadVideoFile(textBox1.Text); } protected TimeSpan CalcRandomTimeSpan(TimeSpan duration) { int mm = randy.Next(0, (int)Math.Floor(duration.TotalMinutes)); int ss = randy.Next(0, duration.Seconds); return new TimeSpan(0, mm, ss); } protected void Clear() { videoFilename = null; videoDuration = TimeSpan.FromSeconds(0); textBox1.Text = string.Empty; ThreadControl.SetText(label5, "-"); ThreadControl.SetText(label7, "-"); ThreadControl.SetText(label2, "-"); ThreadControl.Clear(flowLayoutPanel1); } protected Label CreateLabel(TimeSpan duration) { Label label = new Label(); label.Padding = new Padding(0); label.Margin = new Padding(0, 0, 0, 10); label.Text = string.Format("{0}h {1}m {2}s", duration.Hours, duration.Minutes, duration.Seconds); return label; } protected PictureBox CreatePictureBox(string filename, int width, int height) { PictureBox imageBox = new PictureBox() { BackColor = Color.White, Margin = new Padding(0, 0, 0, 0), Padding = new Padding(0), SizeMode = PictureBoxSizeMode.Zoom, Width = width, Height = height, }; imageBox.Load(filename); return imageBox; } protected void DeleteFile(string filename) { try { File.Delete(filename); } catch { // do nothing } } //protected string GetTempFolder() //{ // string path = Path.Combine(Application.StartupPath, "tmp"); // if (Directory.Exists(path)) // { // return path; // } // try // { // Directory.CreateDirectory(path); // } // catch // { // // do nothing // } // if (Directory.Exists(path)) // { // return path; // } // path = Path.GetTempPath(); // if (Directory.Exists(path)) // { // return path; // } // return null; //} protected decimal ParseFrameSizeRatio(string videoSize) { if (string.IsNullOrWhiteSpace(videoSize)) { return 0; } string[] parts = videoSize.Trim().Split("x"); if (parts.Length != 2) { return 0; } int w; if (!int.TryParse(parts[0], out w)) { return 0; } int h; if (!int.TryParse(parts[1], out h)) { return 0; } try { return decimal.Divide(w, h); } catch { return 0; } } protected async Task ReadVideoFile(string filename) { await Task.Run(() => { if (this.IsBusy) { return; } this.IsBusy = true; Clear(); MediaFile inputFile = new MediaFile { Filename = filename }; using (Engine engine = new Engine()) { try { engine.GetMetadata(inputFile); } catch (Exception exc) { MessageBox.Show(exc.Message); this.IsBusy = false; return; } } videoFilename = filename; videoDuration = inputFile.Metadata.Duration; textBox1.Text = videoFilename; ThreadControl.SetText(label5, inputFile.Metadata.VideoData.Format ?? string.Empty); ThreadControl.SetText(label7, (inputFile.Metadata.VideoData.FrameSize ?? string.Empty) + " @ " + inputFile.Metadata.VideoData.Fps.ToString() + "FPS"); ThreadControl.SetText(label2, string.Format("{0}h {1}m {2}s", videoDuration.Hours, videoDuration.Minutes, videoDuration.Seconds)); // calculate frame dimensions ratio decimal frameRatio = ParseFrameSizeRatio(inputFile.Metadata.VideoData.FrameSize); if (frameRatio <= 0) { this.IsBusy = false; return; } int thumbnailWidth = flowLayoutPanel1.ClientSize.Width - flowLayoutPanel1.Padding.Horizontal - SystemInformation.VerticalScrollBarWidth; int thumbnailHeight = (int)Math.Round(decimal.Divide((decimal)thumbnailWidth, frameRatio)); using (Engine engine = new Engine()) { for (int i = 0; i < this.CurrentSession.NoFrames; i++) { TimeSpan ts = CalcRandomTimeSpan(videoDuration); string thumbnailFilename = Path.ChangeExtension(Path.GetTempFileName(), "jpg"); ConversionOptions options = new ConversionOptions { Seek = ts, CustomWidth = thumbnailWidth, CustomHeight = thumbnailHeight }; engine.GetThumbnail(inputFile, new MediaFile { Filename = thumbnailFilename }, options); PictureBox imageBox = CreatePictureBox(thumbnailFilename, thumbnailWidth, thumbnailHeight); ThreadControl.Add(flowLayoutPanel1, imageBox); Label label = CreateLabel(ts); ThreadControl.Add(flowLayoutPanel1, label); // clean-up DeleteFile(thumbnailFilename); } } this.IsBusy = false; }); } } }