2021-10-03 17:43:59 +00:00
|
|
|
|
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;
|
2021-10-06 11:57:50 +00:00
|
|
|
|
button2.DownImage = button2.OverImage = UIResource.cog;
|
|
|
|
|
button3.DefaultImage = UIResource.refresh2;
|
|
|
|
|
button3.DownImage = button3.OverImage = UIResource.refresh;
|
2021-10-03 17:43:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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<string> 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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-06 11:57:50 +00:00
|
|
|
|
private async void button3_MouseClick(object sender, MouseEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
await ReadVideoFile(textBox1.Text);
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-03 17:43:59 +00:00
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2021-10-06 11:57:50 +00:00
|
|
|
|
textBox1.Text = string.Empty;
|
2021-10-03 17:43:59 +00:00
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-06 11:57:50 +00:00
|
|
|
|
//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;
|
|
|
|
|
//}
|
|
|
|
|
|
2021-10-03 17:43:59 +00:00
|
|
|
|
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;
|
|
|
|
|
|
2021-10-06 11:57:50 +00:00
|
|
|
|
textBox1.Text = videoFilename;
|
2021-10-03 17:43:59 +00:00
|
|
|
|
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);
|
2021-10-06 11:57:50 +00:00
|
|
|
|
string thumbnailFilename = Path.ChangeExtension(Path.GetTempFileName(), "jpg");
|
2021-10-03 17:43:59 +00:00
|
|
|
|
|
|
|
|
|
ConversionOptions options = new ConversionOptions
|
|
|
|
|
{
|
|
|
|
|
Seek = ts,
|
|
|
|
|
CustomWidth = thumbnailWidth,
|
|
|
|
|
CustomHeight = thumbnailHeight
|
|
|
|
|
};
|
2021-10-06 11:57:50 +00:00
|
|
|
|
engine.GetThumbnail(inputFile, new MediaFile { Filename = thumbnailFilename }, options);
|
2021-10-03 17:43:59 +00:00
|
|
|
|
|
2021-10-06 11:57:50 +00:00
|
|
|
|
PictureBox imageBox = CreatePictureBox(thumbnailFilename, thumbnailWidth, thumbnailHeight);
|
2021-10-03 17:43:59 +00:00
|
|
|
|
ThreadControl.Add(flowLayoutPanel1, imageBox);
|
|
|
|
|
|
|
|
|
|
Label label = CreateLabel(ts);
|
|
|
|
|
ThreadControl.Add(flowLayoutPanel1, label);
|
|
|
|
|
|
|
|
|
|
// clean-up
|
2021-10-06 11:57:50 +00:00
|
|
|
|
DeleteFile(thumbnailFilename);
|
2021-10-03 17:43:59 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.IsBusy = false;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|