C# 中简单的 Mplayer 前端






4.86/5 (19投票s)
描述如何简单地使用 Mplayer 在您的 Winform 应用程序中显示媒体文件的代码
引言
大家好!这是我的第一篇文章,所以希望大家能忽略我的错误。
它演示了如何在不使用任何 COM/ActiveX 控件的情况下,在我们的 C# Winform 应用程序中轻松使用 mplayer 来显示媒体文件。
为了使用此代码运行视频,我们需要将 *mplayer.exe* 放在我们的 *bin* 文件夹中。
可以从 这里 下载。在该页面上,我们还提供了 mplayer 的 Windows 版本链接。
也可以在此处 找到 mplayer 的预编译二进制文件。
背景
我想在我的 C# Winform 应用程序中显示视频,但不想使用 MediaPlayer 组件。
Mplayer 是一个命令行电影播放器。它可以使用多种不同的输出驱动程序显示视频输出。它似乎是一个合适的选择,但没有关于如何使用 mplayer 在 C# winform 应用程序中显示输出的示例,也找不到使用 .NET 框架制作的 mplayer 前端。
查看找到的 C++ 示例后,发现用 C# 也可以相当简单地实现这一点。本文将展示如何使用 Mplayer 轻松地在我们的应用程序中显示视频文件。
以下是示例解决方案执行时的屏幕截图。

使用的技术
此项目中使用的主要技术包括:
- 使用 Process 对象,因为我们使用外部 EXE 文件来播放媒体文件
- 输入/输出重定向,因为我们需要与外部进程通信
- 获取控件的窗口句柄,以便在其中显示视频
Using the Code
我们在窗体类中声明了以下变量:
string args = "";
/// <summary>
/// Path of selected file
/// </summary>
string filename = null;
/// <summary>
/// The process Object to run Mplayer.exe
/// </summary>
Process ps = null;
args
将保存除了文件名之外将要传递给进程的参数。filename
将是要打开的文件的名称。ps
是进程对象。我们将使用它来保留对 mplayer 进程的引用。
我们将使用 `System.Diagnostics` 命名空间中的 `Process` 类来启动 mplayer 实例以播放视频文件。
我们将重定向输入,以便通过设置将命令从我们的应用程序发送到 mplayer 进程。
这是我们用于初始化进程的代码:
ps = new Process();
//Path of Mplayer exe
ps.StartInfo.FileName = "mplayer ";
ps.StartInfo.UseShellExecute = false;
ps.StartInfo.RedirectStandardInput = true;
args = "-nofs -noquiet -identify -slave ";
args += "-nomouseinput -sub-fuzziness 1 ";
//-wid will tell MPlayer to show output inside our panel
args += " -vo direct3d, -ao dsound -wid ";
int id = (int)panel1.Handle;
args += id;
我们使用 `-slave` 选项,因为我们希望 mplayer 在“slave”模式下运行,在这种模式下,它将从另一个进程读取命令并相应地执行操作。
- `-nofs` 选项将指示 mplayer 不要全屏运行。
- `-wid` 选项将指示我们希望显示视频输出的窗口的 ID。在这里,我们希望在 panel1 中显示,所以我们获取它的句柄并将其传递给 `-wid` 之后。
- `-wid` 是必须传递的最重要的选项,它确保输出显示在我们的控件中,而不是 mplayer 创建的另一个窗口中。
当用户单击“选择文件”时,将打开一个文件打开对话框,在选择文件后,其路径将存储在 `filename` 变量中。
`OpenFile` 函数用于播放文件。它看起来像这样:
void OpenFile()
{
if (filename == null)
return;
//Close any current playing media file
try
{
ps.Kill();
}
catch
{
}
try
{
ps.StartInfo.Arguments = args + " \"" + filename + "\"";
ps.Start();
SendCommand("set_property volume " + trkVolume.Value);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
我们首先确保关闭我们启动的任何 mplayer 前实例。
只需将 `ps.Kill` 包装在 `try` catch 中,这样如果进程已退出或尚未启动,就不会显示错误。
然后,我们将所选文件的路径附加到将传递给 mplayer 的参数中。
我们将调用进程对象的 `start` 方法来开始播放电影。
由于启动了一个新进程,我们将向 mplayer 进程发送“`set_property`”命令以根据用户的选择设置音量。
由于我们已经将 `-wid` 参数设置为 `panel1` 的 `Handle`,因此视频将在我们的窗体内的 `panel1` 中显示。
我们可以向 mplayer 进程的 `stdout` 写入命令来控制正在播放的电影。每个命令都必须以“`\n`”结尾,所以我们向每个命令附加“`\n`”而不是使用 `WriteLine` 函数。
`SendCommand` 函数将执行将命令发送到 mplayer 进程的任务。
bool SendCommand(string cmd)
{
try
{
if (ps != null && ps.HasExited == false)
{
ps.StandardInput.Write(cmd + "\n");
return true;
}
else
{
return false;
}
}
catch
{
return false;
}
}
这样,我们就可以传递命令并控制正在播放的电影。
现在,要播放或暂停选定的电影,将使用以下代码:
if (SendCommand("pause") == false)
{
OpenFile();
}
“`pause`”命令将暂停当前正在播放的电影或恢复暂停的电影。如果电影已播放完毕,mplayer 进程将不再运行。因此,`SendCommand` 将返回 `false`。在这种情况下,我们将调用 `OpenFile` 函数,它将重新启动进程并开始播放选定的电影文件。
其余代码都相当简单易懂。
要了解可以在 slave 模式下传递给 mplayer 的命令,您可以访问:
ftp://ftp2.mplayerhq.hu/MPlayer/DOCS/tech/slave.txt.
要了解 *mplayer.exe* 接受的开关,请访问:
http://www.mplayerhq.hu/DOCS/man/en/mplayer.1.txt.
关注点
如果电影暂停了,并且由于某种原因我们的应用程序崩溃了,可能会有一个 mplayer 进程无用运行。通过将项目的输出类型更改为控制台并将 `UseShellExecute` 设置为 `false`,如果 mplayer 未终止,将保留一个控制台,关闭该控制台也将关闭 mplayer。
在此示例中,我们只向 mplayer 进程发送数据,而不读取任何内容。我们还可以重定向进程的输出以读取有关当前正在播放文件的信息,例如位置或时长。如果您觉得在我们的演示应用程序中包含一个进度条来演示这一点是个好主意,请告诉我。