这是一个WPF中播放rtsp等流视频文件的示例,使用的方式是使用ffmpeg封装MediaElement来实现的。封装的方法是unosquare做的,我只是把他的成果拿来用罢了,找了好久才找到在wpf中播放rtsp流(当然vlc、nvlc、winform控件和流转bitmap的方式也能实现,但都没有这个效率高而且它不依赖任何其他内容),封装的源码请查看:https://github.com/unosquare/ffmediaelement
为了方遍别人和我以后更方便地使用demo,我将生成地dll文件和所需其他文件也传到了gihub上,这使得我的文件显得很臃肿,看起来很不专业,但方遍简洁最重要不是么,哈哈。
此次我使用Visual Stdio2015进行编程工作,只要你下载下这整个文件(zip或者clone),然后双击.sln
文件打开解决方案,加载完成Rebuild
一下,然后点击Start
按钮即可,首先vs会先下载一些NuGet包,配置完成后会顺利运行,此时你就会看到展示了四个视频直播地窗口。
这是一个非常简单的UserController
的建立与使用的示例
MainWindow只是展示了四个PlayerControl
用户控件而已,PlayerControl
是我自己写好的播放器控件,它的SourceStr
属性为依赖项属性,从父窗口获取要播放的rtsp流地址。
PlayerControl.xaml:
<UserControl x:Class="FFMEVideoPlayer.Player.PlayerControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:FFMEVideoPlayer.Player"
Loaded="UserControl_Loaded"
xmlns:player="clr-namespace:Unosquare.FFME;assembly=ffme"
mc:Ignorable="d" Name="playerController">
</UserControl.Resources>
<Grid>
<player:MediaElement Name="Media"/>
</Grid>
</UserControl>
PlayerControl.xaml.cs
using Microsoft.Practices.Prism.Commands;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace FFMEVideoPlayer.Player
{
/// <summary>
/// Interaction logic for PlayerControl.xaml
/// </summary>
public partial class PlayerControl : UserControl
{
public PlayerControl()
{
InitializeComponent();
//必须在为播放器指定uri之前设置FFmpegDirectory的值
//它引用一些依赖的.dll和.exe文件,该文件在../bin/DLL/中
Unosquare.FFME.MediaElement.FFmpegDirectory = Directory.GetCurrentDirectory() + "\\DLL\\";
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
if (SourceStr != null)
{
//指定播放路径
Media.Source = new Uri(SourceStr);
//开始播放
Media.Play();
}
}
public static readonly DependencyProperty SourceStrProperty = DependencyProperty.Register("SourceStr", typeof(string), typeof(PlayerControl));
public string SourceStr
{
get { return (string)GetValue(SourceStrProperty); }
set { SetValue(SourceStrProperty, value); }
}
}
}
PlayerControl
调用ffme
封装好的MediaElement
来实现播放功能。经过封装的MediaElement
被集成到了我所引用的ffme.dll
文件中,而ffmpeg.dll
在本程序中也是不可缺少的引用。
所以引用MediaElement
的方式如下:
PlayerControl.xaml文件
- 首先引入ffme.dll的命名空间:
xmlns:player="clr-namespace:Unosquare.FFME;assembly=ffme"
- 在Grid中添加MediaElementk控件:
<player:MediaElement Name="Media" HorizontalAlignment="Right" VerticalAlignment="Stretch"/>
xaml中定义的其他内容只是控制播放/停止等命令的按钮而已,若不需要可以删除掉,不影响播放功能。
PlayerControl.xaml.cs
- 注册一个依赖项属性,获取父窗体提供的播放地址
public static readonly DependencyProperty SourceStrProperty = DependencyProperty.Register("SourceStr", typeof(string), typeof(PlayerControl));
public string SourceStr
{
get { return (string)GetValue(SourceStrProperty); }
set { SetValue(SourceStrProperty, value); }
}
- 在构造函数中首先添加一句:
Unosquare.FFME.MediaElement.FFmpegDirectory = Directory.GetCurrentDirectory() + "\\DLL\\";
这是为了要添加一些播放所需的dll和exe文件,位置在/bin/Debug/DLL,它必须在设置播放器Source
属性之前执行。
- 而后在控件的
Loaded
事件里为Media
控件的Source
属性赋值并令其播放。
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
if (SourceStr != null)
{
//指定播放路径
Media.Source = new Uri(SourceStr);
//开始播放
Media.Play();
}
}
此时就可以实现最简单的播放功能了。
MediaElement有Play()
、Close()
、Dispose()
、Pause()
、Stop()
等方法,有IsPlaying
、IsOpen
、IsOpening
、MediaState
、HasAudio
等属性,我们可以通过他们来判断和控制播放状态。
定义DelegateCommand
命令实现停止、播放功能,定义公有属性监控当前播放状态,当MediaElement
播放状态发生改变时Media_PropertyChanged
事件被触发来更新监控状态的属性的值。
知道了这些内容,如何定义自已的界面以及功能就随君所欲了。
如果想要按照unosquare的指引来做播放器的话,首先要做的就是下载并安装Visual Stuido 2017来使用C#7.0,否则是无法编译成功的。
从这里下载unosquare/ffmediaelement整个项目源码,里面有使用FFmpeg封装MediaElemnt的源码,也有使用封装得到的dll的Exmaple,我便是按照他的教程来做的。
从这里下载文件并解压。
在VS中新建一个你的播放器WPF程序,我取的名字为FFMEVideoPlayer
。建立完成之后打开其所在文件夹,依次导航到FFMEVideoPlayer\FFMEVideoPlayer\bin\Debug
下,新建一个文件夹命名为DLL
,当然你也可以取别的名字。而后将刚才下载并解压得到的ffmpeg-3.3.2-win32-shared
文件夹中bin
文件夹下的3个exe文件和8个dll文件全部复制到DLL
下。
下载下载unosquare/ffmediaelemen完成之后使用VS2017打开Unosquare.FFME.sln
解决方案,重新生Unosquare.FFME
项目,生成成功之后打开其所在文件夹,找到bin/Debug
或者bin/Release
下生成的ffme.dll
和ffmpeg.dll
文件,复制到你的WPF应用程序的bin/DLL
文件夹下。
在刚才新建的WPF应用程序中添加引用,引用刚刚复制到bin/DLL
文件夹中的ffme.dll
和ffmpeg.dll
文件。
在MainWindow.xaml中:
- 添加命名空间:
xmlns:player="clr-namespace:Unosquare.FFME;assembly=ffme"
- 注册Loaded事件:
Loaded="Window_Loaded"
- 添加MediaElement控件
<player:MediaElement Name="Media"/>
在MainWindow.xaml.cs中:
- 修改Loaded事件:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//必须在为播放器指定uri之前设置FFmpegDirectory的值
//它引用一些依赖的.dll和.exe文件,文件在../bin/DLL/中
Unosquare.FFME.MediaElement.FFmpegDirectory = Directory.GetCurrentDirectory() + "\\DLL\\";
//http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8是cctv1直播地址
Media.Source = new Uri("http://ivi.bupt.edu.cn/hls/cctv1hd.m3u8);
//开始播放
Media.Play();
}
此时运行你的程序,稍等一会就回看到cctv1的直播节目了。
这里简要说了下MediaElement
的几个方法,具体内容可以在 Media.Play();
的 Play
上右键转到定义查看其他属性、方法和事件。
感谢Unosquare Labs提供的解决方案