前回記事ではFFMpegを使用したRTMPの配信方法について記載しました。
WPFだろうが何だろうが、C#ではProcessとしてFFmpegを起動してあげれば配信可能なので、簡単かなと思います。
問題なのは再生の方かな。
1.再生用のWebページを作って、そのページをWPFで開く
サーバに配信用のPlayerとHTMLを置いて、そのページをWebBrowserコントロールで表示しようと思いました。これなら、WPF側では制御いらないのでいいのかなと・・・
PlayerとしてはHTML5のvideoタグの利用をする方法と、FlowPlayerを利用する方法を試してみました。
WebBrowserコントロールはそのままではHTML5が表示できないので、レジストリを修正。
WPFのWebBrowserでHTML5を表示する
単体では動かせるけど、webBrowserコントロールで表示するとなると、動いてくれません。
やはり、javaやらflashなどを含めたページだから厳しいのかな・・・?
2.VlcControlの使用
結局うまくいったのは、Vlc.DotNet.Wpfを使用する方法です。こちらのサイトを参考に導入しました。
必要なものは以下の4つ。
NuGetから取得できます。
- VideoLAN.LibVLC.Windows
- Vlc.DotNet.Core
- Vlc.DotNet.Core.Interops
- Vlc.DotNet.Wpf
VlcPlayerはXAMLのコードビハインドで以下のように書くだけ。
VlcLibDirectory = new DirectoryInfo(System.IO.Path.Combine(Directory.GetCurrentDirectory(), "libvlc", IntPtr.Size == 4 ? "win-x86" : "win-x64"));
string StreamParams = ":network-caching=2000";
var player = new VlcControl();
container.Content = player;
player.SourceProvider.CreatePlayer(VlcLibDirectory);
player.SourceProvider.MediaPlayer.Play(new Uri(RTMPのアドレス), StreamParams);
作成したVlcPlayerをContentControlなどのContentに入れてあげればOK。
導入は簡単だと思います。
残念な点があるとすれば、操作が基本的にXamlのコードビハインドになること。
そこで、ViewModelからバインドできるようにアレンジします。
3.VlcControlをViewModelから使用する
VlcContorlを操作するため、UserControlを作成し依存プロパティを追加します。Xamlはこんな感じ。余計なものは省略しています。
VLCPlayer.xaml
<UserControl>
<Grid>
<ContentControl Name="PlayerContainer" />
</Grid>
<UserControl>
で、UserControlのコードビハインド。
この例では依存プロパティとして「StreamPath」プロパティを追加しています。
StreamPathにViewModelからRTMPのパスを指定することで、再生先を切り替え出来ます。
VLCPlayer.xaml.cs
public partial class VLCPlayer : UserControl
{
// Extra parameters to pass to the viewer media. I found a 2 seconds buffer cache makes playing much more stable.
private const string StreamParams = ":network-caching=2000";
public VlcControl vlcPlayer;
VlcLibDirectory = new DirectoryInfo(System.IO.Path.Combine(Directory.GetCurrentDirectory(), "libvlc", IntPtr.Size == 4 ? "win-x86" : "win-x64"));
#region StreamPath
public static readonly DependencyProperty StreamPathProperty =
DependencyProperty.Register("StreamPath",
typeof(string),
typeof(VLCPlayer),
new FrameworkPropertyMetadata(string.Empty, new PropertyChangedCallback(OnStreamPathChanged)));
public string StreamPath
{
get { return (string)GetValue(StreamPathProperty); }
set { SetValue(StreamPathProperty, value); }
}
private static void OnStreamPathChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
VLCPlayer ctrl = obj as VLCPlayer;
if (ctrl == null) return;
ctrl.SetCamera();
}
#endregion
public VLCPlayer()
{
InitializeComponent();
}
public void SetCamera()
{
if (vlcPlayer != null)
{
vlcPlayer.Dispose();
vlcPlayer = null;
}
if (string.IsNullOrEmpty(this.StreamPath)) return;
vlcPlayer = AddPlayer(this.StreamPath, PlayerContainer);
}
private VlcControl AddPlayer(string streamPath, ContentControl container)
{
var player = new VlcControl();
container.Content = player;
player.SourceProvider.CreatePlayer(VlcLibDirectory);
player.SourceProvider.MediaPlayer.Play(new Uri(streamPath), StreamParams);
return player;
}
private void UserControl_Unloaded(object sender, RoutedEventArgs e)
{
try
{
if (vlcPlayer != null)
{
vlcPlayer.Dispose();
vlcPlayer = null;
}
}
catch (Exception ex) { }
}
}