.Net8 Avalonia跨平台UI框架——<vlc:VideoView>控件播放海康监控、摄像机视频(Windows / Linux)

一、UI效果

在这里插入图片描述
在这里插入图片描述

二、新建用户控件:VideoViewControl.axaml

需引用:VideoLAN.LibVLC.Windows包
Linux平台需安装:VLC 和 LibVLC (sudo apt-get update、sudo apt-get install vlc libvlccore-dev libvlc-dev)

.axaml 代码

注:vlc:VideoView 上无法增加鼠标和指针事件,需使用Popup浮动透明层

<UserControl xmlns="https://github.com/avaloniaui"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:vlc="clr-namespace:LibVLCSharp.Avalonia;assembly=LibVLCSharp.Avalonia"xmlns:vm="using:TrainArrivalAnalysis.Avalonia.ViewModels"xmlns:i="clr-namespace:Avalonia.Xaml.Interactivity;assembly=Avalonia.Xaml.Interactivity"xmlns:controls="clr-namespace:Avalonia.Controls;assembly=Avalonia.Controls"mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"x:Class="TrainArrivalAnalysis.Avalonia.Controls.VideoViewControl"><Design.DataContext><vm:VideoWindowViewModel/></Design.DataContext><Grid><vlc:VideoView x:Name="playerView" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"  IsHitTestVisible="False" SizeChanged="playerViewSizeChanged" ></vlc:VideoView><Popup x:Name="videoViewPopup" Placement="Center" PlacementTarget="{Binding ElementName=playerView}" IsOpen="True" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"><Border Background="Transparent" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ><Grid Background="Transparent" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"><TextBlock x:Name="playBackTip" VerticalAlignment="Top" HorizontalAlignment="Right" Background="#F0F8FF" Foreground="Red" Margin="0,50,10,0" Padding="15" FontSize="16" FontWeight="Bold" IsVisible="False" /><TextBlock x:Name="connectTip" VerticalAlignment="Center" HorizontalAlignment="Center" Background="Transparent" Foreground="White" FontSize="40" Text="网络中断" IsVisible="False" /></Grid></Border></Popup></Grid></UserControl>
.axaml.cs 代码
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Extensions.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Threading;
using Avalonia.VisualTree;
using LibVLCSharp.Avalonia;
using LibVLCSharp.Shared;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Net.NetworkInformation;
using System.Threading;
using System.Threading.Tasks;
using TrainArrivalAnalysis.Utility;namespace TrainArrivalAnalysis.Avalonia.Controls;public partial class VideoViewControl : UserControl, INotifyPropertyChanged, IDisposable
{private bool _disposed = false;private LibVLC _libVLC;private MediaPlayer _mediaPlayer;private string _url;public string Url{get => _url;set{if (_url != value){StopPlayback(); // 停止当前播放_url = value;OnPropertyChanged(nameof(Url));if (!string.IsNullOrEmpty(_url)){SetMediaPlayerAsync();}}}}private int _type = 0;public int Type{get => _type;set{_type = value;OnPropertyChanged(nameof(Type));}}private bool _isPlayBackTip = false;public bool IsPlayBackTip{get => _isPlayBackTip;set{_isPlayBackTip = value;OnPropertyChanged(nameof(IsPlayBackTip));Dispatcher.UIThread.InvokeAsync(() =>{playBackTip.IsVisible = _isPlayBackTip;});}}private string _playBackTipContent;public string PlayBackTipContent{get => _playBackTipContent;set{if (_playBackTipContent != value){_playBackTipContent = value;OnPropertyChanged(nameof(PlayBackTipContent));Dispatcher.UIThread.InvokeAsync(() =>{playBackTip.Text = _playBackTipContent;});}}}private bool _isConnectTip = false;public bool IsConnectTip{get => _isConnectTip;set{_isConnectTip = value;OnPropertyChanged(nameof(IsConnectTip));Dispatcher.UIThread.InvokeAsync(() =>{connectTip.IsVisible = _isConnectTip;});}}public event PropertyChangedEventHandler PropertyChanged;protected virtual void OnPropertyChanged(string propertyName){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}private int _maxRetryAttempts = 5;private int _retryDelayMilliseconds = 5000;private int _currentRetryAttempt = 0;public VideoViewControl(){InitializeComponent();var libVlcOptions = new[] { "--no-video-title-show", "--no-osd" };_libVLC = new LibVLC(libVlcOptions);this.Loaded += async (sender, e) =>{var videoView = this.FindControl<VideoView>("playerView");if (videoView != null){videoView.Loaded += async (s, ev) =>{if (!string.IsNullOrEmpty(Url)){await SetMediaPlayerAsync();}};}};this.Unloaded += (sender, e) =>{StopPlayback();Dispose(false);};}public async Task SetMediaPlayerAsync(){try{if (!string.IsNullOrEmpty(Url)){_mediaPlayer = new MediaPlayer(_libVLC);await Dispatcher.UIThread.InvokeAsync(() =>{VideoView _videoView = this.FindControl<VideoView>("playerView");if (_videoView != null){_videoView.MediaPlayer = _mediaPlayer;}});var mediaOptions = new[] { ":network-caching=300", "avcodec-hw=any" };var _media = new Media(_libVLC, Url, FromType.FromLocation, mediaOptions);_mediaPlayer.Media = _media;_mediaPlayer.EncounteredError += OnEncounteredError;await Task.Run(() =>{_mediaPlayer.Play();});}_currentRetryAttempt = 0;_ = CheckPlayStatus().ConfigureAwait(false);}catch (Exception ex){}}private async Task CheckPlayStatus(){try{await Task.Delay(5000).ConfigureAwait(false);while (true){if (_mediaPlayer != null && _mediaPlayer.IsPlaying){IsConnectTip = false;if (Type == 1){IsPlayBackTip = true;}_currentRetryAttempt = 0;}else if (_mediaPlayer.State == VLCState.Stopped || _mediaPlayer.State == VLCState.Error || (_mediaPlayer.State == VLCState.Ended && !NetworkHelper.IsNetworkConnected())){IsPlayBackTip = false;IsConnectTip = true;StopPlayback();}else if (_mediaPlayer.State == VLCState.Ended){IsConnectTip = false;if (Type == 1){IsPlayBackTip = true;}}await Task.Delay(10000).ConfigureAwait(false);}}catch (OperationCanceledException){}catch (Exception ex){}}private async void OnEncounteredError(object sender, EventArgs e){IsPlayBackTip = false;IsConnectTip = true;}private async void playerViewSizeChanged(object sender, SizeChangedEventArgs e){if (videoViewPopup.IsOpen){videoViewPopup.Width = playerView.ActualWidth();videoViewPopup.Height = playerView.ActualHeight();}}// 停止播放private void StopPlayback(){_mediaPlayer?.Stop();}public void Dispose(){Dispose(true);GC.SuppressFinalize(this);}protected virtual void Dispose(bool disposing){if (!_disposed){if (disposing){if (_mediaPlayer != null){_mediaPlayer.Stop();_mediaPlayer.Dispose();_mediaPlayer = null;}if (_libVLC != null){_libVLC.Dispose();_libVLC = null;}}_disposed = true;}}
}

三、主页面MainWindow.axaml使用

.axaml代码
<Window xmlns="https://github.com/avaloniaui"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:animation="clr-namespace:Avalonia.Animation;assembly=Avalonia.Animation"xmlns:vm="using:TrainArrivalAnalysis.Avalonia.ViewModels"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:controls="clr-namespace:TrainArrivalAnalysis.Avalonia.Controls"xmlns:converters="clr-namespace:TrainArrivalAnalysis.Avalonia.Converters"xmlns:md="clr-namespace:TrainArrivalAnalysis.Avalonia.Models.Dto"mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"x:Class="TrainArrivalAnalysis.Avalonia.Views.MainWindow"x:DataType="md:ArrivalRecordDto"Icon="/Assets/avalonia-logo.ico"Title="半自动闭塞区段列车整列到达自动智能分析系统"WindowState="FullScreen" SystemDecorations="None"  ZIndex="1"><Window.Resources><converters:GridLengthToDoubleConverter x:Key="GridLengthToDoubleConverter"/></Window.Resources><Window.Styles><Style Selector="Button.blueBtn"><Setter Property="Foreground" Value="White"/><Setter Property="Background" Value="#4C7DF7"/><Setter Property="Height" Value="32"/><Setter Property="FontSize" Value="16"/><Setter Property="BorderBrush" Value="DarkGray"/><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="Button"><Border x:Name="containerBorder" BorderBrush="{TemplateBinding BorderBrush}" Background="#4C7DF7" CornerRadius="13"><ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" ></ContentPresenter></Border></ControlTemplate></Setter.Value></Setter></Style></Window.Styles><Grid  x:Name="RootGrid" RowDefinitions="Auto,*"  SizeChanged="RootGridSizeChanged"><Grid x:Name="TopGird"  Grid.Row="0" Height="2" Background="Black" PointerMoved="TopGridPointerMovedHandler"> </Grid><Grid Grid.Row="1"  Background="Black"><Grid.ColumnDefinitions><ColumnDefinition Width="*" /><ColumnDefinition Width="*" /></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition Height="*" /><RowDefinition Height="*" /></Grid.RowDefinitions><controls:VideoViewControl  Grid.Row="0" Grid.Column="0" x:Name="videoView"  DoubleTapped="VideoDoubleTappedHandler" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/><controls:VideoViewControl  Grid.Row="0" Grid.Column="1" x:Name="videoView1" DoubleTapped="VideoDoubleTappedHandler" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/><Image x:Name="imageArriva" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"   Stretch="Fill" DoubleTapped="ImageDoubleTappedHandler"></Image><Image x:Name="imageLeave" Grid.Row="1" Grid.Column="1"  HorizontalAlignment="Stretch" VerticalAlignment="Stretch"   Stretch="Fill" DoubleTapped="ImageDoubleTappedHandler" ></Image><Image x:Name="imageArriva_1" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"   Stretch="Fill" DoubleTapped="ImageDoubleTappedHandler"></Image><Image x:Name="imageLeave_1" Grid.Row="0"  Grid.Column="1"  HorizontalAlignment="Stretch" VerticalAlignment="Stretch"   Stretch="Fill" DoubleTapped="ImageDoubleTappedHandler" ></Image></Grid><Popup x:Name="NavMenuPopup" Placement="Top" PlacementTarget="{Binding ElementName=TopGird}" IsOpen="False" IsVisible="False"><Border x:Name="PopupBorder"  Background="#F0F8FF"  HorizontalAlignment="Stretch" VerticalAlignment="Stretch"><Grid x:Name="NavMenuGird" Background="Transparent" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" ColumnDefinitions="Auto,*,Auto" MinHeight="30" PointerExited="NavMenuPointerExitedHandler"><StackPanel Orientation="Horizontal" Grid.Column="0" HorizontalAlignment="Left"><Button Content="标记为来车信号" Margin="5" Classes="blueBtn" Width="125" x:Name="arrivalSignalButton" Click="ArrivalSignal_Click" DockPanel.Dock="Left" /><TextBox x:Name="searchStartTime" Watermark="取图开始日期" Text="" Height="32" /><TextBox x:Name="searchEndTime" Watermark="取图结束日期" Text="" Height="32" /><Button Content="标记为无车信号" Margin="5" Classes="blueBtn" Width="125" x:Name="leaveSignalButton" Click="LeaveSignal_Click" DockPanel.Dock="Left" /></StackPanel><Rectangle Grid.Column="1" Fill="Transparent"/><StackPanel Orientation="Horizontal" Grid.Column="2" HorizontalAlignment="Right"><Button Content="最近来车记录" Margin="5" Classes="blueBtn" Width="125" x:Name="showLastArrivalRecordButton" Click="ShowLastArrivalRecordClick" /><Button Content="来车记录查询" x:Name="showArrivalRecordButton" Margin="5" Classes="blueBtn" Width="125" Click="ShowArrivalRecordClick" /><Button Content="结束查询" x:Name="closeArrivalRecordButton" Margin="5" Classes="blueBtn" Width="125" Click="CloseArrivalRecordClick"/><Button Content="测试下载" x:Name="downLoadButton" Margin="5" Classes="blueBtn" Width="125" Click="DownLoadClick" IsVisible="False" /><Button Content="关闭系统" Margin="50,5,5,5" Classes="blueBtn" Width="125" Click="CloseAppClick" /></StackPanel></Grid></Border></Popup><Popup x:Name="ArrivalRecordPopup" Placement="Center" PlacementTarget="{Binding ElementName=RootGrid}" IsOpen="False" ><Border x:Name="ArrivalRecordPopupBorder"  Background="White"  HorizontalAlignment="Stretch" VerticalAlignment="Stretch"><controls:ArrivalRecordViewControl x:Name="arrivalRecordView"  HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/></Border></Popup></Grid>
</Window>
.axaml.cs代码
 public partial class MainWindow : Window{public MainWindow()
{InitializeComponent();this.Loaded += async (sender, e) =>{string url = $"rtsp://用户名:密码@IP/LiveMedia/ch1/Media1";SetVideoViewUrl("videoView", url, "");url = $"rtsp://用户名:密码@IP/LiveMedia/ch1/Media1";SetVideoViewUrl("videoView1", url, "");};}public async void SetVideoViewUrl(string videoViewControlName, string url, string playBackTipContent, int type = 0, bool isPlayBackTip = false)
{_ = Task.Run(async () =>{await Dispatcher.UIThread.InvokeAsync(() =>{var _videoView = this.FindControl<VideoViewControl>(videoViewControlName);if (_videoView != null){_videoView.Url = url;_videoView.Type = type;_videoView.PlayBackTipContent = playBackTipContent;_videoView.IsPlayBackTip = isPlayBackTip;}});});
}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/3319.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

51.WPF应用加图标指南 C#例子 WPF例子

完整步骤&#xff1a; 先使用文心一言生成一个图标如左边使用Windows图片编辑器编辑&#xff0c;去除背景使用正方形&#xff0c;放大图片使图标铺满图片使用格式工程转换为ico格式&#xff0c;分辨率为最大 在资源管理器中右键项目添加ico类型图片到项目里图片属性设置为始终…

C++(二十一)

前言&#xff1a; 本文承接上文&#xff0c;将详细讲解指针概念。 一&#xff0c;通过指针了解变量的数值。 在将变量地址存入指针后&#xff0c;从指针反推也可以知道原变量的值&#xff0c;若想进行反退&#xff0c;就需要使用间接引用运算符&#xff1a;*。 语法&#x…

Redis 性能优化:多维度技术解析与实战策略

文章目录 1 基准性能2 使用 slowlog 优化耗时命令3 big key 优化4 使用 lazy free 特性5 缩短键值对的存储长度6 设置键值的过期时间7 禁用耗时长的查询命令8 使用 Pipeline 批量操作数据9 避免大量数据同时失效10 客户端使用优化11 限制 Redis 内存大小12 使用物理机而非虚拟机…

网络安全面试题汇总(个人经验)

1.谈一下SQL主从备份原理&#xff1f; 答&#xff1a;主将数据变更写入自己的二进制log,从主动去主那里去拉二进制log并写入自己的二进制log,从而自己数据库依据二进制log内容做相应变更。主写从读 2.linux系统中的计划任务crontab配置文件中的五个星星分别代表什么&#xff…

从AI生成内容到虚拟现实:娱乐体验的新边界

引言 在快速发展的科技时代&#xff0c;娱乐行业正经历一场前所未有的变革。传统的娱乐方式正与先进技术融合&#xff0c;创造出全新的沉浸式体验。从AI生成的个性化内容&#xff0c;到虚拟现实带来的身临其境的互动场景&#xff0c;科技不仅改变了我们消费娱乐的方式&#xf…

爬虫基础学习

什么是爬虫: 通过编写程序&#xff0c;模拟浏览器上网&#xff0c;然后让其去互联网上抓取数据的过程。 爬虫的价值: 实际应用就业 爬虫究竟是合法还是违法的? 在法律中是不被禁止具有违法风险善意爬虫 恶意爬虫 爬虫带来的风险可以体现在如下方面: 爬虫干扰了被访问网…

wireshark抓路由器上的包 抓包路由器数据

文字目录 抓包流程概述设置抓包配置选项 设置信道设置无线数据包加密信息设置MAC地址过滤器 抓取联网过程 抓包流程概述 使用Omnipeek软件分析网络数据包的流程大概可以分为以下几个步骤&#xff1a; 扫描路由器信息&#xff0c;确定抓包信道&#xff1b;设置连接路由器的…

第34天:Web开发-PHP应用鉴别修复AI算法流量检测PHP.INI通用过滤内置函数

#知识点 1、安全开发-原生PHP-PHP.INI安全 2、安全开发-原生PHP-全局文件&单函数 3、安全开发-原生PHP-流量检测&AI算法 一、通用-PHP.INI设置 参考&#xff1a; https://www.yisu.com/ask/28100386.html https://blog.csdn.net/u014265398/article/details/109700309 …

Python爬虫学习前传 —— Python从安装到学会一站式服务

早上好啊&#xff0c;大佬们。我们的python基础内容的这一篇终于写好了&#xff0c;啪唧啪唧啪唧…… 说实话&#xff0c;这一篇确实写了很久&#xff0c;一方面是在忙其他几个专栏的内容&#xff0c;再加上生活学业上的事儿&#xff0c;确实精力有限&#xff0c;另一方面&…

【Flink系列】6. Flink中的时间和窗口

6. Flink中的时间和窗口 在批处理统计中&#xff0c;我们可以等待一批数据都到齐后&#xff0c;统一处理。但是在实时处理统计中&#xff0c;我们是来一条就得处理一条&#xff0c;那么我们怎么统计最近一段时间内的数据呢&#xff1f;引入“窗口”。 所谓的“窗口”&#xff…

《汽车维修技师》是什么级别的期刊?是正规期刊吗?能评职称吗?

​问题解答&#xff1a; 问&#xff1a;《汽车维修技师》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的正规学术期刊。 问&#xff1a;《汽车维修技师》级别&#xff1f; 答&#xff1a;省级。主管单位&#xff1a;北方联合出版传媒&#xff08;…

HTML中如何保留字符串的空白符和换行符号的效果

有个字符串 储值门店{{thing3.DATA}}\n储值卡号{{character_string1.DATA}}\n储值金额{{amount4.DATA}}\n当前余额{{amount5.DATA}}\n储值时间{{time2.DATA}} &#xff0c; HTML中想要保留 \n的换行效果的有下面3种方法&#xff1a; 1、style 中 设置 white-space: pre-lin…

Git在码云上的使用指南:从安装到推送远程仓库

目录 目录 前言&#xff1a; 1、git的安装 1.1.Linux-centos环境下安装 1.2.Linux-ubuntu环境下安装 2.创建Git本地仓库 3.配置Git 4.认识⼯作区、暂存区、版本库 5.添加文件 5.1.git命令 5.2.commit命令 6.远程操作 6.1.新建远程仓库 6.2.克隆远程仓库&#xff…

群论学习笔记

什么是对称&#xff1f; 对称是一个保持对象结构不变的变换&#xff0c;对称是一个过程&#xff0c;而不是一个具体的事物&#xff0c;伽罗瓦的对称是对方程根的置换&#xff0c;而一个置换就是对一系列事物的重排方式&#xff0c;严格的说&#xff0c;它也并不是这个重排本身…

联通用户管理系统(一)

#联通用户管理系统&#xff08;一&#xff09; 1.新建项目 如果你是windows的话&#xff0c;界面应该是如下的&#xff1a; 2.创建app python manage.py startapp app01一般情况下&#xff1a;我们是在pycharm的终端中运行上述指令&#xff0c;但是pychrm中为我们提供了工具…

.Net Core微服务入门全纪录(二)——Consul-服务注册与发现(上)

系列文章目录 1、.Net Core微服务入门系列&#xff08;一&#xff09;——项目搭建 2、.Net Core微服务入门全纪录&#xff08;二&#xff09;——Consul-服务注册与发现&#xff08;上&#xff09; 3、.Net Core微服务入门全纪录&#xff08;三&#xff09;——Consul-服务注…

在 macOS 上,用命令行连接 MySQL(/usr/local/mysql/bin/mysql -u root -p)

根据你提供的文件内容&#xff0c;MySQL 的安装路径是 /usr/local/mysql。要直接使用 mysql 命令&#xff0c;你需要找到 mysql 可执行文件的路径。 在 macOS 上&#xff0c;mysql 客户端通常位于 MySQL 安装目录的 bin 子目录中。因此&#xff0c;完整的路径应该是&#xff1…

春秋杯-WEB

SSTI 可以看到主页那里有个登录测试之后为ssti {{4*4}} fenjing梭哈即可得到payload {{((g.pop.__globals__.__builtins__.__import__(os)).popen(cat flag)).read()}}file_copy 看到题目名字为file_copy&#xff0c; 当输入路径时会返回目标文件的大小&#xff0c; 通…

记录一次微信小程序使用云能力开发的过程

对于开发微信小程序云开发不知从何起的同学们&#xff0c;可以当作一次参考。虽说官方有文档&#xff0c;有模板示例&#xff0c;但是这些都是片段或者完整的结果展示。对于初学或者开发经验较少的同学们&#xff0c;可能不知先从那里入手进行第一步的开发。下面解析下构建微信…

doc、pdf转markdown

国外的一个网站可以&#xff1a; Convert A File Word, PDF, JPG Online 这个网站免费的&#xff0c;算是非常厚道了&#xff0c;但是大文件上传多了之后会扛不住 国内的一个网站也不错&#xff1a; TextIn-AI智能文档处理-图像处理技术-大模型加速器-在线免费体验 https://…