当前位置: 首页 > news >正文

C# Avalonia 06 - Controls- MediaElement

C# Avalonia没有内置的MediaElement,我们用LibVLC实现一个就行了。配置文章里更新了。https://www.cnblogs.com/dalgleish/p/18967204

MediaElement类,实现了播放器大多数功能。

    public class MediaElement : UserControl, IDisposable{private readonly LibVLC libVLC;private readonly VideoView videoView;private uint videoWidth;private uint videoHeight;public event EventHandler? Paused;public event EventHandler? Stopped;public event EventHandler? Playing;public event EventHandler? VolumeChanged;public event EventHandler? TimeChanged;public event EventHandler? LengthChanged;public event EventHandler? Muted;public event EventHandler? Unmuted;public event EventHandler? Buffering;public static readonly StyledProperty<Uri> SourceProperty =AvaloniaProperty.Register<MediaElement, Uri>(nameof(Source));public Uri Source{get => GetValue(SourceProperty);set => SetValue(SourceProperty, value);}public static readonly StyledProperty<MediaPlayer> MediaPlayerProperty =AvaloniaProperty.Register<MediaElement, MediaPlayer>(nameof(MediaPlayer));public MediaPlayer MediaPlayer{get => GetValue(MediaPlayerProperty);set => SetValue(MediaPlayerProperty, value);}public static readonly StyledProperty<int> VolumeProperty = AvaloniaProperty.Register<MediaElement, int>(nameof(Volume), 100);public int Volume{get => GetValue(VolumeProperty);set => SetValue(VolumeProperty, value);}public static readonly StyledProperty<bool> IsMutedProperty =  AvaloniaProperty.Register<MediaElement, bool>(nameof(IsMuted), false);public bool IsMuted{get => GetValue(IsMutedProperty);set => SetValue(IsMutedProperty, value);}public static readonly StyledProperty<long> TimeProperty =AvaloniaProperty.Register<MediaElement, long>(nameof(Time), 0L);public long Time{get => GetValue(TimeProperty);set => SetValue(TimeProperty, value);}public static readonly StyledProperty<float> RateProperty =  AvaloniaProperty.Register<MediaElement, float>(nameof(Rate), 1.0f);public float Rate{get => GetValue(RateProperty);set => SetValue(RateProperty, value);}public static readonly StyledProperty<int> SpuProperty =AvaloniaProperty.Register<MediaElement, int>(nameof(Spu), -1);public int Spu{get=> GetValue(SpuProperty);set => SetValue(SpuProperty, value);}public static readonly StyledProperty<Stretch> StretchProperty = AvaloniaProperty.Register<MediaElement, Stretch>(nameof(Stretch), Stretch.Fill);public Stretch Stretch{get => GetValue(StretchProperty);set => SetValue(StretchProperty, value);}public static readonly StyledProperty<string> AspectRatioProperty =AvaloniaProperty.Register<MediaElement, string>(nameof(AspectRatio));public string AspectRatio{get => GetValue(AspectRatioProperty);set => SetValue(AspectRatioProperty, value);}public MediaElement(){Core.Initialize();if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))libVLC = new LibVLC("--directx-use-sysmem", "--network-caching=2000");elselibVLC = new LibVLC("--network-caching=2000");/*
#if DEBUGlibVLC.Log += (sender, e) =>{Console.WriteLine($"[LibVLC 日志][{e.Level}] {e.Module}: {e.Message}");};
#endif*/MediaPlayer = new MediaPlayer(libVLC);videoView = new VideoView(){MediaPlayer = MediaPlayer};this.Content = videoView;this.GetObservable(SourceProperty).Subscribe(s => OnSourceChanged(s));this.GetObservable(MediaPlayerProperty).Subscribe(m => OnMediaPlayerChanged(m));this.GetObservable(RateProperty).Subscribe(r => MediaPlayer.SetRate(r));this.GetObservable(SpuProperty).Subscribe(s => MediaPlayer.SetSpu(s));this.GetObservable(BoundsProperty).Subscribe(_ => ScheduleApplyStretch());}public bool IsPlaying => MediaPlayer.IsPlaying;public void Play() => MediaPlayer.Play();public bool CanPlay() => !MediaPlayer.IsPlaying;public void Stop() => MediaPlayer.Stop();public bool CanStop() => MediaPlayer.IsPlaying;public void Pause() => MediaPlayer.Pause();public bool CanPause() => MediaPlayer.IsPlaying;public void TogglePlayPause(){if (MediaPlayer.IsPlaying){MediaPlayer.Pause();}else{MediaPlayer.Play();}}public void Mute() => IsMuted = true;public bool CanMute() => !IsMuted;public void Unmute() => IsMuted = false;public bool CanUnmute() => IsMuted;public void ToggleMute() => IsMuted = !IsMuted;public void ToggleCloseCaption(){if (Spu != -1)Spu = -1;elseSpu = 0;}public bool IsSeekable => MediaPlayer.IsSeekable;public long Length => MediaPlayer.Length;public void Download(){if (Source.Scheme != "avares")Process.Start(new ProcessStartInfo() { FileName = MediaPlayer.Media?.Mrl, UseShellExecute = true });}private void OnSourceChanged(Uri uri){if (uri == null) return;try{Media? media;if (uri.Scheme == "avares"){var stream = new StreamMediaInput(AssetLoader.Open(uri));media = new Media(libVLC, stream);}elsemedia = new Media(libVLC, uri);MediaPlayer.Media = media;media.ParsedChanged += (s, e) =>{foreach (var track in media.Tracks){if (track.TrackType == TrackType.Video){VideoTrack videoTrack = track.Data.Video;videoWidth = videoTrack.Width;videoHeight = videoTrack.Height;ScheduleApplyStretch();break;}}};}catch (Exception ex){Console.WriteLine("[MediaElement] 警告:媒体播放失败:" + ex.Message, ex);}}private void OnMediaPlayerChanged(MediaPlayer newPlayer){if (newPlayer == null){Console.WriteLine("[MediaElement] 警告:newPlayer不能为空.");return;}newPlayer.Paused += (s, e) => Paused?.Invoke(s, e);newPlayer.Stopped += (s, e) => Stopped?.Invoke(s, e);newPlayer.Playing += (s, e) => Playing?.Invoke(s, e);newPlayer.VolumeChanged += (s, e) => VolumeChanged?.Invoke(s, e);newPlayer.TimeChanged += (s, e) => TimeChanged?.Invoke(s, e);newPlayer.LengthChanged += (s, e) => LengthChanged?.Invoke(s, e);newPlayer.Muted += (s, e) => Muted?.Invoke(s, e);newPlayer.Unmuted += (s, e) => Unmuted?.Invoke(s, e);newPlayer.Buffering += (s, e) => Buffering?.Invoke(s, e);newPlayer.EndReached += (s, e) => ThreadPool.QueueUserWorkItem(_ =>{newPlayer.Stop();newPlayer.Time = 0;});this.Bind(VolumeProperty, new Binding("Volume") { Source = newPlayer, Mode = BindingMode.TwoWay });this.Bind(IsMutedProperty, new Binding("Mute") { Source = newPlayer, Mode = BindingMode.TwoWay });this.Bind(TimeProperty, new Binding("Time") { Source = newPlayer, Mode = BindingMode.TwoWay });this.Bind(AspectRatioProperty, new Binding("AspectRatio") { Source = newPlayer, Mode = BindingMode.TwoWay });}private void ScheduleApplyStretch(){Dispatcher.UIThread.Post(() =>{if (videoWidth <= 0 || videoHeight <= 0){videoView.Width = double.NaN;videoView.Height = double.NaN;videoView.HorizontalAlignment = HorizontalAlignment.Stretch;videoView.VerticalAlignment = VerticalAlignment.Stretch;return;}var availableWidth = this.Bounds.Width;var availableHeight = this.Bounds.Height;if (availableWidth <= 0 || availableHeight <= 0)return;double aspectVideo = (double)videoWidth / videoHeight;double aspectContainer = availableWidth / availableHeight;switch (Stretch){case Stretch.None:AspectRatio = $"{videoWidth}:{videoHeight}";videoView.Width = videoWidth;videoView.Height = videoHeight;videoView.HorizontalAlignment = HorizontalAlignment.Left;videoView.VerticalAlignment = VerticalAlignment.Top;break;case Stretch.Fill:AspectRatio = $"{availableWidth}:{availableHeight}";videoView.Width = availableWidth;videoView.Height = availableHeight;videoView.HorizontalAlignment = HorizontalAlignment.Stretch;videoView.VerticalAlignment = VerticalAlignment.Stretch;break;case Stretch.Uniform:AspectRatio = $"{videoWidth}:{videoHeight}";if (aspectContainer > aspectVideo){videoView.Height = availableHeight;videoView.Width = availableHeight * aspectVideo;}else{videoView.Width = availableWidth;videoView.Height = availableWidth / aspectVideo;}videoView.HorizontalAlignment = HorizontalAlignment.Center;videoView.VerticalAlignment = VerticalAlignment.Center;break;case Stretch.UniformToFill:if (aspectContainer > aspectVideo){AspectRatio = $"{availableWidth}:{(int)availableWidth / aspectVideo}";videoView.Width = availableWidth;videoView.Height = availableWidth / aspectVideo;}else{AspectRatio = $"{(int)availableHeight * aspectVideo}:{availableHeight}";videoView.Height = availableHeight;videoView.Width = availableHeight * aspectVideo;}videoView.HorizontalAlignment = HorizontalAlignment.Center;videoView.VerticalAlignment = VerticalAlignment.Center;break;}});}public void Dispose(){MediaPlayer?.Dispose();libVLC?.Dispose();}}

AssemblyResources.axaml代码

<Window 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"Height="300" Width="300"x:Class="AvaloniaUI.AssemblyResources"Title="AssemblyResources"><!--https://github.com/videolan/libvlcsharp/tree/3.x--><Grid RowDefinitions="*,auto"><MediaElement Name="Sound" Source="avares://AvaloniaUI/Resources/Sounds/金刚经.mp4"/><StackPanel Grid.Row="1"><Button Name="Play" Click="cmdPlay_Click" Content="Play"><Button.Background><ImageBrush Source="avares://AvaloniaUI/Resources/Images/Blue hills.jpg" Stretch="Fill"/></Button.Background></Button></StackPanel></Grid>
</Window>

AssemblyResources.axaml.cs代码

using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
using Shares.Avalonia;
using System;namespace AvaloniaUI;public partial class AssemblyResources : Window
{public AssemblyResources(){InitializeComponent();}private void cmdPlay_Click(object? sender, RoutedEventArgs e){var uri = new Uri("avares://AvaloniaUI/Resources/Images/Winter.jpg");using var stream = AssetLoader.Open(uri);Play.Background = new ImageBrush() { Source = new Bitmap(stream), Stretch = Stretch.Fill };Sound.Play();}
}

运行效果

image

 

http://www.vanclimg.com/news/2584.html

相关文章:

  • 学习笔记《莫比乌斯反演》
  • 惯性导航+DVL的组合导航算法
  • CVE-2016-5385 CGI 应用环境变量注入漏洞 (复现)
  • spring和Mybatis的逆向工程
  • 解决keil使用UTF-8乱码问题,兼容UTF-8编码,但keil显示不乱码的解决方案
  • 解决MySQL删除/var/lib/mysql下的所有文件后无法启动的问题
  • godot 二维报表库
  • EG800KCN移远4G模块wifiscan辅助定位
  • 基于小波分析和TV非凸模型的图像去模糊去噪算法
  • Ubuntu24.04体验Qwen3-Coder
  • 实验室检测仪器数据采集监控联网
  • Adobe InDesign 2025(id2025)安装教程-附mac+win安装包
  • IC验证常见88道
  • 【JPCS出版】第六届先进材料与智能制造国际学术会议(ICAMIM 2025)
  • html5代码片段
  • DevOps 平台选择参考:Gitee 的功能特性与适用情况解析
  • 图像生成-概率密度函数的变量变换--05 - jack
  • Webstorm 和 Intellij Idea 最新版 Git 本地修改丢失,手工开启 git 的 Local Changes
  • Java核心类——2.StringBuilder
  • 提高组线段树汇总
  • Lock 、 Monitor 、SemaphoreSlim 以及await一起
  • 还在用网闸做跨网文件交换?2025年该升级了!
  • 部署分布式版本控制系统git,gitlab
  • DP - 数位 dp
  • 记Codes 研发项目管理平台——拖拽式无代码CICD 创新实现
  • 利用改进遗传算法进行大地电磁视电阻率反演
  • 移远4G EG800K-CN 关于基站定位
  • 安全围栏
  • linux查看so接口函数 - 河北大学
  • Linux执行程序脚本,以及自动生成相关脚本