WPF 实现调用 ffmpeg 实现屏幕录制
框架使用.NET4
Visual Studio 2022
需要去 ffmpeg[2] 官网下载 Windows
解压进入 ffmpeg-4.1.1-win32-static\bin\
或者 下载 ffmpeg.exe[3] 拷贝到运行目录下的ffmpeg
文件夹下 DesktopRecord.exe
就可以进行录屏,结束录屏后视频保存在运行程序根目录下。
使用参数命令进行录屏 "-f gdigrab -framerate 30 -offset_x 0 -offset_y 0 -video_size 1920x1080 -i desktop -c:v libx264 -preset ultrafast -crf 0 " + DateTime.Now.ToString("yyyyMMddHHmmss") + "_DesktopRecord.mp4"
-f gdigrab
: 设定视频输入来源为Windows
桌面画面捕获;-framerate 30
: 设置帧率为30fps
;-offset_x 0 -offset_y 0
: 设置捕获起始坐标为(0, 0)
;-video_size 1920x1080
: 设置视频分辨率为1920x1080
;-i desktop
: 指示从桌面捕获视频流;-c:v libx264
: 使用libx264
编码器进行视频压缩;-preset ultrafast
: 设定视频压缩速度为最快;-crf 0
: 设置视频压缩质量无限制(CRF
为0
表示最高质量);" + DateTime.Now.ToString("yyyyMMddHHmmss") + "_DesktopRecord.mp4"
: 指定视频输出文件名为yyyyMMddHHmmss_DesktopRecord.mp4
。
实现代码
1)创建 FFmpegHelper.cs
代码如下:
using System; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; namespace DesktopRecord.Helper { public class FFmpegHelper { #region 模拟控制台信号需要使用的api [DllImport("kernel32.dll")] static extern bool GenerateConsoleCtrlEvent(int dwCtrlEvent, int dwProcessGroupId); [DllImport("kernel32.dll")] static extern bool SetConsoleCtrlHandler(IntPtr handlerRoutine, bool add); [DllImport("kernel32.dll")] static extern bool AttachConsole(int dwProcessId); [DllImport("kernel32.dll")] static extern bool FreeConsole(); #endregion // ffmpeg进程 static Process _process; // ffmpeg.exe实体文件路径 static string ffmpegPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ffmpeg.exe"); /// <summary> /// 功能: 开始录制 /// </summary> public static bool Start() { if(!File.Exists(ffmpegPath)) return false; var processInfo = new ProcessStartInfo { FileName = ffmpegPath, Arguments = "-f gdigrab -framerate 30 -offset_x 0 -offset_y 0 -video_size 1920x1080 -i desktop -c:v libx264 -preset ultrafast -crf 0 " + DateTime.Now.ToString("yyyyMMddHHmmss") + "_DesktopRecord.mp4", UseShellExecute = false, RedirectStandardInput = true, RedirectStandardOutput = true, CreateNoWindow = true }; _process = new Process { StartInfo = processInfo }; _process.Start(); return true; } /// <summary> /// 功能: 停止录制 /// </summary> public static void Stop() { if (_process == null) return; AttachConsole(_process.Id); SetConsoleCtrlHandler(IntPtr.Zero, true); GenerateConsoleCtrlEvent(0, 0); FreeConsole(); _process.StandardInput.Write("q"); if (!_process.WaitForExit(10000)) { _process.Kill(); } } } }
2)创建 MainWindow.xaml
代码如下:
<wd:Window x:Class="DesktopRecord.View.MainWindow" 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:vm="clr-namespace:DesktopRecord.ViewModel" xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers" Title="屏幕录制" Width="525" Height="200" Icon="/screen.ico" ResizeMode="CanMinimize" WindowStartupLocation="CenterScreen" mc:Ignorable="d"> <wd:Window.DataContext> <vm:MainVM /> </wd:Window.DataContext> <Grid> <TabControl> <TabItem Header="ffmpeg 录制"> <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal"> <Button Margin="0,0,5,0" Command="{Binding MyStart}" Content="{Binding MyTime}" Style="{StaticResource WD.SuccessPrimaryButton}" /> <Button Margin="5,0,0,0" Command="{Binding MyStop}" Content="停止录制" Style="{StaticResource WD.DangerPrimaryButton}" /> </StackPanel> </TabItem> </TabControl> </Grid> </wd:Window>
3)创建 MainVM.cs
代码如下:
using DesktopRecord.Helper; using System; using System.Diagnostics; using System.Threading.Tasks; using System.Windows.Input; using System.Windows.Threading; using WPFDevelopers.Controls; using WPFDevelopers.Helpers; namespace DesktopRecord.ViewModel { public class MainVM : ViewModelBase { private DispatcherTimer tm = new DispatcherTimer(); public int currentCount = 0; private string myTime = "开始录制"; public string MyTime { get { return myTime; } set { myTime = value; NotifyPropertyChange("MyTime"); } } private bool isStart = true; public bool IsStart { get { return isStart; } set { isStart = value; NotifyPropertyChange("IsStart"); } } private bool _isShow; public bool IsShow { get { return _isShow; } set { _isShow = value; NotifyPropertyChange("IsShow"); } } private ICommand myStart; public ICommand MyStart { get { return myStart ?? (myStart = new RelayCommand(p => { App.Current.MainWindow.WindowState = System.Windows.WindowState.Minimized; if (!FFmpegHelper.Start()) { App.Current.MainWindow.WindowState = System.Windows.WindowState.Normal; MessageBox.Show("未找到 【ffmpeg.exe】,请下载", "错误", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error); return; } tm.Tick += tm_Tick; tm.Interval = TimeSpan.FromSeconds(1); tm.Start(); IsStart = false; }, a => { return IsStart; })); } } private void tm_Tick(object sender, EventArgs e) { currentCount++; MyTime = "录制中(" + currentCount + "s)"; } /// <summary> /// 获取或设置 /// </summary> private ICommand myStop; /// <summary> /// 获取或设置 /// </summary> public ICommand MyStop { get { return myStop ?? (myStop = new RelayCommand(p => { var task = new Task(() => { FFmpegHelper.Stop(); MyTime = "开始录制"; tm.Stop(); currentCount = 0; IsShow = true; }); task.ContinueWith(previousTask => { IsShow = false; IsStart = true; Process.Start(AppDomain.CurrentDomain.BaseDirectory); }, TaskScheduler.FromCurrentSynchronizationContext()); task.Start(); }, a => { return !IsStart; })); } }
效果图
以上就是WPF调用ffmpeg实现屏幕录制的详细内容,更多关于WPF屏幕录制的资料请关注其它相关文章!