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();} }
运行效果

