C# WinForm 播放图片,视频 ,调用外部程序(传值、返回值)
form1,
1.轮播图片
2.播放视频:3种
1.Vlc
2. WindowsMediaPlayer播放视频
3. ffplay
FFmpeg 开源、跨平台、体积小、功能强大,提供了录制、转换以及流化音视频的完整解决方案。
https://www.gyan.dev/ffmpeg/builds/
百科:https://baike.baidu.com/item/ffmpeg/2665727?fr=aladdin
给外部的程序传值:1.startInfo.Arguments = s;//parameters 2.标准输入值,process.StandardInput.WriteLine(s);

public partial class Form1 : Form { private CancellationTokenSource cts = new CancellationTokenSource(); private Task currentTask ; //ManualResetEvent resetEvent = new ManualResetEvent(true); #region 始终获取焦点 ////调用API //[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, ExactSpelling = true)] //public static extern IntPtr GetForegroundWindow(); //获得本窗体的句柄 //[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SetForegroundWindow")] //public static extern bool SetForegroundWindow(IntPtr hWnd);//设置此窗体为活动窗体 ////定义变量,句柄类型 //public IntPtr Handle1; #endregion public Form1() { InitializeComponent(); this.AutoScaleMode = AutoScaleMode.Inherit; //this.FormBorderStyle = FormBorderStyle.None; //设置窗体为无边框样式 //this.WindowState = FormWindowState.Maximized; //最大化窗体 //this.TopMost = true; //设置窗体置顶 //Handle1 = this.Handle; ////设置此窗体为活动窗体 //SetForegroundWindow(Handle1); } #region 轮播图片 /// <summary> /// 播放 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void btnCarousel_Click(object sender, EventArgs e) { this.picBox1.BackColor = Color.Green; var lstImg = await InitImage(); CancellationToken token = cts.Token; PlayImage(lstImg, token); //currentTask = new Task(async () => //{ // while (true) // { // await ShowImageAsync(lstImg); // } //}, token); //currentTask.Start(); } /// <summary> /// 播放图片 /// </summary> /// <param name="images"></param> /// <param name="token"></param> /// <returns></returns> private void PlayImage(List<Image> images, CancellationToken token) { currentTask = new Task(async () => { while (!cts.IsCancellationRequested) { //if (cts.IsCancellationRequested) //{ // Debug.WriteLine($"{DateTime.Now},退出播放图片:"); // break; //} Debug.WriteLine($"{DateTime.Now},准备播放图片:ManagedThreadId:{Thread.CurrentThread.ManagedThreadId}"); await ShowImageAsync(images); } Debug.WriteLine($"{DateTime.Now},退出播放图片:"); }, token); currentTask.Start(); } /// <summary> /// 初始化图片 /// </summary> /// <returns></returns> private async Task<List<Image>> InitImage() { List<Image> images = new List<Image>(); var strDir = System.AppDomain.CurrentDomain.BaseDirectory; string str2 = System.Environment.CurrentDirectory; string str3 = System.IO.Directory.GetCurrentDirectory();//不可靠 images.Add(Image.FromFile($"{strDir}/Image/a.jpeg")); images.Add(Image.FromFile($"{strDir}/Image/b.jpeg")); images.Add(Image.FromFile($"{strDir}/Image/c.jpeg")); //images.Add(Image.FromFile($"{strDir}/Image/m5506.mp4")); string[] arrFile = Directory.GetFileSystemEntries($"{System.AppDomain.CurrentDomain.BaseDirectory}/Image"); return await Task.FromResult(images); } /// <summary> /// 显示图片 /// </summary> /// <param name="images"></param> /// <returns></returns> private async Task ShowImageAsync(List<Image> images) { foreach (var img in images) { if (cts.IsCancellationRequested) { Debug.WriteLine($"{DateTime.Now},暂停图片:{images.IndexOf(img)}"); ; break ; } Debug.WriteLine($"{DateTime.Now},播放图片:{images.IndexOf(img)}"); await ChangeImageAsync(img, 2000); } } /// <summary> /// 变更图片 /// </summary> /// <param name="img"></param> /// <param name="milliseconds"></param> /// <returns></returns> private async Task ChangeImageAsync(Image img,int milliseconds = 2000) { this.picBox1.Image = img; this.picBox1.SizeMode = PictureBoxSizeMode.StretchImage; await Task.Delay(milliseconds); } /// <summary> /// 暂停 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnImgStop_Click(object sender, EventArgs e) { if (currentTask != null) { if (currentTask.IsCompleted || currentTask.Status == TaskStatus.RanToCompletion) { cts.Cancel(); Debug.WriteLine($"{DateTime.Now},图片暂停。"); } } } /// <summary> /// 继续 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void btnImgContinue_Click(object sender, EventArgs e) { var lstImg = await InitImage(); cts = new CancellationTokenSource(); PlayImage(lstImg, cts.Token); } #endregion #region 启动外部程序 /// <summary> /// 启动程序 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void btnExec_Click(object sender, EventArgs e) { var strExePath2 = $"{Application.StartupPath }"; Debug.WriteLine($"Application.StartupPath:{strExePath2}"); var strExePath = @"C:\Users\Administrator\Desktop\01文件夹\Solution1\WindowsFormsApp2\bin\Debug\WindowsFormsApp2.exe"; if (!File.Exists(strExePath)) { MessageBox.Show("程序不存在"); return; } var blnRes = false; if (txtParam.Text == "1") { var strffmpegPath = $"{System.AppDomain.CurrentDomain.BaseDirectory}\\Image\\ffmpeg.exe";//Path.GetDirectoryName(Application.ExecutablePath); var strffplayPath = $"{System.AppDomain.CurrentDomain.BaseDirectory}\\Image\\ffplay.exe";//Path.GetDirectoryName(Application.ExecutablePath); var strDirFile = $"{System.AppDomain.CurrentDomain.BaseDirectory}\\Image\\m5506.mp4"; //-fs 全屏模式启动,-autoexit 播完自动退出,-window_title 设置标题, -noborder 无边框窗口,-alwaysontop 窗口始终在顶部,-showmode 0 显示模式 '-loop number' 循环播放 "number" 次(0将一直循环) //var blnRes = ExecuteCommandSync("ffplay", $"-i -window_title 测试视频 -showmode 0 -alwaysontop {strDirFile}"); //ffplay放在当前运行目录下;-autoexit blnRes = await ExecuteCommandSync(strffplayPath, $"-i -window_title 测试视频 -showmode 0 -loop 0 {strDirFile}"); //await Task.Run(() => { blnRes = ExecuteCommandSync(strffplayPath, $"-i -window_title 测试视频 -showmode 0 -loop 0 {strDirFile}"); }); } else { blnRes = await ExecuteCommandSync(strExePath, $"{DateTime.Now},测试程序"); } if (blnRes) { Debug.WriteLine($"{DateTime.Now}:调用结束"); } else { Debug.WriteLine($"{DateTime.Now}:调用失败"); } } /// <summary> /// 关闭外部程序 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnExeClose_Click(object sender, EventArgs e) { var strffplayPath = $"{System.AppDomain.CurrentDomain.BaseDirectory}\\Image\\ffplay.exe"; var strExeName = Path.GetFileNameWithoutExtension(strffplayPath); ExecuteClose(strExeName); } /// <summary> /// 启动外部程序 /// </summary> /// <param name="filename"></param> /// <param name="args"></param> /// <returns></returns> /// <exception cref="Exception"></exception> public async Task<bool> ExecuteCommandSync(string filename,params string[] args) { string s = ""; foreach (string arg in args) { s = s + arg + " "; } s = s.Trim(); try { System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(); startInfo.ErrorDialog = false; startInfo.UseShellExecute = false; //不使用系统外壳程序启动进程 startInfo.RedirectStandardOutput = true; startInfo.RedirectStandardError = true; //把外部程序错误输出写到StandardError流中 startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Maximized; startInfo.CreateNoWindow = true; //不显示dos程序窗口 startInfo.FileName = filename;//exe file name startInfo.Arguments = s;//parameters startInfo.UseShellExecute = false; ////不使用操作系统外壳程序启动线程(一定为FALSE,详细的请看MSDN) System.Diagnostics.Process process = new System.Diagnostics.Process(); process.StartInfo = startInfo; //process.ErrorDataReceived += new DataReceivedEventHandler(Output);//外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN //process.ErrorDataReceived += (o, e) => Debug.WriteLine($"{DateTime.Now}ErrorDataReceived:{e.Data}"); //process.OutputDataReceived += (o, e) => Debug.WriteLine($"{DateTime.Now}OutputDataReceived:{e.Data}"); //process.BeginOutputReadLine(); process.Start(); #region 标准输入值 ////标准输入写入值 //process.StandardInput.AutoFlush = true; //process.StandardInput.WriteLine(s); //process.StandardInput.Close(); #region 调用的exe,读取值 //string[] cmdArgs = System.Environment.GetCommandLineArgs();//接收参数 //var r = new System.IO.StreamReader(Console.OpenStandardInput()); //var sz = r.ReadToEnd(); //MessageBox.Show(sz); //MessageBox.Show($"视频窗接收参数:{string.Join(",", cmdArgs)}"); #endregion #endregion process.BeginErrorReadLine();//开始异步读取,不能少 await process.WaitForExitAsync(); //WaitForExit()阻塞等待进程结束, process.WaitForExit(3000);不等待其退出, EnableRaisingEvents开启退出事件 string output = string.Empty; #region 读取返回值 //string output = process.StandardOutput.ReadToEnd(); //第一种:读取返回值。调用的exe直接Console.WriteLine() //读取返回值。调用的exe直接Console.WriteLine() string result = string.Empty; while (!process.StandardOutput.EndOfStream) { result += process.StandardOutput.ReadLine() + Environment.NewLine; } #endregion Debug.WriteLine($"{DateTime.Now},process 返回值: {result},exe输出Console.WriteLine:{output}"); Debug.WriteLine($"{DateTime.Now},process exist: {process.ExitCode},退出:{process.HasExited},exe输出Console.WriteLine:{output}"); //int res = process.ExitCode; return process.HasExited; } catch (Exception objException) { throw new Exception("Problem to execute outer .exe file!", objException); } } /// <summary> /// 关闭外部程序 /// </summary> /// <param name="exeName">外部程序名称</param> public void ExecuteClose(string exeName) { var arrProcess = Process.GetProcessesByName(exeName); foreach (var proc in arrProcess) { if (!proc.HasExited) { proc.CloseMainWindow(); //之后调用 proc.Kill(); //录制视频流,Process.Kill()直接关闭进程视频文件就损坏了。 } } } #endregion #region 播放视频 /// <summary> /// 播放 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnVlc_Click(object sender, EventArgs e) { var current = System.Reflection.Assembly.GetEntryAssembly(); var strDirFile = $"{System.AppDomain.CurrentDomain.BaseDirectory}/Image/m5506.mp4"; if (!File.Exists(strDirFile)) { MessageBox.Show($"文件不存在"); } //vlcControl1.Video.IsKeyInputEnabled = false; //vlcControl1.Video.IsMouseInputEnabled = false; //1.第一种 string[] mediaOptions = new string[] { "input-repeat=0" }; //input-repeat=2, x为循环次数 vlcControl1.SetMedia(new FileInfo(strDirFile), mediaOptions); //vlcControl1.Size = new Size(800, 500); //this.WindowState = FormWindowState.Maximized; vlcControl1.Play(); //2.第二种 //vlcControl1.Play(new FileInfo(strDirFile)); //vlcControl1.Play(strDirFile); //播放RTSP //vlcControl1.Play(new Uri(rtsp://192.168.1.111)); //播放摄像头 //string mrl = @"dshow:// "; //string optVideo = @":dshow-vdev=摄像头设备名"; ////string optAudio = @":dshow-adev=音频设备名"; //string size = ":dshow-size=800"; //vlcControl1.Play(mrl, optVideo, size); } /// <summary> /// vlcControl1初始化 /// Vlc.DotNet.Forms /// VideoLAN.LibVLC.Windows /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void vlcControl1_VlcLibDirectoryNeeded(object sender, Vlc.DotNet.Forms.VlcLibDirectoryNeededEventArgs e) { var currentAssembly = System.Reflection.Assembly.GetEntryAssembly(); Debug.WriteLine($"vlc:{currentAssembly}"); var currentDirectory = new FileInfo(currentAssembly.Location).DirectoryName; if (currentDirectory == null) { return; } if (IntPtr.Size == 4 ) { e.VlcLibDirectory = new DirectoryInfo(Path.GetFullPath(@".\libvlc\win-x86\")); } else { e.VlcLibDirectory = new DirectoryInfo(Path.GetFullPath(@".\libvlc\win-x64\")); } } /// <summary> /// 继续、暂停 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnReplay_Click(object sender, EventArgs e) { var str = vlcControl1.GetCurrentMedia(); vlcControl1.Show(); vlcControl1.SendToBack(); var strImgPath = $"{Application.StartupPath }/{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.jpg"; var blnSnapshot = vlcControl1.TakeSnapshot(strImgPath); //截图 if (blnSnapshot) { this.picBox1.Image = Image.FromFile(strImgPath); this.picBox1.SizeMode = PictureBoxSizeMode.StretchImage; } if (vlcControl1.IsPlaying) { vlcControl1.VlcMediaPlayer.Pause(); this.btnReplay.Text = "继续"; } else { vlcControl1.VlcMediaPlayer.Play(); this.btnReplay.Text = "暂停"; } } /// <summary> /// 停止 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnVlcStop_Click(object sender, EventArgs e) { Task.Run(() => { vlcControl1.Stop(); }); //这里要开线程处理,不然会阻塞播放 } #endregion }
修改后:

public partial class Form1 : Form { private CancellationTokenSource cts = new CancellationTokenSource(); private Task currentTask ; //ManualResetEvent resetEvent = new ManualResetEvent(true); #region 始终获取焦点 ////调用API //[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, ExactSpelling = true)] //public static extern IntPtr GetForegroundWindow(); //获得本窗体的句柄 //[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SetForegroundWindow")] //public static extern bool SetForegroundWindow(IntPtr hWnd);//设置此窗体为活动窗体 ////定义变量,句柄类型 //public IntPtr Handle1; #endregion public Form1() { InitializeComponent(); this.AutoScaleMode = AutoScaleMode.Inherit; //this.FormBorderStyle = FormBorderStyle.None; //设置窗体为无边框样式 //this.WindowState = FormWindowState.Maximized; //最大化窗体 //this.TopMost = true; //设置窗体置顶 //Handle1 = this.Handle; ////设置此窗体为活动窗体 //SetForegroundWindow(Handle1); } #region 轮播图片 /// <summary> /// 播放 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void btnCarousel_Click(object sender, EventArgs e) { this.picBox1.BackColor = Color.Green; var lstImg = await InitImage(); CancellationToken token = cts.Token; PlayImage(lstImg, token); //currentTask = new Task(async () => //{ // while (true) // { // await ShowImageAsync(lstImg); // } //}, token); //currentTask.Start(); } /// <summary> /// 播放图片 /// </summary> /// <param name="images"></param> /// <param name="token"></param> /// <returns></returns> private void PlayImage(List<Image> images, CancellationToken token) { currentTask = new Task(async () => { while (!cts.IsCancellationRequested) { //if (cts.IsCancellationRequested) //{ // Debug.WriteLine($"{DateTime.Now},退出播放图片:"); // break; //} Debug.WriteLine($"{DateTime.Now},准备播放图片:ManagedThreadId:{Thread.CurrentThread.ManagedThreadId}"); await ShowImageAsync(images); } Debug.WriteLine($"{DateTime.Now},退出播放图片:"); }, token); currentTask.Start(); } /// <summary> /// 初始化图片 /// </summary> /// <returns></returns> private async Task<List<Image>> InitImage() { List<Image> images = new List<Image>(); var strDir = System.AppDomain.CurrentDomain.BaseDirectory; string str2 = System.Environment.CurrentDirectory; string str3 = System.IO.Directory.GetCurrentDirectory();//不可靠 images.Add(Image.FromFile($"{strDir}/Image/a.jpeg")); images.Add(Image.FromFile($"{strDir}/Image/b.jpeg")); images.Add(Image.FromFile($"{strDir}/Image/c.jpeg")); //images.Add(Image.FromFile($"{strDir}/Image/m5506.mp4")); string[] arrFile = Directory.GetFileSystemEntries($"{System.AppDomain.CurrentDomain.BaseDirectory}/Image"); return await Task.FromResult(images); } /// <summary> /// 显示图片 /// </summary> /// <param name="images"></param> /// <returns></returns> private async Task ShowImageAsync(List<Image> images) { foreach (var img in images) { if (cts.IsCancellationRequested) { Debug.WriteLine($"{DateTime.Now},暂停图片:{images.IndexOf(img)}"); ; break ; } Debug.WriteLine($"{DateTime.Now},播放图片:{images.IndexOf(img)}"); await ChangeImageAsync(img, 2000); } } /// <summary> /// 变更图片 /// </summary> /// <param name="img"></param> /// <param name="milliseconds"></param> /// <returns></returns> private async Task ChangeImageAsync(Image img,int milliseconds = 2000) { this.picBox1.Image = img; this.picBox1.SizeMode = PictureBoxSizeMode.StretchImage; await Task.Delay(milliseconds); } /// <summary> /// 暂停 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnImgStop_Click(object sender, EventArgs e) { if (currentTask != null) { if (currentTask.IsCompleted || currentTask.Status == TaskStatus.RanToCompletion) { cts.Cancel(); Debug.WriteLine($"{DateTime.Now},图片暂停。"); } } } /// <summary> /// 继续 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void btnImgContinue_Click(object sender, EventArgs e) { var lstImg = await InitImage(); cts = new CancellationTokenSource(); PlayImage(lstImg, cts.Token); } #endregion #region 启动外部程序 /// <summary> /// 启动程序 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void btnExec_Click(object sender, EventArgs e) { var strExePath2 = $"{Application.StartupPath }"; Debug.WriteLine($"Application.StartupPath:{strExePath2}"); var strExePath = @"C:\Users\Administrator\Desktop\01文件夹\Solution1\WindowsFormsApp2\bin\Debug\WindowsFormsApp2.exe"; if (!File.Exists(strExePath)) { MessageBox.Show("程序不存在"); return; } var blnRes = false; if (txtParam.Text == "1") { var strffmpegPath = $"{System.AppDomain.CurrentDomain.BaseDirectory}\\Image\\ffmpeg.exe";//Path.GetDirectoryName(Application.ExecutablePath); var strffplayPath = $"{System.AppDomain.CurrentDomain.BaseDirectory}\\Image\\ffplay.exe";//Path.GetDirectoryName(Application.ExecutablePath); var strDirFile = $"{System.AppDomain.CurrentDomain.BaseDirectory}\\Image\\m5506.mp4"; //-fs 全屏模式启动,-autoexit 播完自动退出,-window_title 设置标题, -noborder 无边框窗口,-alwaysontop 窗口始终在顶部,-showmode 0 显示模式 '-loop number' 循环播放 "number" 次(0将一直循环) //var blnRes = ExecuteCommandSync("ffplay", $"-i -window_title 测试视频 -showmode 0 -alwaysontop {strDirFile}"); //ffplay放在当前运行目录下;-autoexit blnRes = await ExecuteCommandSync(strffplayPath, $"-i -window_title 测试视频 -showmode 0 -loop 0 {strDirFile}"); //await Task.Run(() => { blnRes = ExecuteCommandSync(strffplayPath, $"-i -window_title 测试视频 -showmode 0 -loop 0 {strDirFile}"); }); } else { blnRes = await ExecuteCommandSync(strExePath, $"{DateTime.Now},测试程序"); } if (blnRes) { Debug.WriteLine($"{DateTime.Now}:调用结束"); } else { Debug.WriteLine($"{DateTime.Now}:调用失败"); } } /// <summary> /// 关闭外部程序 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnExeClose_Click(object sender, EventArgs e) { var strffplayPath = $"{System.AppDomain.CurrentDomain.BaseDirectory}\\Image\\ffplay.exe"; var strExeName = Path.GetFileNameWithoutExtension(strffplayPath); ExecuteClose(strExeName); } /// <summary> /// 启动外部程序 /// </summary> /// <param name="filename"></param> /// <param name="args"></param> /// <returns></returns> /// <exception cref="Exception"></exception> public async Task<bool> ExecuteCommandSync(string filename,params string[] args) { string s = ""; foreach (string arg in args) { s = s + arg + " "; } s = s.Trim(); try { System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(); startInfo.ErrorDialog = false; startInfo.UseShellExecute = false; //不使用系统外壳程序启动进程 startInfo.RedirectStandardOutput = true; startInfo.RedirectStandardError = true; //把外部程序错误输出写到StandardError流中 startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Maximized; startInfo.CreateNoWindow = true; //不显示dos程序窗口 startInfo.FileName = filename;//exe file name startInfo.Arguments = s;//parameters startInfo.UseShellExecute = false; ////不使用操作系统外壳程序启动线程(一定为FALSE,详细的请看MSDN) System.Diagnostics.Process process = new System.Diagnostics.Process(); process.StartInfo = startInfo; //process.ErrorDataReceived += new DataReceivedEventHandler(Output);//外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN //process.ErrorDataReceived += (o, e) => Debug.WriteLine($"{DateTime.Now}ErrorDataReceived:{e.Data}"); //process.OutputDataReceived += (o, e) => Debug.WriteLine($"{DateTime.Now}OutputDataReceived:{e.Data}"); //process.BeginOutputReadLine(); process.Start(); #region 标准输入值 ////标准输入写入值 //process.StandardInput.AutoFlush = true; //process.StandardInput.WriteLine(s); //process.StandardInput.Close(); #region 调用的exe,读取值 //string[] cmdArgs = System.Environment.GetCommandLineArgs();//接收参数 //var r = new System.IO.StreamReader(Console.OpenStandardInput()); //var sz = r.ReadToEnd(); //MessageBox.Show(sz); //MessageBox.Show($"视频窗接收参数:{string.Join(",", cmdArgs)}"); #endregion #endregion process.BeginErrorReadLine();//开始异步读取,不能少 await process.WaitForExitAsync(); //WaitForExit()阻塞等待进程结束, process.WaitForExit(3000);不等待其退出, EnableRaisingEvents开启退出事件 string output = string.Empty; #region 读取返回值 //string output = process.StandardOutput.ReadToEnd(); //第一种:读取返回值。调用的exe直接Console.WriteLine() //读取返回值。调用的exe直接Console.WriteLine() string result = string.Empty; while (!process.StandardOutput.EndOfStream) { result += process.StandardOutput.ReadLine() + Environment.NewLine; } #endregion Debug.WriteLine($"{DateTime.Now},process 返回值: {result},exe输出Console.WriteLine:{output}"); Debug.WriteLine($"{DateTime.Now},process exist: {process.ExitCode},退出:{process.HasExited},exe输出Console.WriteLine:{output}"); //int res = process.ExitCode; return process.HasExited; } catch (Exception objException) { throw new Exception("Problem to execute outer .exe file!", objException); } } /// <summary> /// 关闭外部程序 /// </summary> /// <param name="exeName">外部程序名称</param> public void ExecuteClose(string exeName) { var arrProcess = Process.GetProcessesByName(exeName); foreach (var proc in arrProcess) { if (!proc.HasExited) { proc.CloseMainWindow(); //之后调用 proc.Kill(); //录制视频流,Process.Kill()直接关闭进程视频文件就损坏了。 } } } #endregion #region 播放视频 /// <summary> /// 播放 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnVlc_Click(object sender, EventArgs e) { var current = System.Reflection.Assembly.GetEntryAssembly(); var strDirFile = $"{System.AppDomain.CurrentDomain.BaseDirectory}/Image/m5506.mp4"; if (!File.Exists(strDirFile)) { MessageBox.Show($"文件不存在"); } //vlcControl1.Video.IsKeyInputEnabled = false; //vlcControl1.Video.IsMouseInputEnabled = false; string pluginPath = $"--plugin-path={ Path.GetFullPath(@".\libvlc\win-x64\plugins")}"; //1.第一种 string[] mediaOptions = new string[] { $"input-repeat={int.MaxValue}" }; //input-repeat=2, x为循环次数 --video-title <字符串型> 视频标题 vlcControl1.SetMedia(new FileInfo(strDirFile), mediaOptions); //vlcControl1.Size = new Size(800, 500); //this.WindowState = FormWindowState.Maximized; vlcControl1.Play(); //2.第二种 //vlcControl1.Play(new FileInfo(strDirFile)); //vlcControl1.Play(strDirFile); //播放RTSP //vlcControl1.Play(new Uri(rtsp://192.168.1.111)); //播放摄像头 //string mrl = @"dshow:// "; //string optVideo = @":dshow-vdev=摄像头设备名"; ////string optAudio = @":dshow-adev=音频设备名"; //string size = ":dshow-size=800"; //vlcControl1.Play(mrl, optVideo, size); } /// <summary> /// vlcControl1初始化 /// Vlc.DotNet.Forms /// VideoLAN.LibVLC.Windows /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void vlcControl1_VlcLibDirectoryNeeded(object sender, Vlc.DotNet.Forms.VlcLibDirectoryNeededEventArgs e) { var currentAssembly = System.Reflection.Assembly.GetEntryAssembly(); Debug.WriteLine($"vlc:{currentAssembly}"); var currentDirectory = new FileInfo(currentAssembly.Location).DirectoryName; if (currentDirectory == null) { return; } if (IntPtr.Size == 4 ) { e.VlcLibDirectory = new DirectoryInfo(Path.GetFullPath(@".\libvlc\win-x86\")); } else { e.VlcLibDirectory = new DirectoryInfo(Path.GetFullPath(@".\libvlc\win-x64\")); } } /// <summary> /// 继续、暂停 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnReplay_Click(object sender, EventArgs e) { var str = vlcControl1.GetCurrentMedia(); vlcControl1.Show(); vlcControl1.SendToBack(); var strImgPath = $"{Application.StartupPath }/{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.jpg"; var blnSnapshot = vlcControl1.TakeSnapshot(strImgPath); //截图 if (blnSnapshot) { this.picBox1.Image = Image.FromFile(strImgPath); this.picBox1.SizeMode = PictureBoxSizeMode.StretchImage; } if (vlcControl1.IsPlaying) { vlcControl1.VlcMediaPlayer.Pause(); this.btnReplay.Text = "继续"; } else { vlcControl1.VlcMediaPlayer.Play(); this.btnReplay.Text = "暂停"; } } /// <summary> /// 停止 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnVlcStop_Click(object sender, EventArgs e) { Task.Run(() => { vlcControl1.Stop(); }); //这里要开线程处理,不然会阻塞播放 } #endregion }

public partial class FormHelpShow : Form { private CancellationTokenSource cts = new CancellationTokenSource(); private Task currentTask; //第三方程序路径 private string strExePath = @"C:\Users\Administrator\Desktop\01文件夹\Solution1\WindowsFormsApp2\bin\Debug\WindowsFormsApp2.exe"; //执行顺序初始值,每次+1 int mIndex = -1; /// <summary> /// 配置文件 /// </summary> public SysConfig SysConfig { get; set; } public FormHelpShow() { InitializeComponent(); //this.ControlBox = false; // 设置不出现关闭按钮,会连同最小化和最大化按钮都给弄掉了 this.MinimizeBox = false; //禁止最小化 //this.WindowState = FormWindowState.Maximized; //最大化窗体 //this.TopMost = true; //设置窗体置顶 this.FormBorderStyle = FormBorderStyle.Sizable; //this.FormBorderStyle.为 None 不会显示窗体标题栏等相关 //this.MaximumSize = new Size(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height); //非全屏 不会遮盖任务栏 this.WindowState = FormWindowState.Maximized; //this.MaximizedBounds = Screen.PrimaryScreen.WorkingArea; //this.MaximumSize = Screen.PrimaryScreen.WorkingArea.Size; //this.MaximumSize=Screen.FromHandle(this.Handle).WorkingArea.Size; this.BackgroundImage = Image.FromFile($"{Application.StartupPath}/Image/bgt01.jpg"); this.BackgroundImageLayout = ImageLayout.Stretch;//设置背景图自适应 this.pnlImg.Visible = false; this.pnlVideo.Visible = false; this.Shown += FormHelpShow_Shown; } /// <summary> /// 显示窗体后 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void FormHelpShow_Shown(object? sender, EventArgs e) { loadTest(); } #region 捕获winform的最小化,最大化,关闭事件 const int WM_SYSCOMMAND = 0x112; const int SC_CLOSE = 0xF060; const int SC_MINIMIZE = 0xF020; const int SC_MAXIMIZE = 0xF030; const int SC_RESTORE = 61728; //窗体按钮的拦截函数 //protected override void WndProc(ref Message m) //{ // //if (m.Msg == WM_SYSCOMMAND) // //{ // // if (m.WParam.ToInt32() == SC_RESTORE) // // { // // //log.Info("窗口还原!"); // // } // // if (m.WParam.ToInt32() == SC_MINIMIZE) //拦截最小化按钮 // // { // // ////这里写操作代码 // // //log.Info("点击最小化按钮!"); // // } // // if (m.WParam.ToInt32() == SC_MAXIMIZE) //拦截窗体最大化按钮 // // { // // //log.Info("点击最大化按钮!"); // // } // // if (m.WParam.ToInt32() == SC_CLOSE) //拦截窗体关闭按钮 // // { // // //log.Info("点击窗口关闭按钮!"); // // } // //} // //base.WndProc(ref m); //} #endregion /// <summary> /// 测试 /// </summary> /// <returns></returns> private async Task loadTest() { while (true) { GetSysconfig(); await Task.Delay(SysConfig.WaitSecond * 1000);; } } /// <summary> /// 退出显示 /// </summary> private void ExitShow() { ChangeMode("0"); } #region 切换模式 /// <summary> /// 切换模式 /// </summary> /// <param name="mode"></param> private void ChangeMode(string mode) { Action action ; switch (mode) { case "1": action = () => { this.pnlImg.Location = new Point(0, 0); this.pnlImg.Dock = DockStyle.Fill; this.pnlImg.Visible = true; cts.Cancel(); this.pnlVideo.Visible = false; this.vlcControl1.Stop(); ExitThirdProject(strExePath); }; break; case "2": action = () => { this.vlcControl1.Dock = DockStyle.Fill; this.pnlVideo.Dock = DockStyle.Fill; this.pnlVideo.Location = new Point(0, 0); this.pnlVideo.Visible = true; this.pnlImg.Visible = false; cts.Cancel(); ExitThirdProject(strExePath); }; break; case "3": action = () => { this.pnlImg.Visible = false; cts.Cancel(); this.pnlVideo.Visible = false; this.vlcControl1.Stop(); ExitThirdProject(strExePath); }; break; default: action = () => { this.pnlImg.Visible = false; cts.Cancel(); this.pnlVideo.Visible = false; this.vlcControl1.Stop(); ExitThirdProject(strExePath); }; break; } this.Invoke(action); } #endregion #region 读配置 /// <summary> /// 读配置 /// </summary> private async Task GetSysconfig() { string strConfigPath = $"{Application.StartupPath}/sysConfig.json"; FileHelper fileHelper = new FileHelper(); //SysConfig config = new SysConfig(); SysConfig = fileHelper.ReadConfig(strConfigPath); //var showMode = config.ShowMode; var lstData = new List<string>() { "0", "1", "2", "3" }; //随机进行 Random random = new Random(); var rdNum = random.Next(0, 4); var showMode = lstData[rdNum]; ////排序进行 //if (mIndex >= lstData.Count - 1) //{ // mIndex = 0; //} //else //{ // mIndex++; //} //var showMode = lstData[mIndex]; switch (showMode) { case "1": await CarouseImage(); break; case "2": ShowVideo(); break; case "3": await StartThirdProject(); break; default: ExitShow(); break; } await Task.Delay(SysConfig.WaitSecond * 1000); } #endregion #region 图片 /// <summary> /// 显示图片 /// </summary> private async Task CarouseImage() { //Task.Run(async () => //{ // var lstImg = await InitImage(); // CancellationToken token = cts.Token; // PlayImage(lstImg, token); //}); ChangeMode("1"); var lstImg = await InitImage(); cts = new CancellationTokenSource(); PlayImage(lstImg, cts.Token); } /// <summary> /// 播放图片 /// </summary> /// <param name="images"></param> /// <param name="token"></param> /// <returns></returns> private void PlayImage(List<Image> images, CancellationToken token) { Action action = async () => { while (!cts.IsCancellationRequested) { Debug.WriteLine($"{DateTime.Now},准备播放图片:ManagedThreadId:{Thread.CurrentThread.ManagedThreadId}"); await ShowImageAsync(images); } Debug.WriteLine($"{DateTime.Now},退出播放图片:"); }; currentTask = new Task(action, token); currentTask.Start(); //currentTask = new Task(async () => //{ // while (!cts.IsCancellationRequested) // { // //if (cts.IsCancellationRequested) // //{ // // Debug.WriteLine($"{DateTime.Now},退出播放图片:"); // // break; // //} // Debug.WriteLine($"{DateTime.Now},准备播放图片:ManagedThreadId:{Thread.CurrentThread.ManagedThreadId}"); // await ShowImageAsync(images); // } // Debug.WriteLine($"{DateTime.Now},退出播放图片:"); //}, token); //currentTask.Start(); } /// <summary> /// 初始化图片 /// </summary> /// <returns></returns> private async Task<List<Image>> InitImage() { List<Image> images = new List<Image>(); var strDir = System.AppDomain.CurrentDomain.BaseDirectory; string str2 = System.Environment.CurrentDirectory; string str3 = System.IO.Directory.GetCurrentDirectory();//不可靠 images.Add(Image.FromFile($"{strDir}/Image/a.jpeg")); images.Add(Image.FromFile($"{strDir}/Image/b.jpeg")); images.Add(Image.FromFile($"{strDir}/Image/c.jpeg")); //images.Add(Image.FromFile($"{strDir}/Image/m5506.mp4")); string[] arrFile = Directory.GetFileSystemEntries($"{System.AppDomain.CurrentDomain.BaseDirectory}/Image"); return await Task.FromResult(images); } /// <summary> /// 显示图片 /// </summary> /// <param name="images"></param> /// <returns></returns> private async Task ShowImageAsync(List<Image> images) { foreach (var img in images) { if (cts.IsCancellationRequested) { Debug.WriteLine($"{DateTime.Now},暂停图片:{images.IndexOf(img)}"); break; } Debug.WriteLine($"{DateTime.Now},播放图片:{images.IndexOf(img)}"); await ChangeImageAsync(img, 2000); } } /// <summary> /// 变更图片 /// </summary> /// <param name="img"></param> /// <param name="milliseconds"></param> /// <returns></returns> private async Task ChangeImageAsync(Image img, int milliseconds = 2000) { Action action = () => { this.picBox1.Image = img; this.picBox1.SizeMode = PictureBoxSizeMode.StretchImage; this.picBox1.Dock = DockStyle.Fill; Task.Delay(milliseconds); }; this.Invoke(action); await Task.Delay(milliseconds); } #endregion #region 视频 /// <summary> /// 播放视频 /// </summary> private void ShowVideo() { try { ChangeMode("2"); Action action = () => { var current = System.Reflection.Assembly.GetEntryAssembly(); var strDirFile = $"{System.AppDomain.CurrentDomain.BaseDirectory}/Image/m5506.mp4"; if (!File.Exists(strDirFile)) { MessageBox.Show($"文件不存在"); } //1.第一种 string[] mediaOptions = new string[] { $"input-repeat={int.MaxValue}", "--video-title='测试视频'", "--video-title-show" }; //input-repeat=2, x为循环次数 --video-title <字符串型> 视频标题 vlcControl1.SetMedia(new FileInfo(strDirFile), mediaOptions); //vlcControl1.Size = new Size(800, 500); //this.WindowState = FormWindowState.Maximized; this.vlcControl1.Dock = DockStyle.Fill; Debug.WriteLine($"{DateTime.Now}:调用播放视频;"); vlcControl1.Play(); }; Task.Run(() => { this.Invoke(action); }); } catch (Exception ex) { throw; } } /// <summary> /// vlcControl1初始化 /// Vlc.DotNet.Forms /// VideoLAN.LibVLC.Windows /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void vlcControl1_VlcLibDirectoryNeeded(object sender, Vlc.DotNet.Forms.VlcLibDirectoryNeededEventArgs e) { var currentAssembly = System.Reflection.Assembly.GetEntryAssembly(); Debug.WriteLine($"vlc:{currentAssembly}"); var currentDirectory = new FileInfo(currentAssembly.Location).DirectoryName; if (currentDirectory == null) { return; } if (IntPtr.Size == 4) { e.VlcLibDirectory = new DirectoryInfo(Path.GetFullPath(@".\libvlc\win-x86\")); } else { e.VlcLibDirectory = new DirectoryInfo(Path.GetFullPath(@".\libvlc\win-x64\")); } } #endregion #region 启动外部程序 /// <summary> /// 启动 /// </summary> /// <returns></returns> private async Task StartThirdProject() { ChangeMode("3"); //var strExePath = @"C:\Users\Administrator\Desktop\01文件夹\Solution1\WindowsFormsApp2\bin\Debug\WindowsFormsApp2.exe"; if (!File.Exists(strExePath)) { MessageBox.Show("程序不存在"); return; } var blnRes = false; if (false) { var strffmpegPath = $"{System.AppDomain.CurrentDomain.BaseDirectory}\\Image\\ffmpeg.exe";//Path.GetDirectoryName(Application.ExecutablePath); var strffplayPath = $"{System.AppDomain.CurrentDomain.BaseDirectory}\\Image\\ffplay.exe";//Path.GetDirectoryName(Application.ExecutablePath); var strDirFile = $"{System.AppDomain.CurrentDomain.BaseDirectory}\\Image\\m5506.mp4"; //-fs 全屏模式启动,-autoexit 播完自动退出,-window_title 设置标题, -noborder 无边框窗口,-alwaysontop 窗口始终在顶部,-showmode 0 显示模式 '-loop number' 循环播放 "number" 次(0将一直循环) //var blnRes = ExecuteCommandSync("ffplay", $"-i -window_title 测试视频 -showmode 0 -alwaysontop {strDirFile}"); //ffplay放在当前运行目录下;-autoexit blnRes = await ExecuteCommandSync(strExePath, $"-i -window_title 测试视频 -showmode 0 -loop 0 {strDirFile}"); //await Task.Run(() => { blnRes = ExecuteCommandSync(strffplayPath, $"-i -window_title 测试视频 -showmode 0 -loop 0 {strDirFile}"); }); } else { blnRes = await ExecuteCommandSync(strExePath, $"{DateTime.Now},测试程序"); } if (blnRes) { Debug.WriteLine($"{DateTime.Now}:调用结束"); } else { Debug.WriteLine($"{DateTime.Now}:调用失败"); } } /// <summary> /// 退出 /// </summary> private void ExitThirdProject(string strExePath = "") { if (string.IsNullOrWhiteSpace(strExePath)) { //strExePath = $"{System.AppDomain.CurrentDomain.BaseDirectory}\\Image\\ffplay.exe"; strExePath = @"C:\Users\Administrator\Desktop\01文件夹\Solution1\WindowsFormsApp2\bin\Debug\WindowsFormsApp2.exe"; } var strExeName = Path.GetFileNameWithoutExtension(strExePath); ExecuteClose(strExeName); } /// <summary> /// 启动外部程序 /// </summary> /// <param name="filename"></param> /// <param name="args"></param> /// <returns></returns> /// <exception cref="Exception"></exception> public async Task<bool> ExecuteCommandSync(string filename, params string[] args) { string s = ""; foreach (string arg in args) { s = s + arg + " "; } s = s.Trim(); try { ExitThirdProject(filename);//启动前存在先退出 System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(); startInfo.ErrorDialog = false; startInfo.UseShellExecute = false; //不使用系统外壳程序启动进程 startInfo.RedirectStandardOutput = true; startInfo.RedirectStandardError = true; //把外部程序错误输出写到StandardError流中 startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Maximized; startInfo.CreateNoWindow = true; //不显示dos程序窗口 startInfo.FileName = filename;//exe file name startInfo.Arguments = s;//parameters startInfo.UseShellExecute = false; ////不使用操作系统外壳程序启动线程(一定为FALSE,详细的请看MSDN) System.Diagnostics.Process process = new System.Diagnostics.Process(); process.StartInfo = startInfo; //process.ErrorDataReceived += new DataReceivedEventHandler(Output);//外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN //process.ErrorDataReceived += (o, e) => Debug.WriteLine($"{DateTime.Now}ErrorDataReceived:{e.Data}"); //process.OutputDataReceived += (o, e) => Debug.WriteLine($"{DateTime.Now}OutputDataReceived:{e.Data}"); //process.BeginOutputReadLine(); process.Start(); #region 标准输入值 ////标准输入写入值 //process.StandardInput.AutoFlush = true; //process.StandardInput.WriteLine(s); //process.StandardInput.Close(); #region 调用的exe,读取值 //string[] cmdArgs = System.Environment.GetCommandLineArgs();//接收参数 //var r = new System.IO.StreamReader(Console.OpenStandardInput()); //var sz = r.ReadToEnd(); //MessageBox.Show(sz); //MessageBox.Show($"视频窗接收参数:{string.Join(",", cmdArgs)}"); #endregion #endregion process.BeginErrorReadLine();//开始异步读取,不能少 await process.WaitForExitAsync(); //WaitForExit()阻塞等待进程结束, process.WaitForExit(3000);不等待其退出, EnableRaisingEvents开启退出事件 string output = string.Empty; #region 读取返回值 //string output = process.StandardOutput.ReadToEnd(); //第一种:读取返回值。调用的exe直接Console.WriteLine() //读取返回值。调用的exe直接Console.WriteLine() string result = string.Empty; while (!process.StandardOutput.EndOfStream) { result += process.StandardOutput.ReadLine() + Environment.NewLine; } #endregion Debug.WriteLine($"{DateTime.Now},process 返回值: {result},exe输出Console.WriteLine:{output}"); Debug.WriteLine($"{DateTime.Now},process exist: {process.ExitCode},退出:{process.HasExited},exe输出Console.WriteLine:{output}"); //int res = process.ExitCode; return process.HasExited; } catch (Exception objException) { throw new Exception("Problem to execute outer .exe file!", objException); } } /// <summary> /// 关闭外部程序 /// </summary> /// <param name="exeName">外部程序名称</param> public void ExecuteClose(string exeName) { var arrProcess = Process.GetProcessesByName(exeName); foreach (var proc in arrProcess) { if (!proc.HasExited) { proc.CloseMainWindow(); //之后调用 proc.Kill(); //录制视频流,Process.Kill()直接关闭进程视频文件就损坏了。 } } } #endregion } #region 重写Myform /// <summary> /// 根据窗体大小进行缩放 /// </summary> public partial class Myform : Form { private float X, Y; //获得控件的长度、宽度、位置、字体大小的数据 private void setTag(Control cons)//Control类,定义控件的基类 { foreach (Control con in cons.Controls) { con.Tag = con.Width + ":" + con.Height + ":" + con.Left + ":" + con.Top + ":" + con.Font.Size;//获取或设置包含有关控件的数据的对象 if (con.Controls.Count > 0) setTag(con);//递归算法 } } private void setControls(float newx, float newy, Control cons)//实现控件以及字体的缩放 { foreach (Control con in cons.Controls) { string[] mytag = con.Tag.ToString().Split(new char[] { ':' }); float a = Convert.ToSingle(mytag[0]) * newx; con.Width = (int)a; a = Convert.ToSingle(mytag[1]) * newy; con.Height = (int)(a); a = Convert.ToSingle(mytag[2]) * newx; con.Left = (int)(a); a = Convert.ToSingle(mytag[3]) * newy; con.Top = (int)(a); Single currentSize = Convert.ToSingle(mytag[4]) * newy; con.Font = new Font(con.Font.Name, currentSize, con.Font.Style, con.Font.Unit); if (con.Controls.Count > 0) { setControls(newx, newy, con);//递归 } } } private void MyForm_Resize(object sender, EventArgs e) { float newx = (this.Width) / X;//当前宽度与变化前宽度之比 float newy = this.Height / Y;//当前高度与变化前宽度之比 setControls(newx, newy, this); this.Text = this.Width.ToString() + " " + this.Height.ToString(); //窗体标题显示长度和宽度 } protected override void OnLoad(EventArgs e) { base.OnLoad(e); this.Resize += new EventHandler(MyForm_Resize); X = this.Width; Y = this.Height; setTag(this); } } #endregion

/// <summary> /// 文件帮助 /// </summary> public class FileHelper { string strConfigPath = $"{Application.StartupPath}/sysConfig.json"; /// <summary> /// 读取文件 /// </summary> /// <param name="filePath"></param> /// <returns></returns> public string GetConfigString(string filePath) { string strRes = string.Empty; using (StreamReader sr = new StreamReader(filePath)) { string line; while ((line = sr.ReadLine()) != null) { strRes = strRes + line; } } return strRes; } /// <summary> /// 读配置文件 /// </summary> /// <param name="filePath"></param> /// <returns></returns> public SysConfig ReadConfig(string filePath) { var str = GetConfigString(filePath); if (str == null) { return null; } SysConfig config = JsonConvert.DeserializeObject<SysConfig>(str); return config; } /// <summary> /// 写配置文件 /// </summary> /// <param name="filePath"></param> /// <param name="sysConfig"></param> public void WriteConfig(string filePath,SysConfig sysConfig) { string jsonData = JsonConvert.SerializeObject(sysConfig,Formatting.Indented); using (StreamWriter sw =new StreamWriter(filePath)) { sw.WriteLine(filePath, jsonData); } } } /// <summary> /// 配置 /// </summary> public class SysConfig { /// <summary> /// 显示模式 /// </summary> public string ShowMode { get; set; } /// <summary> /// 等待时间(S) /// </summary> public int WaitSecond { get; set; } }
外部程序 form1

public partial class Form1 : Form { public Form1() { InitializeComponent(); //this.TopMost = true; string[] cmdArgs = System.Environment.GetCommandLineArgs();//接收参数 var r = new System.IO.StreamReader(Console.OpenStandardInput()); var sz = r.ReadToEnd(); //MessageBox.Show(sz); //MessageBox.Show($"视频窗接收参数:{string.Join(",", cmdArgs)}"); System.Diagnostics.Debug.WriteLine($"{DateTime.Now}:视频窗接收OpenStandardInput参数:{sz}"); System.Diagnostics.Debug.WriteLine($"{DateTime.Now}:视频窗接收Arguments参数:{string.Join(",", cmdArgs)}"); PlayVideo(); } /// <summary> /// WindowsMediaPlayer播放视频 /// </summary> private void PlayVideo() { //AxHost. WindowsMediaPlayer //AxWMPLib.AxWindowsMediaPlayer var strDir = System.AppDomain.CurrentDomain.BaseDirectory; axWindowsMediaPlayer1.URL = $"{strDir}/Image/m5506.mp4"; //axWindowsMediaPlayer1.currentPlaylist.appendItem(axWindowsMediaPlayer1.newMedia(url1)); //axWindowsMediaPlayer1.currentPlaylist.appendItem(axWindowsMediaPlayer1.newMedia(url2)); //axWindowsMediaPlayer1.Ctlcontrols.play(); axWindowsMediaPlayer1.settings.setMode("Loop", true); Console.WriteLine($"exe返回:{DateTime.Now},{ axWindowsMediaPlayer1.URL}"); } /// <summary> /// 选文件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSelect_Click(object sender, EventArgs e) { OpenFileDialog openFileDialog = new OpenFileDialog(); //openFileDialog.Filter = "媒体文件(所有类型)|*.mp3;*.mp4;*.mpeg;*.wma;*.wmv;*.wav;*.avi;"; openFileDialog.Filter = @" 视频文件 (*.mp4;*.avi;*.wmv;*.dat;*.mpg;*.mpeg;*.mov;*.wm;*.wma)|*.mp4;*.avi;*.wmv;*.dat;*.mpg;*.mpeg;*.mov;*.wm;*.wma | 音频文件 (*.wav;*.mp3;*.snd;*.au;*.midi;*.mid)|*.wav;*.mp3;*.snd;*.au;*.midi;*.mid| 所有文件 (*.*)|*.*"; if (openFileDialog.ShowDialog() == DialogResult.OK) { axWindowsMediaPlayer1.URL = openFileDialog.FileName; } } private void axWindowsMediaPlayer1_StatusChange(object sender, EventArgs e) { if (axWindowsMediaPlayer1.playState == WMPLib.WMPPlayState.wmppsStopped) { axWindowsMediaPlayer1.Ctlcontrols.play(); } } }
================================
https://www.cnblogs.com/EasyInvoice/p/14140051.html
另外的示例:https://gitee.com/bidev_admin/river-int-ai.git

/// <summary> /// 初始化命令、参数,启动线程 /// </summary> /// <param name="args"></param> /// <param name="finishiEvent"></param> public static void Start(string args, EventHandler finishiEvent) { LogHelper.LogInfoFormat("开始执行命令, 参数:{0}", args); FinishiEvent = finishiEvent; // ffmpeg.exe组件文件路径 string ffmpegPath = FFmpegBinariesHelper.RegisterFFmpegBinaries(); string cmdType = args.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries)[0]; ProcessStartInfo startInfo = new ProcessStartInfo(Path.Combine(ffmpegPath, cmdType)); startInfo.WindowStyle = ProcessWindowStyle.Normal; startInfo.Arguments = args.Substring(cmdType.Length); startInfo.UseShellExecute = false; startInfo.CreateNoWindow = true; startInfo.RedirectStandardInput = true; startInfo.RedirectStandardOutput = true; startInfo.RedirectStandardError = true;// ffmpeg信息输出是error事件 p.StartInfo = startInfo; p.OutputDataReceived += P_OutputDataReceived; // ffmpeg信息输出事件 p.ErrorDataReceived += P_OutputDataReceived; Thread thread = new Thread(startffmpeg); thread.Start(); }
命令:
1.查看音频信息:
命令如下(注:pcm文件不适用以下命令):
命令:ffprobe -print_format json -loglevel quiet -show_streams
"您的文件"
示例:ffprobe -print_format json -loglevel quiet -show_streams
"F:\mp4\3.TF以及地图构建.mp4"
命令:ffmpeg -i "您的视频文件路径" -vn -ar 采样率 "音频文件输出路径"
示例:ffmpeg -i "F:\mp4\3.TF以及地图构建.mp4" -vn -ar 8000 "F:\mp4\3.TF以及地图构建_201215172919_8k.m4a"
3.转换音频文件
命令:ffmpeg -i "源音频文件" -acodec pcm_s16le -f s16le -ar 目标音频采样率 "目标音频路径"
示例:ffmpeg -i "F:\mp4\3.TF以及地图构建_201215172919_8k.m4a" -acodec pcm_s16le -f s16le -ar 8000 "F:\mp4\3.TF以及地图构建_201215172919_8k_201215173520_8k.pcm"
FFmpeg部分参数说明

//参数说明 /* * -i filename(input) 源文件目录 * -y 输出新文件,是否强制覆盖已有文件 * -c 指定编码器 * -fs limit_size(outinput) 设置文件大小的限制,以字节表示的。没有进一步的字节块被写入后,超过极限。输出文件的大小略大于所请求的文件大小。 * -s 视频比例 4:3 320x240/640x480/800x600 16:9 1280x720 ,默认值 'wxh',和原视频大小相同 * -vframes number(output) 将视频帧的数量设置为输出。别名:-frames:v * -dframes number (output) 将数据帧的数量设置为输出.别名:-frames:d * -frames[:stream_specifier] framecount (output,per-stream) 停止写入流之后帧数帧。 * -bsf[:stream_specifier] bitstream_filters (output,per-stream) 指定输出文件流格式, 例如输出h264编码的MP4文件:ffmpeg -i h264.mp4 -c:v copy -bsf:v h264_mp4toannexb -an out.h264 * -r 29.97 桢速率(可以改,确认非标准桢率会导致音画不同步,所以只能设定为15或者29.97) * */
方法:

public class Demo2 { public static string ffmpegtool = @"F:\SolutionSet\ABCSolution\VideoSolution\Demo1\bin\Debug\ffmpeg.exe"; //public static string ffmpegtool = @"F:\ABCSolution\ffmpeg-20160808-ce2217b-win64-static\bin\ffplay.exe"; public static string playFile = @"F:\SolutionSet\ABCSolution\VideoSolution\VideoSolution\Content\Video\my3.mp4"; public static string imgFile = @"F:\SolutionSet\ABCSolution\VideoSolution\VideoSolution\Content\Video\my3.gif"; public static string sourceFile = @"F:\SolutionSet\ABCSolution\VideoSolution\VideoSolution\Content\Video\COOLUI.mp4"; //public static string sourceFile = @"F:\ABCSolution\VideoSolution\VideoSolution\Content\Video\theme.mp4"; public void ConvertVideo() { Process p = new Process();//建立外部调用线程 p.StartInfo.FileName = ffmpegtool;//要调用外部程序的绝对路径 //参数(这里就是FFMPEG的参数了) //p.StartInfo.Arguments = @"-i "+sourceFile+ " -ab 56 -b a -ar 44100 -b 500 -r 29.97 -s 1280x720 -y " + playFile+""; // p.StartInfo.Arguments = "-y -i \""+sourceFile+"\" -b v -s 800x600 -r 29.97 -b 1500 -acodec aac -ac 2 -ar 24000 -ab 128 -vol 200 -f psp \""+playFile+"\" "; //string strArg = "-i " + sourceFile + " -y -s 640x480 " + playFile + " "; string strArg = "-i " + sourceFile + " -y -s 1280x720 " + playFile + " "; //获取图片 //截取图片jpg //string strArg = "-i " + sourceFile + " -y -f image2 -t 1 " + imgFile; //string strArg = "-i " + sourceFile + " -y -s 1280x720 -f image2 -t 1 " + imgFile; //视频截取 //string strArg = " -i " + sourceFile + " -y -ss 0:20 -frames 100 " + playFile; //转化gif动画 //string strArg = "-i " + sourceFile + " -y -s 1280x720 -f gif -vframes 30 " + imgFile; //string strArg = " -i " + sourceFile + " -y -f gif -vframes 50 " + imgFile; // string strArg = " -i " + sourceFile + " -y -f gif -ss 0:20 -dframes 10 -frames 50 " + imgFile; //显示基本信息 //string strArg = "-i " + sourceFile + " -n OUTPUT"; //播放视频 //string strArg = "-stats -i " + sourceFile + " "; p.StartInfo.Arguments = strArg; p.StartInfo.UseShellExecute = false;//不使用操作系统外壳程序启动线程(一定为FALSE,详细的请看MSDN) p.StartInfo.RedirectStandardError = true;//把外部程序错误输出写到StandardError流中(这个一定要注意,FFMPEG的所有输出信息,都为错误输出流,用StandardOutput是捕获不到任何消息的...这是我耗费了2个多月得出来的经验...mencoder就是用standardOutput来捕获的) p.StartInfo.CreateNoWindow = false;//不创建进程窗口 p.ErrorDataReceived += new DataReceivedEventHandler(Output);//外部程序(这里是FFMPEG)输出流时候产生的事件,这里是把流的处理过程转移到下面的方法中,详细请查阅MSDN p.Start();//启动线程 p.BeginErrorReadLine();//开始异步读取 p.WaitForExit();//阻塞等待进程结束 p.Close();//关闭进程 p.Dispose();//释放资源 } private void Output(object sendProcess, DataReceivedEventArgs output) { if (!String.IsNullOrEmpty(output.Data)) { //处理方法... Console.WriteLine(output.Data); ////去获取时长 //string partitio1 = @"Duration: \d{2}:\d{2}:\d{2}.\d{2}"; //if (RegexHelper.IsMatch(partitio1, output.Data)) //{ // string partition = @"(?<=Duration: )\d{2}:\d{2}:\d{2}.\d{2}"; // string timespan = RegexHelper.Matchs(output.Data, partition).FirstOrDefault(); // TimeSpan span; // if (TimeSpan.TryParse(timespan, out span)) // { // Console.WriteLine(span.TotalMilliseconds); // } //} ////获取时刻 //string partitio2 = @"time=\d{2}:\d{2}:\d{2}.\d{2}"; //if (RegexHelper.IsMatch(partitio2, output.Data)) //{ // string partition = @"(?<=time=)\d{2}:\d{2}:\d{2}.\d{2}"; // string timespan = RegexHelper.Matchs(output.Data, partition).FirstOrDefault(); // TimeSpan span; // if (TimeSpan.TryParse(timespan, out span)) // { // Console.WriteLine(span.TotalMilliseconds); // } //} } } }
https://www.cnblogs.com/renhui/p/8458802.html
一个异步方法:

public static async Task<ProcessResult> ExecuteShellCommand(string command, string arguments="", int timeout=1000, bool insertWait=false) { var result = new ProcessResult(); using (var process = new Process()) { process.StartInfo.FileName = command; process.StartInfo.Arguments = arguments; process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardInput = true; process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardError = true; process.StartInfo.CreateNoWindow = true; var outputBuilder = new StringBuilder(); var outputCloseEvent = new TaskCompletionSource<bool>(); process.OutputDataReceived += (s, e) => { // The output stream has been closed i.e. the process has terminated if (e.Data == null) { outputCloseEvent.SetResult(true); } else { outputBuilder.AppendLine(e.Data); } }; var errorBuilder = new StringBuilder(); var errorCloseEvent = new TaskCompletionSource<bool>(); process.ErrorDataReceived += (s, e) => { // The error stream has been closed i.e. the process has terminated if (e.Data == null) { errorCloseEvent.SetResult(true); } else { errorBuilder.AppendLine(e.Data); } }; bool isStarted; try { process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler); process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler); isStarted = process.Start(); StreamReader reader = process.StandardOutput; string output = reader.ReadToEnd(); result.Output = output; } catch (Exception error) { // Usually it occurs when an executable file is not found or is not executable result.Completed = true; result.ExitCode = -1; result.Output = error.Message; isStarted = false; } if (isStarted) { // Reads the output stream first and then waits because deadlocks are possible process.BeginOutputReadLine(); process.BeginErrorReadLine(); if (insertWait) { await Task.Delay(150000); } // Creates task to wait for process exit using timeout var waitForExit = WaitForExitAsync(process, timeout); // Create task to wait for process exit and closing all output streams var processTask = Task.WhenAll(waitForExit, outputCloseEvent.Task, errorCloseEvent.Task); // Waits process completion and then checks it was not completed by timeout if (await Task.WhenAny(Task.Delay(timeout), processTask) == processTask && waitForExit.Result) { result.Completed = true; result.ExitCode = process.ExitCode; // Adds process output if it was completed with error if (process.ExitCode != 0) { result.Output = $"{outputBuilder}{errorBuilder}"; } } else { try { // Kill hung process process.Kill(); } catch { } } } } return result; }
https://stackoverflow.com/questions/11460606/i-am-trying-to-read-the-output-of-a-process-in-c-sharp-but-i-get-this-message-c
FFmpeg&FFplay常用命令汇总
1、FFmpeg常用命令
帮助指令
1)查看基本帮助信息:ffmpeg -h
2)查看高级帮助信息:ffmpeg -h long
3)查看所有帮助信息:ffmpeg -h full
若帮助信息过多,查看不便,可以把帮助信息保存到文件,然后再打开文件查看,如:ffmpeg -h full > fullhelp.log
查询版本
查询命令: ffmpeg -version
查询编译配置
查询命令: ffmpeg -buildconf
查询可用格式
查询命令: ffmpeg -formats
查询可用复用器
查询命令: ffmpeg -muxers
查询可用解复用器
查询命令: ffmpeg -demuxers
查询可用编解码器
查询命令: ffmpeg -codecs
查询可用解码器
查询命令: ffmpeg -decoders
查询可用编码器
查询命令: ffmpeg -encoders
查询可可用比特流filter
查询命令: ffmpeg -bsfs
查询可用的协议
查询命令: ffmpeg -protocols
查询可用的过滤器
查询命令: ffmpeg -filters
查询可用的像素格式
查询命令: ffmpeg -pix_fmts
查询标准声道名称
查询命令: ffmpeg -layouts
查询可用的音频采样格式
查询命令: ffmpeg -sample_fmts
查询可用的颜色名称
查询命令: ffmpeg -colors
参数说明
提取视频
1)保留编码格式:ffmpeg -i test.mp4 -vcodec copy -an test_copy.h264
2)强转编码格式:ffmpeg -i test.mp4 -vcodec libx264 -an test.h264
提取音频
1)保留编码格式:ffmpeg -i test.mp4 -acodec copy -vn test.aac
2)强转编码格式:ffmpeg -i test.mp4 -acodec libmp3lame -vn test.mp3
提取YUV
1)提取3秒数据,分辨率和源视频一致:ffmpeg -i test_1280x720.mp4 -t 3 -pix_fmt yuv420p yuv420p_orig.yuv
2)提取3秒数据,分辨率转为320x240:ffmpeg -i test_1280x720.mp4 -t 3 -pix_fmt yuv420p -s 320x240 yuv420p_320x240.yuv
提取RGB
提取3秒数据,分辨率为320x240:ffmpeg -i test.mp4 -t 3 -pix_fmt rgb24 -s 320x240 rgb24_320x240.rgb
RGB和YUV之间的转换
转换命令:ffmpeg -s 320x240 -pix_fmt yuv420p -i yuv420p_320x240.yuv -pix_fmt rgb24 rgb24_320x240_2.rgb
提取PCM
提取命令:
ffmpeg -i buweishui.mp3 -ar 48000 -ac 2 -f s16le 48000_2_s16le.pcm
ffmpeg -i buweishui.mp3 -ar 48000 -ac 2 -sample_fmt s16 out_s16.wav
ffmpeg -i buweishui.mp3 -ar 48000 -ac 2 -codec:a pcm_s16le out2_s16le.wav
ffmpeg -i buweishui.mp3 -ar 48000 -ac 2 -f f32le 48000_2_f32le.pcm
ffmpeg -i test.mp4 -t 10 -vn -ar 48000 -ac 2 -f f32le 48000_2_f32le_2.pcm
修改编码格式
修改命令:ffmpeg -i test.mp4 -vcodec libx265 -acodec libmp3lame out_h265_mp3.mkv
修改帧率
修改命令:ffmpeg -i test.mp4 -r 15 output2.mp4
修改视频码率
修改命令:
ffmpeg -i test.mp4 -b 400k output_b.mkv (此时音频也被重新编码)
ffmpeg -i test.mp4 -b:v 400k output_bv.mkv
修改音频码率
修改命令:ffmpeg -i test.mp4 -b:a 192k output_ba.mp4 如果不想重新编码video,需要加上-vcodec copy
修改音视频码率
修改命令:ffmpeg -i test.mp4 -b:v 400k -b:a 192k output_bva.mp4
修改视频分辨率
修改命令:ffmpeg -i test.mp4 -s 480x270 output_480x270.mp4
修改音频采样率
修改命令:ffmpeg -i test.mp4 -ar 44100 output_44100hz.mp4
裁剪视频
裁剪命令:ffmpeg -i test.mp4 -ss 00:05:00 -t 10 -codec copy 1.mp4
视频格式转换
1)mp4转换成ts:ffmpeg -i 1.mp4 -codec copy -vbsf h264_mp4toannexb 1.ts
2)mp4转换成flv:ffmpeg -i 1.mp4 -codec copy 1.flv
分离某些封装格式(例如MP4/FLV/MKV等)中的H.264的时候,需要首先写入SPS和PPS,否则会导致分离出来的数据没有SPS、 PPS而无法播放。 H.264码流的SPS和PPS信息存储在AVCodecContext结构体的extradata中。需要使用ffmpeg中名称为“ h264_mp4toannexb”的bitstream filter处理。
视频拼接
1)拼接mp4格式(mp4list.txt保存视频名称列表)
ffmpeg -f concat -i mp4list.txt -codec copy out_mp42.mp4
2)拼接ts格式
方法1:ffmpeg -i "concat:1.ts|2.ts|3.ts" -codec copy out_ts.mp4
方法2:ffmpeg -f concat -i tslist.txt -codec copy out_ts2.mp4
基于MFC和ffplay实现的视频播放软件
rar
5星
超过95%的资源
49.49MB
下载
3)拼接flv格式
ffmpeg -f concat -i flvlist.txt -codec copy out_flv2.mp4
注意事项:
- 把每个视频封装格式也统一为ts,拼接输出的时候再输出你需要的封装格式,比如MP4
- 视频分辨率可以不同,但是编码格式需要统一
- 音频编码格式需要统一,音频参数(采样率/声道等)也需要统一
截图
截图命令:ffmpeg -i test.mp4 -y -f image2 -ss 00:00:02 -vframes 1 -s 640x360 test.jpg
参数说明:
-i 输入
-y 覆盖
-f 格式
image2 一种格式
-ss 起始值
-vframes 帧 如果大于1 那么 输出加%03d test%03d.jpg
-s 格式大小size
提取视频图片
提取命令:ffmpeg -i test.mp4 -t 5 -s 640x360 -r 15 frame%03d.jpg (每帧一张图)
图片合成视频
合成命令:ffmpeg -f image2 -i frame%03d.jpg -r 25 video.mp4
视频转成gif
转换命令:ffmpeg -i test.mp4 -t 5 -r 25 -s 640x360 image.gif
gif转成视频
转换命令:ffmpeg -f gif -i image.gif image.mp4
视频录制
1)视频录制需要安装dshow软件Screen Capturer Recorder。
下载网址:https://sourceforge.net/projects/screencapturer/files/
2) 查看可用设备名字:ffmpeg -list_devices true -f dshow -i dummy
得到摄像头名称等相关信息。
3)录制视频(默认参数)
桌面:ffmpeg -f dshow -i video="screen-capture-recorder" v-out.mp4
摄像头:ffmpeg -f dshow -i video="Integrated Webcam" -y v-out2.flv (""为摄像头名称)
4)录制声音(默认参数)
系统声音:ffmpeg -f dshow -i audio="virtual-audio-capturer" a-out.aac
系统+麦克风声音:ffmpeg -f dshow -i audio="麦克风 (Realtek Audio)" -f dshow -i audio="virtual-audio-capturer" -filter_complex amix=inputs=2:duration=first:dropout_transition=2 a-out2.aac
5)同时录制视频和声音(默认参数)
ffmpeg -f dshow -i audio="麦克风 (Realtek Audio)" -f dshow -i audio="virtualaudio-capturer" -filter_complex amix=inputs=2:duration=first:dropout_transition=2 -f dshow -i video="screen-capture-recorder" -y av-out.flv
直播拉流
ffplay rtmp://server/live/streamName
ffmpeg -i rtmp://server/live/streamName -c copy dump.flv 对于不是rtmp的协议 -c copy要谨慎使用
直播推流
ffmpeg -re -i out.mp4 -c copy flv rtmp://server/live/streamName
-re,表示按时间戳读取文件
ffplay工具
exe
0星
超过10%的资源
27.36MB
下载
2、FFplay常用命令
播放本地文件
播放命令: ffplay -window_title "test time" -ss 2 -t 10 -autoexit test.mp4 或 ffplay test.mp3
播放网络流
播放命令: ffplay -window_title "rtmp stream" rtmp://202.69.69.180:443/webcast/bshdlive-pc
强制解码器
1)mpeg4解码器:ffplay -vcodec mpeg4 test.mp4
2)h264解码器:ffplay -vcodec h264 test.mp4
禁用音频或视频
1)禁用音频:ffplay test.mp4 -an
2)禁用视频:ffplay test.mp4 -vn
播放YUV数据
播放命令: ffplay -pixel_format yuv420p -video_size 320x240 -framerate 5 yuv420p_320x240.yuv
播放RGB数据
播放命令: ffplay -pixel_format rgb24 -video_size 320x240 -framerate 5 -i rgb24_320x240.rgb
播放PCM数据
播放命令: ffplay -ar 48000 -ac 2 -f f32le 48000_2_f32le.pcm
参数说明:
-ar 设置音频采样率 (单位: Hz,取值:0 ~ INT_MAX,默认值: 0)
-ac 设置音频声道数 (取值:0 ~ INT_MAX,默认值: 0)
播放控制
播放视频:‘ffplay 视频文件’
视频播放时,可以通过以前指令控制视频的状态。
播放选项
ffplay test.mp4 -bytes 0:按字节进行定位拖动(bytes取值: 0:off, 1:on, -1:auto)
ffplay test.mp4 -seek_interval 15:自定义左/右键定位拖动时间间隔(单位:秒,默认值10秒)
ffplay test.mp4 -nodisp:关闭图形化显示窗口,不显示视频
ffplay test.mp4 -noborder:显示无边框窗口
ffplay test.mp4 -volume 30:设置起始音量(音量范围:0~100)
ffplay test.mp4 -f s16le:强制使用设置的格式(比如s16le)进行解析
ffplay test.mp4 -window_title title:设置窗口标题(默认为输入文件名)
ffplay test.mp4 -loop 2:设置循环播放次数(比如这里为循环播放2次)
ffplay test.mp4 -showmode mode:设置显示模式,mode取值: 0视频,1音频波形,2 音频频谱。缺省为0,若视频不存在自动选择2
ffplay test.mp4 -vf filtergraph:设置视频滤镜
ffplay test.mp4 -af filtergraph:设置音频滤镜
ffplay test.mp4 -stats:打印回放统计信息,包括显示流持续时间,编解码器参数等。默认启用,显示禁用可以指定-nostats
ffplay test.mp4 -fast:非标准化规范的多媒体兼容优化
ffplay test.mp4 -genpts:生成pts
ffplay test.mp4 -sync type:同步类型,将主时钟设置为audio(type=audio),video或external。
ffplay test.mp4 -ast audio_stream_specifier:指定音频流索引,比如-ast 3,播放流索引为3的音频流
ffplay test.mp4 -vst video_stream_specifier:指定视频流索引,比如-vst 4,播放流索引为4的视频流
ffplay test.mp4 -sst subtitle_stream_specifier:指定字幕流索引,比如-sst 5,播放流索引为5的字幕流
ffplay test.mp4 -autoexit:视频播放完毕后退出
ffplay test.mp4 -exitonkeydown:键盘按下任何键退出播放
ffplay test.mp4 -exitonmousedown:鼠标按下任何键退出播放
ffplay test.mp4 -codec:media_specifier codec_name:强制使用设置的多媒体解码器,media_specifier可用值为a(音频),v(视频)和s字幕。比如-codec:v h264_qsv 强制视频采用h264_qsv解码
ffplay test.mp4 -acodec codec_name: 强制使用设置的音频解码器进行音频解码
ffplay test.mp4 -vcodec codec_name: 强制使用设置的视频解码器进行视频解码
ffplay test.mp4 -scodec codec_name: 强制使用设置的字幕解码器进行字幕解码
ffplay test.mp4 -autorotate: 根据文件元数据自动旋转视频。值为0或1 ,默认为1。
ffplay test.mp4 -framedrop: 如果视频不同步则丢弃视频帧。当主时钟非视频时钟时默认开启。若需禁用则使用 -noframedrop
ffplay test.mp4 -infbuf: 不限制输入缓冲区大小。尽可能快地从输入中读取尽可能多的数据。播放实时流时默认启用,如果未及时读取数据,则可能会丢弃数据。此选项将不限制缓冲区的大小。若需禁用则使用-noinfbuf
视频旋转
旋转命令: ffplay -i test.mp4 -vf transpose=1 取值:0~3
视频反转
反转命令: ffplay test.mp4 -vf hflip或ffplay test.mp4 -vf vflip
视频旋转和反转
执行命令: ffplay test.mp4 -vf hflip,transpose=1
音频变速播放
查询命令: ffplay -i test.mp4 -af atempo=2
视频变速播放
查询命令: ffplay -i test.mp4 -vf setpts=PTS/2
音视频同时变速
查询命令: ffplay -i test.mp4 -vf setpts=PTS/2 -af atempo=2
原文链接:https://blog.csdn.net/locahuang/article/details/113739781
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库