C# WPF如何将文件夹PNG转JPG、按25FPS播放并生成视频?
解决方案
问题1:JPG无法正常加载修复
WPF的BitmapImage原生支持JPG格式,之前加载失败是直接用Uri加载时存在文件资源锁定、特殊路径识别异常的问题,改用流加载的方式即可解决,无需手动提前转PNG格式。
问题2:25FPS顺序播放修复
原代码中for循环在UI线程同步执行,执行速度远快于UI刷新速度,导致中间帧全部被跳过仅渲染最后一帧。改用DispatcherTimer按25FPS对应间隔(40毫秒)切换图片即可实现顺序播放效果。
问题3:图片序列转视频实现
通过调用FFmpeg命令行实现图片序列合成25FPS视频,稳定性高兼容性好,只需将FFmpeg.exe放到程序运行目录即可,无需引用复杂第三方库。如果需要支持帧编辑,只需修改图片序列数组的内容(增删、调整顺序)后再调用播放或生成视频逻辑即可。
完整修改后代码
using System; using System.IO; using System.Linq; using System.Windows; using System.Windows.Threading; using System.Windows.Media.Imaging; using System.Diagnostics; namespace WpfApp2 { public partial class MainWindow : Window { public static string WorkingFolder { get; set; } private DispatcherTimer _playTimer; private string[] _imageFrames; private int _currentFrameIndex; public MainWindow() { InitializeComponent(); // 初始化25FPS播放计时器 _playTimer = new DispatcherTimer(); _playTimer.Interval = TimeSpan.FromMilliseconds(40); _playTimer.Tick += PlayTimer_Tick; } private void PlayTimer_Tick(object sender, EventArgs e) { if (_imageFrames == null || _currentFrameIndex >= _imageFrames.Length) { _playTimer.Stop(); // 播放完成后可自行添加循环播放逻辑 return; } UpdateImage(_imageFrames[_currentFrameIndex]); _currentFrameIndex++; } public void UpdateImage(string imagePath) { // 流加载兼容JPG/PNG等格式,避免文件锁定 using (var fs = new FileStream(imagePath, FileMode.Open, FileAccess.Read)) { var bitmap = new BitmapImage(); bitmap.BeginInit(); bitmap.CacheOption = BitmapCacheOption.OnLoad; bitmap.StreamSource = fs; bitmap.EndInit(); bitmap.Freeze(); ImportImage.Source = bitmap; } } public void FileDropStackPanel_Drop(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) { string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); WorkingFolder = Path.GetFullPath(files[0]); LoadImageSequence(); } } public void LoadImageSequence() { string filesTxtPath = Path.Combine(WorkingFolder, "files.txt"); if (File.Exists(filesTxtPath)) { string[] lines = File.ReadAllLines(filesTxtPath); // 组装所有图片完整路径 _imageFrames = lines.Select(line => Path.Combine(WorkingFolder, line.Trim())).Where(File.Exists).ToArray(); _currentFrameIndex = 0; // 启动序列播放 _playTimer.Start(); // 需要生成视频时调用下方方法,传入输出视频路径即可 // GenerateVideo(@"D:\output\test.mp4"); } } /// <summary> /// 图片序列生成25FPS视频方法 /// </summary> /// <param name="outputVideoPath">输出视频完整路径,如D:\test.mp4</param> public void GenerateVideo(string outputVideoPath) { if (_imageFrames == null || _imageFrames.Length == 0) return; string ffmpegArgs = $"-f concat -safe 0 -i \"{Path.Combine(WorkingFolder, "files.txt")}\" -r 25 -c:v libx264 -pix_fmt yuv420p \"{outputVideoPath}\""; using var process = new Process(); process.StartInfo.FileName = "ffmpeg.exe"; process.StartInfo.Arguments = ffmpegArgs; process.StartInfo.UseShellExecute = false; process.StartInfo.CreateNoWindow = true; process.Start(); process.WaitForExit(); } } }
注意事项
- 请确保界面中接收拖拽的
StackPanel的AllowDrop属性设置为True,否则拖拽事件不会触发 - 生成视频功能需提前将FFmpeg静态编译版的
ffmpeg.exe放置到程序运行目录即可使用 - 如需帧编辑功能,可直接对
_imageFrames数组做增删、排序操作后,再重启播放或调用生成视频方法即可生效
内容的提问来源于stack exchange,提问作者ChaseRatliff
相关产品推荐
相关产品推荐

