diff --git a/SimpleFFmpegGUI.WPF/App.xaml.cs b/SimpleFFmpegGUI.WPF/App.xaml.cs index ab43bde..caf5909 100644 --- a/SimpleFFmpegGUI.WPF/App.xaml.cs +++ b/SimpleFFmpegGUI.WPF/App.xaml.cs @@ -57,9 +57,26 @@ protected override void OnStartup(StartupEventArgs e) ConfigureServices(serviceCollection); ServiceProvider = serviceCollection.BuildServiceProvider(); - ServiceProvider.GetService(); - MainWindow = ServiceProvider.GetService(); - MainWindow.Show(); + if (e.Args.Length > 1) + { + if (e.Args[0] == "cut") + { + MainWindow = new CutWindow(new CutWindowViewModel(), e.Args[2..]); + WindowInteropHelper helper = new WindowInteropHelper(MainWindow); + helper.Owner = IntPtr.Parse(e.Args[1]); + MainWindow.ShowDialog(); + } + else + { + throw new ArgumentException("未知参数:" + e.Args[0]); + } + } + else + { + ServiceProvider.GetService(); + MainWindow = ServiceProvider.GetService(); + MainWindow.Show(); + } } private void ConfigureServices(IServiceCollection services) @@ -73,9 +90,6 @@ private void ConfigureServices(IServiceCollection services) services.AddSingleton(); services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); services.AddTransient(); diff --git a/SimpleFFmpegGUI.WPF/CutWindow.xaml.cs b/SimpleFFmpegGUI.WPF/CutWindow.xaml.cs index fe4a489..c0d2feb 100644 --- a/SimpleFFmpegGUI.WPF/CutWindow.xaml.cs +++ b/SimpleFFmpegGUI.WPF/CutWindow.xaml.cs @@ -37,27 +37,92 @@ namespace SimpleFFmpegGUI.WPF { - public static class AsyncEventExtension + public class CutWindowViewModel : INotifyPropertyChanged { - public static Task WaitForEventAsync(this object obj, string eventName) + public CutWindowViewModel() { - var e = obj.GetType().GetEvent(eventName); - if (e == null) + } + + public event PropertyChangedEventHandler PropertyChanged; + + private double currentP; + + public double CurrentP + { + get => currentP; + set { - throw new ArgumentException($"找不到事件{eventName}"); + current = Length * value; + this.SetValueAndNotify(ref currentP, value, nameof(CurrentP), nameof(Current)); } - TaskCompletionSource tcs = new TaskCompletionSource(); - EventHandler handler = null; - handler = new EventHandler(Finish); - e.AddEventHandler(obj, handler); - return tcs.Task; + } - void Finish(object sender, EventArgs a) + private TimeSpan current = TimeSpan.Zero; + + public TimeSpan Current + { + get => current; + set { - e.RemoveEventHandler(obj, handler); - tcs.SetResult(); + currentP = value / Length; + this.SetValueAndNotify(ref current, value, nameof(Current), nameof(CurrentP)); } } + + public double FromP => From / Length; + public double ToP => To / Length; + + private TimeSpan from = TimeSpan.Zero; + + public TimeSpan From + { + get => from; + set => this.SetValueAndNotify(ref from, value, nameof(From), nameof(FromP)); + } + + private TimeSpan to = TimeSpan.Zero; + + public TimeSpan To + { + get => to; + set => this.SetValueAndNotify(ref to, value, nameof(To), nameof(ToP)); + } + + private string filePath; + + public string FilePath + { + get => filePath; + set => this.SetValueAndNotify(ref filePath, value, nameof(FilePath)); + } + + private TimeSpan length; + + public TimeSpan Length + { + get => length; + set + { + to = value; + this.SetValueAndNotify(ref length, value, nameof(Length), nameof(To), nameof(FromP), nameof(ToP)); + } + } + + private bool isBarEnabled = true; + + public bool IsBarEnabled + { + get => isBarEnabled; + set => this.SetValueAndNotify(ref isBarEnabled, value, nameof(IsBarEnabled)); + } + + private long frame; + + public long Frame + { + get => frame; + set => this.SetValueAndNotify(ref frame, value, nameof(Frame)); + } } /// @@ -65,12 +130,15 @@ void Finish(object sender, EventArgs a) /// public partial class CutWindow : Window { + private readonly string[] args; - public CutWindow(CutWindowViewModel viewModel) + public CutWindowViewModel ViewModel { get; set; } + + public CutWindow(CutWindowViewModel viewModel, string[] args) { InitializeComponent(); ViewModel = viewModel; - + this.args = args; DataContext = ViewModel; ViewModel.PropertyChanged += ViewModel_PropertyChanged; Unloaded += (s, e) => media.Close(); @@ -79,41 +147,24 @@ public CutWindow(CutWindowViewModel viewModel) if (e.MessageType == Unosquare.FFME.Common.MediaLogMessageType.Error) { await Dispatcher.Invoke(async () => - { - await CommonDialog.ShowErrorDialogAsync("加载视频失败", e.Message); - Close(); - }); + { + await CommonDialog.ShowErrorDialogAsync("加载视频失败", e.Message); + Close(); + }); } Debug.WriteLine(e.Message); }; } - public string FileName { get; private set; } - - public CutWindowViewModel ViewModel { get; set; } - - public void Initialize(string fileName, TimeSpan? from, TimeSpan? to) - { - FileName = fileName; - if (from.HasValue) - { - ViewModel.From = from.Value; - } - if (to.HasValue) - { - ViewModel.To = to.Value; - } - } - - public async Task SetVideoAsync() + public async Task SetVideoAsync(string path, TimeSpan? from, TimeSpan? to) { MediaInfoGeneral mediaInfo; - ViewModel.FilePath = FileName; + ViewModel.FilePath = path; try { - mediaInfo = await MediaInfoManager.GetMediaInfoAsync(FileName); + mediaInfo = await MediaInfoManager.GetMediaInfoAsync(path); } catch (Exception ex) { @@ -124,7 +175,41 @@ public async Task SetVideoAsync() throw new Exception("文件没有视频流"); } ViewModel.Length = mediaInfo.Duration; - await media.Open(new Uri(FileName)); + if (from.HasValue) + { + ViewModel.From = from.Value; + } + if (to.HasValue) + { + ViewModel.To = to.Value; + } + //fps = mediaInfo.VideoStreams[0].AvgFrameRate; + + var r = await media.Open(new Uri(path)); + } + + private void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + switch (e.PropertyName) + { + case nameof(ViewModel.CurrentP): + + break; + } + } + + private void Button_Click(object sender, RoutedEventArgs e) + { + } + + private async void PauseButton_Click(object sender, RoutedEventArgs e) + { + await media.Pause(); + } + + private async void PlayButton_Click(object sender, RoutedEventArgs e) + { + await media.Play(); } protected override async void OnPreviewKeyDown(KeyEventArgs e) @@ -153,12 +238,55 @@ protected override async void OnPreviewKeyDown(KeyEventArgs e) } } + private void JumpToFrom_Click(object sender, RoutedEventArgs e) + { + ViewModel.Current = ViewModel.From; + } + + private void JumpToTo_Click(object sender, RoutedEventArgs e) + { + ViewModel.Current = ViewModel.To; + } + + private void SetFrom_Click(object sender, RoutedEventArgs e) + { + if (ViewModel.Current >= ViewModel.To) + { + this.CreateMessage().QueueError("开始时间不可晚于结束时间"); + return; + } + ViewModel.From = ViewModel.Current; + this.CreateMessage().QueueSuccess("已将开始时间设置为" + ViewModel.From.ToString(FindResource("TimeSpanFormat") as string)); + } + + private void SetTo_Click(object sender, RoutedEventArgs e) + { + if (ViewModel.Current <= ViewModel.From) + { + this.CreateMessage().QueueError("结束时间不可早于开始时间"); + return; + } + ViewModel.To = ViewModel.Current; + this.CreateMessage().QueueSuccess("已将结束时间设置为" + ViewModel.To.ToString(FindResource("TimeSpanFormat") as string)); + } + + private void Slider_PreviewKeyDown(object sender, KeyEventArgs e) + { + e.Handled = true; + } + + private void OKButton_Click(object sender, RoutedEventArgs e) + { + Console.Write("{0},{1}", ViewModel.From, ViewModel.To); + Application.Current.Shutdown(); + } + private void CancelButton_Click(object sender, RoutedEventArgs e) { - DialogResult = false; - Close(); + Application.Current.Shutdown(); } + private async void JumpButton_Click(object sender, RoutedEventArgs e) { bool shift = Keyboard.Modifiers.HasFlag(ModifierKeys.Shift); @@ -193,177 +321,86 @@ private async void JumpButton_Click(object sender, RoutedEventArgs e) } } - private void JumpToFrom_Click(object sender, RoutedEventArgs e) - { - ViewModel.Current = ViewModel.From; - } - - private void JumpToTo_Click(object sender, RoutedEventArgs e) - { - ViewModel.Current = ViewModel.To; - } - private void Media_RenderingVideo(object sender, Unosquare.FFME.Common.RenderingVideoEventArgs e) { ViewModel.Frame = e.PictureNumber; } - private void OKButton_Click(object sender, RoutedEventArgs e) - { - DialogResult = true; - Close(); - } - - private async void PauseButton_Click(object sender, RoutedEventArgs e) - { - await media.Pause(); - } - - private async void PlayButton_Click(object sender, RoutedEventArgs e) - { - await media.Play(); - } - - private void SetFrom_Click(object sender, RoutedEventArgs e) + private async void Window_Loaded(object sender, RoutedEventArgs e) { - if (ViewModel.Current >= ViewModel.To) + if (args.Length != 3) { - this.CreateMessage().QueueError("开始时间不可晚于结束时间"); + await CommonDialog.ShowErrorDialogAsync("参数不全"); + Application.Current.Shutdown(); return; } - ViewModel.From = ViewModel.Current; - this.CreateMessage().QueueSuccess("已将开始时间设置为" + ViewModel.From.ToString(FindResource("TimeSpanFormat") as string)); - } - - private void SetTo_Click(object sender, RoutedEventArgs e) - { - if (ViewModel.Current <= ViewModel.From) + if (!File.Exists(args[0])) { - this.CreateMessage().QueueError("结束时间不可早于开始时间"); + await CommonDialog.ShowErrorDialogAsync("文件不存在"); + Application.Current.Shutdown(); return; } - ViewModel.To = ViewModel.Current; - this.CreateMessage().QueueSuccess("已将结束时间设置为" + ViewModel.To.ToString(FindResource("TimeSpanFormat") as string)); - } - - private void Slider_PreviewKeyDown(object sender, KeyEventArgs e) - { - e.Handled = true; - } - - private void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e) - { - switch (e.PropertyName) + TimeSpan? from = null; + TimeSpan? to = null; + if (args[1] != "-") { - case nameof(ViewModel.CurrentP): - - break; + if (TimeSpan.TryParse(args[1], out TimeSpan fromValue)) + { + from = fromValue; + } + else + { + await CommonDialog.ShowErrorDialogAsync("无法解析开始时间"); + Application.Current.Shutdown(); + return; + } } - } - private async void Window_Loaded(object sender, RoutedEventArgs e) - { - if (!File.Exists(FileName)) + if (args[1] != "-") { - await CommonDialog.ShowErrorDialogAsync("文件不存在"); - Close(); - return; + if (TimeSpan.TryParse(args[2], out TimeSpan toValue)) + { + to = toValue; + } + else + { + await CommonDialog.ShowErrorDialogAsync("无法解析结束时间"); + Application.Current.Shutdown(); + return; + } } try { - await SetVideoAsync(); + await SetVideoAsync(args[0], from, to); } catch (Exception ex) { await CommonDialog.ShowErrorDialogAsync(ex, "加载视频失败"); - Close(); + Application.Current.Shutdown(); return; } } } - public class CutWindowViewModel : INotifyPropertyChanged + public static class AsyncEventExtension { - private TimeSpan current = TimeSpan.Zero; - - private double currentP; - - private string filePath; - - private long frame; - - private TimeSpan from = TimeSpan.Zero; - - private bool isBarEnabled = true; - - private TimeSpan length; - - private TimeSpan to = TimeSpan.Zero; - - public CutWindowViewModel() - { - } - - public event PropertyChangedEventHandler PropertyChanged; - public TimeSpan Current - { - get => current; - set - { - currentP = value / Length; - this.SetValueAndNotify(ref current, value, nameof(Current), nameof(CurrentP)); - } - } - - public double CurrentP + public static Task WaitForEventAsync(this object obj, string eventName) { - get => currentP; - set + var e = obj.GetType().GetEvent(eventName); + if (e == null) { - current = Length * value; - this.SetValueAndNotify(ref currentP, value, nameof(CurrentP), nameof(Current)); + throw new ArgumentException($"找不到事件{eventName}"); } - } - public string FilePath - { - get => filePath; - set => this.SetValueAndNotify(ref filePath, value, nameof(FilePath)); - } - - public long Frame - { - get => frame; - set => this.SetValueAndNotify(ref frame, value, nameof(Frame)); - } - - public TimeSpan From - { - get => from; - set => this.SetValueAndNotify(ref from, value, nameof(From), nameof(FromP)); - } - - public double FromP => From / Length; - public bool IsBarEnabled - { - get => isBarEnabled; - set => this.SetValueAndNotify(ref isBarEnabled, value, nameof(IsBarEnabled)); - } + TaskCompletionSource tcs = new TaskCompletionSource(); + EventHandler handler = null; + handler = new EventHandler(Finish); + e.AddEventHandler(obj, handler); + return tcs.Task; - public TimeSpan Length - { - get => length; - set + void Finish(object sender, EventArgs a) { - to = value; - this.SetValueAndNotify(ref length, value, nameof(Length), nameof(To), nameof(FromP), nameof(ToP)); + e.RemoveEventHandler(obj, handler); + tcs.SetResult(); } } - - public TimeSpan To - { - get => to; - set => this.SetValueAndNotify(ref to, value, nameof(To), nameof(ToP)); - } - - public double ToP => To / Length; } } \ No newline at end of file diff --git a/SimpleFFmpegGUI.WPF/Panels/FileIOPanel.xaml.cs b/SimpleFFmpegGUI.WPF/Panels/FileIOPanel.xaml.cs index d3564a0..160e605 100644 --- a/SimpleFFmpegGUI.WPF/Panels/FileIOPanel.xaml.cs +++ b/SimpleFFmpegGUI.WPF/Panels/FileIOPanel.xaml.cs @@ -435,16 +435,40 @@ private async void ClipButton_Click(object sender, RoutedEventArgs e) return; } this.GetWindow().IsEnabled = false; - - var cut = App.ServiceProvider.GetService(); - cut.Initialize(input.FilePath, input.From, input.To); - if (cut.ShowDialog()==true) + (TimeSpan From, TimeSpan To)? result = null; + Process p = new Process() + { + StartInfo = new ProcessStartInfo() + { + FileName = FzLib.Program.App.ProgramFilePath, + RedirectStandardOutput = true, + } + }; + p.StartInfo.ArgumentList.Add("cut"); + p.StartInfo.ArgumentList.Add(new WindowInteropHelper(this.GetWindow()).Handle.ToString()); + p.StartInfo.ArgumentList.Add(input.FilePath); + p.StartInfo.ArgumentList.Add(input.From.HasValue ? input.From.Value.ToString() : "-"); + p.StartInfo.ArgumentList.Add(input.To.HasValue ? input.To.Value.ToString() : "-"); + p.Start(); + var output = await p.StandardOutput.ReadToEndAsync(); + string[] outputs = output.Split(','); + if (outputs.Length == 2) + { + if (TimeSpan.TryParse(outputs[0], out TimeSpan from)) + { + if (TimeSpan.TryParse(outputs[1], out TimeSpan to)) + { + result = (from, to); + } + } + } + if (result.HasValue) { - input.From = cut.ViewModel.From; - input.To = cut.ViewModel.To; + var time = result.Value; + input.From = time.From; + input.To = time.To; input.Duration = null; } - } catch (Exception ex) { diff --git "a/\346\227\245\345\277\227.md" "b/\346\227\245\345\277\227.md" index 05b4c47..1c49ee6 100644 --- "a/\346\227\245\345\277\227.md" +++ "b/\346\227\245\345\277\227.md" @@ -679,4 +679,6 @@ 【Core】【WPF】新增处理后删除输入文件的功能 -【Core】修复了最新版本ffmpeg因输出状态改变导致部分场景(如复制流)下无法获取进度的BUG \ No newline at end of file +【Core】修复了最新版本ffmpeg因输出状态改变导致部分场景(如复制流)下无法获取进度的BUG + +【WPF】由于发现裁剪闪退问题为解决,因此回退了[cc72816](https://github.com/autodotua/RemoteFFmpegGUI/commit/cc7281699db1d342262676efa8abeb4c92a19a72) \ No newline at end of file