问题:在使用cmd窗口执行以上命令时(cmd中参数前面要加 ffmpeg 注意文件位置),可以成功处理,但在运行WPF测试的时候,发现只有一个大小为0kb的新文件生成,但迟迟不见处理。给人一种假死的现象。而当关掉调试的WPF程序时,过几秒钟,貌似ffmpeg.exe 又起作用了,文件处理成功了。这个不得其解.
原因:process.WaitForExit(); 这句执行会造成程序一直处于等待状态。于是,抱着试试看的态度,注释了这一句。当然,程序不再等待外部进程完成执行,proces.Close(); 这一句也要注释一下,测试结果成功!

<Application x:Class="VideoWatermark.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:VideoWatermark"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml"/>
                <ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>
<Window x:Class="VideoWatermark.MainWindow"
        xmlns:hc="https://handyorg.github.io/handycontrol"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:VideoWatermark"
        Icon="ico.ico"
        mc:Ignorable="d"
        ResizeMode="CanMinimize"
        Title="VideoWatermark" Height="500" Width="815">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="50"/>
            <RowDefinition Height="50"/>
            <RowDefinition Height="300"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="800"/>
        </Grid.ColumnDefinitions>

        <StackPanel Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
            <TextBox x:Name="VideosPathTextBox" Style="{StaticResource TextBoxExtend}" hc:InfoElement.TitlePlacement="Left" hc:InfoElement.Title="视频文件:" Width="600" VerticalAlignment="Center" IsEnabled="False"/>
            <Button Style="{StaticResource ButtonPrimary}" Width="85" Content="选择文件" Click="SelectVideoButton_Click"/>
        </StackPanel>
        <StackPanel Grid.Row="1" Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
            <TextBox x:Name="TxtWatermarkPath" Style="{StaticResource TextBoxExtend}" hc:InfoElement.TitlePlacement="Left" hc:InfoElement.Title="图片水印:" Width="600" VerticalAlignment="Center" IsEnabled="False"/>
            <Button  Style="{StaticResource ButtonPrimary}" Width="85"  Content="选择水印" Click="Button_WatermarkClick"/>
        </StackPanel>
        <StackPanel Grid.Row="2" Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
            <Button Style="{StaticResource ButtonPrimary}" Width="335"  Content="开始" Click="Button_AddWatermarkButton_Click" Margin="0,0,10,0"/>
            <Button Style="{StaticResource ButtonPrimary}" Width="335"  Content="清空" Click="Button_ClearList_Click"/>
        </StackPanel>

        <StackPanel Grid.Row="3" Grid.Column="0" Orientation="Vertical" VerticalAlignment="Top" HorizontalAlignment="Center">
            <ListView x:Name="VideosListView" ItemsSource="{Binding DataList}" >
                <ListView.View>
                    <GridView>
                        <GridViewColumn Width="80" Header="序号" DisplayMemberBinding="{Binding Index}"/>
                        <GridViewColumn Width="500" Header="名称" DisplayMemberBinding="{Binding Name}"/>
                        <GridViewColumn Width="80" Header="状态" DisplayMemberBinding="{Binding Remark}"/>
                    </GridView>
                </ListView.View>
            </ListView>
            <Border x:Name="NoDataBorder" Style="{StaticResource BorderRegion}" Visibility="Visible">
                <TextBlock Text="没有数据" Height="200" HorizontalAlignment="Center" Foreground="#000000"/>
            </Border>
        </StackPanel>
    </Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.IO;
using Microsoft.Win32;
using VideoWatermark.Models;
using System.Diagnostics;


namespace VideoWatermark
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public ObservableCollection<VideoItem> DataList { get; set; } = new ObservableCollection<VideoItem>();
        public MainWindow()
        {
            InitializeComponent();
            DataList = new ObservableCollection<VideoItem>(); // 初始化DataList
            DataContext = this;
        }

        private void SelectVideoButton_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog
            {
                Multiselect = true,
                Filter = "Video files (*.mp4;*.avi;*.wmv)|*.mp4;*.avi|All files (*.*)|*.*"
            };

            if (openFileDialog.ShowDialog() == true)
            {
                // 获取已在DataList中的文件名
                var existingFiles = DataList.Select(v => v.Name).ToList();

                // 将选中的文件路径添加到文本框,同时避免重复
                List<string> newFiles = new List<string>();
                int index = DataList.Count + 1; // 计算新的起始序号

                foreach (string fileName in openFileDialog.FileNames)
                {
                    string justFileName = Path.GetFileName(fileName);
                    if (!existingFiles.Contains(justFileName))
                    {
                        newFiles.Add(fileName);
                        // 只有当文件不在列表中时,才添加到DataList
                        DataList.Add(new VideoItem
                        {
                            Index = index++,
                            Name = justFileName,
                            Remark = "待处理"
                        });
                    }
                }

                // 更新文本框
                if (newFiles.Any())
                {
                    string existingText = VideosPathTextBox.Text;
                    if (!string.IsNullOrEmpty(existingText))
                    {
                        VideosPathTextBox.Text += ";";
                    }
                    VideosPathTextBox.Text += string.Join(";", newFiles);
                }
                UpdateNoDataVisibility();

                // 更新ListView
                VideosListView.ItemsSource = null;
                VideosListView.ItemsSource = DataList;
            }
        }

        private void Button_WatermarkClick(object sender, RoutedEventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "图片文件|*.png;*.jpg;*.jpeg|所有文件|*.*";

            if (openFileDialog.ShowDialog() == true)
            {
                TxtWatermarkPath.Text = openFileDialog.FileName;
            }
        }

        private void Button_ClearList_Click(object sender, RoutedEventArgs e)
        {
            DataList.Clear();
            VideosPathTextBox.Text = string.Empty;
            VideosListView.ItemsSource = null;
            VideosListView.ItemsSource = DataList;
            UpdateNoDataVisibility();
            HandyControl.Controls.MessageBox.Show(this, "列表已清空", "提示");
        }


        private async void Button_AddWatermarkButton_Click(object sender, RoutedEventArgs e)
        {
            string watermarkImage = TxtWatermarkPath.Text;
            string[] videoFiles = VideosPathTextBox.Text.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);

            // 检查是否导入了视频文件
            if (videoFiles.Length == 0)
            {
                HandyControl.Controls.MessageBox.Show(this, "请先导入视频文件!", "缺少视频");
                return;
            }

            // 检查是否导入了水印图片
            if (string.IsNullOrWhiteSpace(watermarkImage) || !File.Exists(watermarkImage))
            {
                HandyControl.Controls.MessageBox.Show(this, "请先导入水印图片!", "缺少水印");
                return;
            }


            foreach (string videoFile in videoFiles)
            {
                // 检查视频文件是否存在
                if (!File.Exists(videoFile))
                {
                    UpdateVideoItemStatus(Path.GetFileName(videoFile), "文件不存在");
                    continue; // 跳过不存在的文件
                }

                UpdateVideoItemStatus(Path.GetFileName(videoFile), "正在处理");

                await Task.Run(() => RunFFmpegProcess(videoFile, watermarkImage));

                // 更新视频状态为 "已完成"
                UpdateVideoItemStatus(Path.GetFileName(videoFile), "已完成");
            }

            HandyControl.Controls.MessageBox.Show(this, "所有添加水印操作完成!", "提示");
        }


        private void RunFFmpegProcess(string videoFile, string watermarkImage)
        {
            string outputVideo = Path.Combine(Path.GetDirectoryName(videoFile), "watermarked_" + Path.GetFileName(videoFile));
            // 在这里编写使用 FFmpeg 添加水印的代码
            string ffmpegArgs = $"-i \"{videoFile}\" -i \"{watermarkImage}\" -filter_complex \"overlay=x='mod(main_h/0.8*ceil(t),main_w)':y='mod(main_w/3*ceil(t/2),main_h)'\" \"{outputVideo}\"";
            // 请确保你已经正确配置 FFmpeg.AutoGen,并且有 FFmpeg 的可执行文件
            //string ffmpegPath = @"C:\Users\az102\ Visual Studio Source\repos\VideoWatermark\VideoWatermark\FFmpeg\ffmpeg.exe"; // 请根据实际路径配置 FFmpeg 可执行文件路径
            string ffmpegPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "FFmpeg", "ffmpeg.exe");

            Process process = new Process();
            process.StartInfo.FileName = ffmpegPath;
            process.StartInfo.Arguments = $"-i \"{videoFile}\" -i \"{watermarkImage}\" -filter_complex \"overlay=x='mod(main_h/0.8*ceil(t),main_w)':y='mod(main_w/3*ceil(t/2),main_h)'\" \"{outputVideo}\"";
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.CreateNoWindow = true;

            process.Start();
            process.WaitForExit();
            process.Close();

        }

        private void UpdateVideoItemStatus(string fileName, string status)
        {
            var videoItem = DataList.FirstOrDefault(v => v.Name == fileName);
            if (videoItem != null)
            {
                Application.Current.Dispatcher.Invoke(() =>
                {
                    videoItem.Remark = status;
                });
            }
        }

        private void UpdateNoDataVisibility()
        {
            if (DataList.Count > 0)
            {
                NoDataBorder.Visibility = Visibility.Collapsed;
            }
            else
            {
                NoDataBorder.Visibility = Visibility.Visible;
            }
        }

    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;

namespace VideoWatermark.Models
{
    public class VideoItem : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public int Index { get; set; }

        private string name;
        public string Name
        {
            get { return name; }
            set
            {
                name = value;
                OnPropertyChanged("Name");
            }
        }

        private string remark;
        public string Remark
        {
            get { return remark; }
            set
            {
                remark = value;
                OnPropertyChanged("Remark");
            }
        }

        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

标签: none

添加新评论