经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 编程经验 » 查看文章
WPF中以MVVM方式,实现RTSP视频播放
来源:cnblogs  作者:猫嘞个扑  时间:2023/9/25 16:49:33  对本文有异议

前言
视频播放在上位机开发中经常会遇到,基本上是两种常见的解决方案

1.采用厂家提供的sdk和前端控件进行展示,常见的海康/大华都提供了相关sdk及文档

2.开启相机onvif协议,捅过rtsp视频流进行播放,前端可以采用web方式,或者wpf中的视频控件进行展示。

项目需求,决定了最终采用开启相机onvif供能,wpf中播放的方式。

网络调研一阵子之后,基本都是推荐Vlc.DotNet或者libvlcsharp.wpf进行前端展示。

参考了很多代码,无论是官方文档,还是不同博客里的代码,很难做到用mvvm的方式对于逻辑解耦。

而且Vlc.DotNet已经不再更新了。

Libvlcasharp.wpf的设计有些反人类,可以参考这篇文章WPF中使用LibVLCSharp.WPF 播放rtsp - Naylor - 博客园 (cnblogs.com)

所以这部分逻辑写的很难受,需要寻找其他方案。

最近有空了,调研了几个其他开源项目,大家的思路都比较一致,相机打开onvif协议推送rtsp视频流,本地通过ffmpeg进行视频转流,然后推送到wpf前端控件上。

unosquare/ffmediaelement: FFME: The Advanced WPF MediaElement (based on FFmpeg) (github.com)

SuRGeoNix/Flyleaf: Media Player .NET Library for WinUI 3/ WPF/WinForms (based on FFmpeg/DirectX) (github.com)

网上有FFME的样例代码,我在本地搭建没有成功,应该是我的ffmpeg编译版本问题,可以参考这个项目。

DG-Wangtao/FFMEVideoPlayer: 使用FFmepg封装的WPF MideaElement,可以播放rtsp视频流。感谢 https://github.com/unosquare/ffmediaelement

最终选择了Flyleaf的方案,简单搭建了demo给大家参考。

Flyleaf官方项目地址SuRGeoNix/Flyleaf: Media Player .NET Library for WinUI 3/ WPF/WinForms (based on FFmpeg/DirectX) (github.com)

MVVM框架使用的是CommunityToolKit.MVVM

 

正文

Flyleaf的使用整体分成四步走,

1.App.xaml及App.xaml.cs中配置ffmpeg的dll文件地址;

1.1ffmpeg的dll文件,我才用的是Flyleaf官方sample中的文件,版本不是最新的。


1.2文件统一放在项目中的FFmpeg文件夹中


1.3生成操作(Build Action)配置为 无(None)


1.4复制到输出目录(Copy to Output Directory)配置为 如果较新则复制(Copy if newer)


1.5App.xaml中添加startup事件

  1. <Application x:Class="FlyleafDemo.App"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. xmlns:local="clr-namespace:FlyleafDemo"
  5. StartupUri="MainWindow.xaml"
  6. Startup="Application_Startup">
  7. <Application.Resources>
  8. </Application.Resources>
  9. </Application>

1.6App.xaml.cs中配置ffmpeg的dll路径,项目编译后会复制ffmpeg文件夹及dll。

  1. using FlyleafLib;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Configuration;
  5. using System.Data;
  6. using System.Linq;
  7. using System.Threading.Tasks;
  8. using System.Windows;
  9. namespace FlyleafDemo
  10. {
  11. /// <summary>
  12. /// Interaction logic for App.xaml
  13. /// </summary>
  14. public partial class App : Application
  15. {
  16. private void Application_Startup(object sender, StartupEventArgs e)
  17. {
  18. Engine.Start(new EngineConfig()
  19. {
  20. FFmpegPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "FFmpeg"),
  21. FFmpegDevices = false, // Prevents loading avdevice/avfilter dll files. Enable it only if you plan to use dshow/gdigrab etc.
  22. #if RELEASE
  23. FFmpegLogLevel = FFmpegLogLevel.Quiet,
  24. LogLevel = LogLevel.Quiet,
  25. #else
  26. FFmpegLogLevel = FFmpegLogLevel.Warning,
  27. LogLevel = LogLevel.Debug,
  28. LogOutput = ":debug",
  29. //LogOutput = ":console",
  30. //LogOutput = @"C:\Flyleaf\Logs\flyleaf.log",
  31. #endif
  32. //PluginsPath = @"C:\Flyleaf\Plugins",
  33. UIRefresh = false, // Required for Activity, BufferedDuration, Stats in combination with Config.Player.Stats = true
  34. UIRefreshInterval = 250, // How often (in ms) to notify the UI
  35. UICurTimePerSecond = true, // Whether to notify UI for CurTime only when it's second changed or by UIRefreshInterval
  36. });
  37. }
  38. }
  39. }

2.ViewModel中配置参数等信息;

  1. using CommunityToolkit.Mvvm.ComponentModel;
  2. using CommunityToolkit.Mvvm.Input;
  3. using FlyleafLib.MediaPlayer;
  4. using FlyleafLib;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Threading.Tasks;
  10. using System.Windows.Media;
  11. namespace FlyleafDemo
  12. {
  13. public class MainViewModel:ObservableObject
  14. {
  15. private Player player;
  16. public Player Player
  17. {
  18. get => player;
  19. set => SetProperty(ref player, value);
  20. }
  21. private Config config;
  22. public Config Config
  23. {
  24. get => config;
  25. set => SetProperty(ref config, value);
  26. }
  27. private string uriString;
  28. public string UriString
  29. {
  30. get => uriString;
  31. set => SetProperty(ref uriString, value);
  32. }
  33. public IRelayCommand<string> PlayCommand { get; set; }
  34. public MainViewModel()
  35. {
  36. Config = new Config();
  37. Config.Video.BackgroundColor = Colors.Transparent;
  38. // 设置播放延迟为100ms,可能我理解有误,具体可以在项目issues里查看
  39. // Config.Player.MaxLatency = 100 * 10000;
  40. Player = new Player(Config);
  41. PlayCommand = new RelayCommand<string>(PlayAction);
  42. UriString = uri1;
  43. }
  44. private string currentUri = string.Empty;
  45. private string uri1 = "rtsp://192.168.20.2:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif";
  46. private string uri2 = "rtsp://192.168.20.3:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif";
  47. private void PlayAction(string uri)
  48. {
  49. if (!string.IsNullOrEmpty(uri))
  50. {
  51. if (currentUri == uri1)
  52. {
  53. //Player.Commands.Stop.Execute(null);
  54. currentUri = uri2;
  55. Player.Commands.Open.Execute(uri2);
  56. }
  57. else
  58. {
  59. //Player.Commands.Stop.Execute(null);
  60. currentUri = uri1;
  61. Player.Commands.Open.Execute(uri1);
  62. }
  63. }
  64. }
  65. }
  66. }

3.View中配置布局等信息;

  1. <Window
  2. x:Class="FlyleafDemo.MainWindow"
  3. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  4. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  5. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  6. xmlns:fl="clr-namespace:FlyleafLib.Controls.WPF;assembly=FlyleafLib"
  7. xmlns:local="clr-namespace:FlyleafDemo"
  8. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  9. Title="MainWindow"
  10. Width="800"
  11. Height="450"
  12. mc:Ignorable="d">
  13. <Grid>
  14. <Grid.RowDefinitions>
  15. <RowDefinition Height="5*" />
  16. <RowDefinition Height="*" />
  17. </Grid.RowDefinitions>
  18. <fl:FlyleafHost
  19. AttachedDragMove="Both"
  20. KeyBindings="Both"
  21. Player="{Binding Player, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
  22. <Viewbox>
  23. <TextBlock Foreground="DarkOrange" Text="Hello Flyleaf Overlay!" />
  24. </Viewbox>
  25. </fl:FlyleafHost>
  26. <Button
  27. Grid.Row="1"
  28. Command="{Binding PlayCommand}"
  29. CommandParameter="{Binding UriString, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
  30. </Grid>
  31. </Window>

4.在xaml.cs中确定View和ViewModel的绑定关系

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Windows;
  7. using System.Windows.Controls;
  8. using System.Windows.Data;
  9. using System.Windows.Documents;
  10. using System.Windows.Input;
  11. using System.Windows.Media;
  12. using System.Windows.Media.Imaging;
  13. using System.Windows.Navigation;
  14. using System.Windows.Shapes;
  15. namespace FlyleafDemo
  16. {
  17. /// <summary>
  18. /// Interaction logic for MainWindow.xaml
  19. /// </summary>
  20. public partial class MainWindow : Window
  21. {
  22. public MainWindow()
  23. {
  24. InitializeComponent();
  25. this.DataContext = new MainViewModel();
  26. }
  27. }
  28. }

 

总结

前端控件绑定比较方便,减少了在xaml.cs中的耦合逻辑
我尝试过三路视频同时播放,效果不错,系统资源消耗也不高
很多参数都可以在Config中配置,一些交互逻辑可以在Player中执行,比较清晰
但是,单视频控件切换视频流的时候,会有一定时间延迟,我尝试过使用
Player.Commands.Stop.Execute(null);
但效果不大。
感兴趣的可以深挖源码,我这里只是抛砖引玉。
Demo源码地址,https://gitee.com/maoleigepu/flyleaf-demo.git,效果图如下

 


————————————————
版权声明:本文为CSDN博主「maoleigepu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/maoleigepu/article/details/133268837

 

原文链接:https://www.cnblogs.com/maoleigepu/p/17727894.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号