LibVLCSharp.WPF简介

从vlc说起

LibVLC支持的平台:

平台 LibVLC包 Nuget地址 最低操作系统版本
Windows VideoLAN.LibVLC.Windows https://www.nuget.org/packages/VideoLAN.LibVLC.Windows/ Windows XP
UWP VideoLAN.LibVLC.UWP https://www.nuget.org/packages/VideoLAN.LibVLC.UWP/ Windows 10
Mac VideoLAN.LibVLC.Mac https://www.nuget.org/packages/VideoLAN.LibVLC.Mac/ macOS 10.7
Android VideoLAN.LibVLC.Android https://www.nuget.org/packages/VideoLAN.LibVLC.Android/ Android 2.3
iOS VideoLAN.LibVLC.iOS https://www.nuget.org/packages/VideoLAN.LibVLC.iOS/ iOS 8.4
tvOS VideoLAN.LibVLC.tvOS https://www.nuget.org/packages/VideoLAN.LibVLC.tvOS/ tvOS 10.2
Linux LinuxGuide:https://code.videolan.org/videolan/LibVLCSharp/-/blob/3.x/docs/linux-setup.md
  • LibVLCSharp是对LibVLC的封装,相当于一个包装器,提供给C#开发人员使用LibVLC的功能。地址:https://code.videolan.org/videolan/LibVLCSharp

  • LibVLCSharp.WPF是LibVLCSharp的WPF实现,封装了vlc:VideoView 这个UI控件,用来播放视频。 LibVLCSharp.WPF可以在.NETCoreApp 3.1 ;.NETFramework 4.6.1+; net6.0+运行时中使用。

虽然 LibVLCSharp 提供跨平台的解决方案,但是本文主要基于 Windows 平台来讨论。

vlc:VideoView基本使用

安装LibVLC

在使用LIibVLCSharp.WPF前必须先安装 LibVLC,否则会报如下错误:


//报错位置:实例化 LibVLC
 LibVLC    _libvlc=new LibVLC(); //Message:
Failed to load required native libraries.
Have you installed the latest LibVLC package from nuget for your target platform?
Search paths include E:\code\WPF\APngApp\bin\Debug\net7.0-windows\libvlc\win-x64\libvlc.dll,E:\code\WPF\APngApp\bin\Debug\net7.0-windows\libvlc\win-x64\libvlccore.dll; E:\code\WPF\APngApp\bin\Debug\net7.0-windows\libvlc\win-x64\libvlc.dll,E:\code\WPF\APngApp\bin\Debug\net7.0-windows\libvlc\win-x64\libvlccore.dll; E:\code\WPF\APngApp\bin\Debug\net7.0-windows\libvlc.dll,

LibVLC安装方式:

  • 集成安装:LibVLC 已经打包成了一个package,放在了nuget上面,只需要在项目中安装此VideoLAN.LibVLC.Windows依赖就可以。nuget安装命令:NuGet\Install-Package VideoLAN.LibVLC.Windows

播放rtsp

新建 wpf 应用程序

引入命名空间


xmlns:vlc="clr-namespace:LibVLCSharp.WPF;assembly=LibVLCSharp.WPF"

xaml 代码


<vlc:VideoView x:Name="video_main" >
......
</vlc:VideoView>

cs代码


private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
    LibVLC _libvlc = new LibVLC();
    LibVLCSharp.Shared.MediaPlayer player = new LibVLCSharp.Shared.MediaPlayer(_libvlc);
    video_main.Width = this.Width;
    video_main.Height = this.Height;
    video_main.MediaPlayer = player;
    //通过设置宽高比为窗体宽高可达到视频铺满全屏的效果
    player.AspectRatio = this.Width + ":" + this.Height;
    string url = "rtsp://user:password@192.168.1.120:554/ch1/main/av_stream";
    using (LibVLCSharp.Shared.Media media = new Media(_libvlc, new Uri(url)))
    {
        video_main.MediaPlayer.Play(media);
    }
}

截图

概述

LibVLCSharp是对 vlc 的封装,而vlc本身就支持截图的功能,相应的LibVLCSharp也提供了一个 MediaPlayer.TakeSnapshot 的方法用来截图

调用该方法需要传递的参数:

  • num:视频输出数量(通常第一个/仅一个为0)【直译过来的,这个参数具体什么意思尚不太清楚,当前是直接传0】
  • filePath:图片文件存放路径,需要确保文件夹存在并有访问权限,如:D:\A\2.png
  • width:图片的宽度
  • height:图片的高度
  • 若宽高都为0,则生成的图片为视频原始大小;若宽为0或者高为0,则生成的图片为视频原始的纵横比

代码示例

在页面添加一个按钮,在按钮点击事件中处理截图。

xaml:


<Label  Width="70"  Height="70" Margin="5,0,5,0" Name="snapshot" MouseLeftButtonDown="snapshot_MouseLeftButtonDown"  Cursor="Hand">
<Label.Background>
    <ImageBrush ImageSource="/Images/small_video_hide.png" Stretch="Uniform"/>
</Label.Background>
</Label>

cs:



private void snapshot_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    string dirPath = AppDomain.CurrentDomain.BaseDirectory+ "\\snapshot\\";
    //string dirPath = "D:\\A\\";
    string imgName = DateTime.Now.Ticks+ ".png";
    string filePath = dirPath + imgName;
    bool r = this.video_main.MediaPlayer.TakeSnapshot(0, filePath, (uint)this.video_main.Width, (uint)this.video_main.Height);
}
  • video_main 就是 VideoView 控件的name

vlc:VideoView进阶使用

空域问题

由于VideoView控件的实现原理是在window上面绑定一个前台窗体(ForegroudWindow),然后在ForegroudWindow中播放视频,所以当需要在window中添加其他控件(如:label,button......)的时候不可以使用WPF原始的“并列”写法,而需要使用“层级”写法,即将需要展示的控件写在VideoView控件的"里面",他们形成父子级关系。

上述文字可能比较难以理解, 用代码来分析。首先通过编写如下代码,让视频播放起来:

xaml:


<Window x:Class="APngApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        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.WPF;assembly=LibVLCSharp.WPF"
        xmlns:local="clr-namespace:APngApp"
        mc:Ignorable="d"
       
        xmlns:apngPlayer="clr-namespace:ImoutoRebirth.Navigator.ApngWpfPlayer.ApngPlayer;assembly=ImoutoRebirth.Navigator.ApngWpfPlayer"
        Title="MainWindow" Height="1200" Width="2300" Loaded="Window_Loaded">
    <Grid>
        <DockPanel>
            <vlc:VideoView Name="videoView">
<Button x:Name="btn_test" Width="200" Height="100"  Content="我是一个测试用的按钮" >
</Button>
</vlc:VideoView>
        </DockPanel>
    </Grid>
</Window>

cs:


using LibVLCSharp.Shared;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace APngApp
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private LibVLC _libvlc;
        public MainWindow()
        {
            InitializeComponent();
            _libvlc=new LibVLC();
        }
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            LibVLCSharp.Shared.MediaPlayer player = new LibVLCSharp.Shared.MediaPlayer(_libvlc);
     
            videoView.MediaPlayer = player;
   
            using (LibVLCSharp.Shared.Media media = new Media(_libvlc, new Uri("rtsp://xxx:xxx@192.168.1.120:554/ch1/main/av_stream")))
            {
                videoView.MediaPlayer.Play(media);
            }
        }
    }
}

如果一切正常,将看到如下的画面,并且在VS实时可视化树中将看到 ForegroudWindow 和 MainWindow。

  • 可以看到虽然我们仅仅创建了一个MainWindow,但是确实有两个窗体存在,VideoView控件为程序生成了一个ForegroudWindow。
  • 当我们在VideoView内部编写一个button控件的时候,控件正确的显示出来了,如果我们将这个button移动到和vlc:VideoView并列的位置,按钮将不会显示出来,因为它被ForegroudWindow遮住了,这很诡异,也很有趣,这里就不列举并列写法的代码了。
  • 官方(videolan)把这种情况总结为空域问题,即 Airspace。
  • 不难看出来VideoView控件的这种设计有悖常理,但是据说这是由于LibVLC和vlc的局限性导致的,属于妥协式设计。但是大可放心使用,LibVLCSharp这套解决方案使用非常的广泛,而且截至目前(2023)官方issues仍非常活跃,并且版本也在不断更新中。官方也提供商业版本和付费的技术支持。

宽高比设置

宽高比设置是一个非常神奇的功能,它可以解决:

  • 想让画面全屏显示却出现了间隙,这里的间隙是指画面没有完全覆盖窗体。
  • 想要挤压或者拉伸画面却不知道如何实现。
  • 在异形屏幕上面全屏显示画面,如:画面比例是16:9,想要在分辨率为5:5的屏幕上面全屏显示画面
  • 其他宽高比问题,实际生产中,画面宽高比和屏幕宽高比都是不固定的,甚至可以说很随意,比如海康全景相机,其输出的画面本身就是宽度远高于高度,再比如同一个WPF程序需要在分辨率为1366768和25601440的屏幕分辨率下面全屏显示
  • 这里提到的画面是指rtsp源本身的画面大小

通过如下代码和现象可以很直观的观察到宽高比的神奇之处。

全屏问题

环境:Windows11,屏幕分辨率为2560*1440,未设置缩放

  • 新建一个WPF的窗体,引入VideoView控件,并在Window_ContentRendered 事件中初始化 MediaPlayer 以播放rtsp流。

  • 为尽可能排除其他因素对本问题的影响,将对窗体和VideoView控件做如下初始化设置:

    • 窗体的WindowStyle=None
    • 窗体的ResizeMode=NoResize
    • 窗体的AllowTransparency=true
    • 设置窗体初始宽高为屏幕工作区域,即不包括任务栏部分,此时实际高度小于1440
    • 设置video控件的 宽高为窗体的宽高

xaml代码:


<Window x:Class="RambleWPF.视频控件3"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        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:local="clr-namespace:RambleWPF"
        mc:Ignorable="d"
        Title="视频控件3" Height="450" Width="800"
       
       
        xmlns:vlc="clr-namespace:LibVLCSharp.WPF;assembly=LibVLCSharp.WPF" ContentRendered="Window_ContentRendered"
        Name="win"
        >
    <Window.Resources>
        <Style x:Key="BtnInfoStyle" TargetType="Button">
            <Setter Property="Width" Value="70"/>
            <Setter Property="Height" Value="25"/>
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="Background" Value="#43a9c7"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="True">
                            <TextBlock Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                        </Border>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="border" Property="Background" Value="#2f96b4"/>
                            </Trigger>
                            <Trigger Property="IsPressed" Value="True">
                                <Setter TargetName="border" Property="Background" Value="#2a89a4"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <vlc:VideoView Name="video"   >
           
        </vlc:VideoView>
    </Grid>
</Window>

cs:


using LibVLCSharp.Shared;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace RambleWPF
{
    /// <summary>
    /// 视频控件3.xaml 的交互逻辑
    /// </summary>
    public partial class 视频控件3 : Window
    {
        readonly LibVLC _libvlc;
        public 视频控件3()
        {
            InitializeComponent();
            _libvlc = new LibVLC();
            this.WindowStyle = WindowStyle.None;
            ResizeMode = ResizeMode.NoResize;
            AllowsTransparency = true;
            //工作区域就是不包括任务栏的其他区域
            double x = SystemParameters.WorkArea.Width;
            //得到屏幕工作区域宽度
            double y = SystemParameters.WorkArea.Height;
            win.Width = x;
            win.Height = y;
            win.Top = 0;
            win.Left = 0;
            video.Width = x;
            video.Height = y;
        }
        private void Window_ContentRendered(object sender, EventArgs e)
        {
            string url = "rtsp://xxx:xxx@192.168.1.120:554/ch1/main/av_stream";
            LibVLCSharp.Shared.MediaPlayer player = new LibVLCSharp.Shared.MediaPlayer(_libvlc);
            video.MediaPlayer = player;
            using (LibVLCSharp.Shared.Media media = new Media(_libvlc, new Uri(url)))
            {
                video.MediaPlayer.Play(media);
            }
        }
    }
}

此时启动程序,如果不出意外,将看到如下的存在“间隙”的画面:

可以看到虽然在初始化的时候我们显示指定了video控件的宽高等于窗体的宽高,但是由于rtsp视频源的画面宽高比和窗体的宽高比不一致,所以出现了“间隙”。要如何解决此问题呢?只需要在Window_ContentRendered中主动设置video.MediaPlayer的宽高比为video控件的宽高即可。

修改后的 Window_ContentRendered 是这样的:


private void Window_ContentRendered(object sender, EventArgs e)
{
    string url = "rtsp://xxx:xxx@192.168.1.120:554/ch1/main/av_stream";
    LibVLCSharp.Shared.MediaPlayer player = new LibVLCSharp.Shared.MediaPlayer(_libvlc);
    video.MediaPlayer = player;
    using (LibVLCSharp.Shared.Media media = new Media(_libvlc, new Uri(url)))
    {
        video.MediaPlayer.Play(media);
    }
    player.AspectRatio = video.Width + ":" + video.Height;
}

修改后的画面是这样的:

  • 可以看到间隙已经没有了,画面按照预期的方式显示了。

拉伸问题

环境:Windows11,屏幕分辨率为2560*1440,未设置缩放

通过对全屏问题的分析,拉伸问题其实就很好理解了,只需要设置特定的宽高比即可实现,如下代码将对画面纵向和横向进行拉伸


/// <summary>
/// 挤压和拉伸
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void extrusion_Click(object sender, RoutedEventArgs e)
{
    video.MediaPlayer.AspectRatio = this.Width + ":" + 100;
    //video.MediaPlayer.AspectRatio = 100 + ":" + video.Height;
}

响应鼠标点击事件

由于空域问题的存在,视频画面是无法响应鼠标点击事件的,不过有一个曲线救国的办法:

  • 首先设置videoView控件的 isEnable 属性为false
  • 然后在视频画面上面放一个遮罩层,遮罩层背景需要设置为透明,此时点击画面将可以获取到响应的事件

核心代码如下:

初始化VideoView:


private void Window_ContentRendered(object sender, EventArgs e)
{
    video.IsEnabled = false;
    string url = "rtsp://xxx:xxx@192.168.1.120:554/ch1/main/av_stream";
    LibVLCSharp.Shared.MediaPlayer player = new LibVLCSharp.Shared.MediaPlayer(_libvlc);
    video.MediaPlayer = player;
    using (LibVLCSharp.Shared.Media media = new Media(_libvlc, new Uri(url)))
    {
        video.MediaPlayer.Play(media);
    }
    player.AspectRatio = video.Width + ":" + video.Height;
   
}

遮罩层xaml:


<Grid x:Name="root_grid" MouseLeftButtonDown="root_grid_MouseLeftButtonDown"  >
     <vlc:VideoView Name="video"   MouseLeftButtonDown="video_MouseLeftButtonDown">        
     </vlc:VideoView>
     <Canvas x:Name="mask" Background="Transparent" MouseLeftButtonDown="mask_MouseLeftButtonDown"></Canvas>    
 </Grid>

其中,mask_MouseLeftButtonDown 和root_grid_MouseLeftButtonDown 事件可以正常响应。

而video_MouseLeftButtonDown 事件无法响应,因为空域的存在,此事件要么绑定在ForegroudWindow上面,要么可能就没有成功被委托。

播放其他类型

如下代码演示了播放M3U8和本地文件:


private void Window_ContentRendered(object sender, EventArgs e)
{
    video.IsEnabled = false;
    //rtsp 播放串
    //string url = "rtsp://xxx:xxx@192.168.1.120:554/ch1/main/av_stream";
    //m3u8播放串
    //string url = "http://1257120875.vod2.myqcloud.com/0ef121cdvodtransgzp1257120875/3055695e5285890780828799271/v.f230.m3u8";
    //播放文件
    string url = "C:\\Users\\cml\\Desktop\\temp\\流浪地球2.mp4";
    LibVLCSharp.Shared.MediaPlayer player = new LibVLCSharp.Shared.MediaPlayer(_libvlc);
    video.MediaPlayer = player;
    using (LibVLCSharp.Shared.Media media = new Media(_libvlc, new Uri(url)))
    {
        video.MediaPlayer.Play(media);
    }
    player.AspectRatio = video.Width + ":" + video.Height;
}

多视频重叠

在一个窗体中播放两个视频,一个在后,全屏显示,一个在前,小窗播放。并且点击按钮可以切换画面位置。效果如下:

实现思路:

  • 首先,其实只要在xaml中编排好VideoView控件的上下位置就可以实现重叠了 ,越靠上的控件会覆盖在靠下的控件上方。
  • 切换功能的实现需要分别销毁前后两个VideoView的MediaPlayer.Media对象,并重新创建。

代码如下:

xaml:


<Window x:Class="RambleWPF.视频控件2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        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:local="clr-namespace:RambleWPF"
       
        xmlns:vlc="clr-namespace:LibVLCSharp.WPF;assembly=LibVLCSharp.WPF"
        mc:Ignorable="d"
        Title="视频控件2" Height="450" Width="800"
        Name="win"
        Loaded="Window_Loaded"  ContentRendered="Window_ContentRendered"
        >
    <Canvas>
        <vlc:VideoView Name="small_video"   ></vlc:VideoView>
        <vlc:VideoView Name="main_video"   >
            <Button x:Name="switch" Content="切换" Width="80" Height="60" Canvas.Left="50" Click="switch_Click"></Button>
        </vlc:VideoView>
    </Canvas>
</Window>

cs:


using LibVLCSharp.Shared;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace RambleWPF
{
    /// <summary>
    /// 视频控件2.xaml 的交互逻辑
    /// </summary>
    public partial class 视频控件2 : Window
    {
        readonly LibVLC _libvlc;
        public 视频控件2()
        {
            InitializeComponent();
            _libvlc = new LibVLC();
            WindowStyle = WindowStyle.None;
            ResizeMode = ResizeMode.NoResize;
            AllowsTransparency = true;
            //工作区域就是不包括任务栏的其他区域
            double x = SystemParameters.WorkArea.Width;
            //得到屏幕工作区域宽度
            double y = SystemParameters.WorkArea.Height;
            win.Width = x;
            win.Height = y;
            win.Top = 0;
            win.Left = 0;
        }
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            Canvas.SetLeft(main_video, 100);
            Canvas.SetZIndex(main_video, 1);
            main_video.Width = 1366;
            main_video.Height = 768;
            Canvas.SetLeft(small_video, 150);
            Canvas.SetTop(small_video, 500);
            Canvas.SetZIndex(small_video, 2);
            small_video.Width = 300;
            small_video.Height = 168.75;
        }
        private void Window_ContentRendered(object sender, EventArgs e)
        {
            this.Tag = main_video.Name;
            string url = "rtsp://xxx:xxx@192.168.1.120:554/ch1/main/av_stream";
            LibVLCSharp.Shared.MediaPlayer player = new LibVLCSharp.Shared.MediaPlayer(_libvlc);
            main_video.MediaPlayer = player;
            using (LibVLCSharp.Shared.Media media = new Media(_libvlc, new Uri(url)))
            {
                main_video.MediaPlayer.Play(media);
            }
            string url2 = "rtsp://xxx:xxx@192.168.1.142:554/Streaming/Channels/1";
            LibVLCSharp.Shared.MediaPlayer player2 = new LibVLCSharp.Shared.MediaPlayer(_libvlc);
            small_video.MediaPlayer = player2;
            using (LibVLCSharp.Shared.Media media = new Media(_libvlc, new Uri(url2)))
            {
                small_video.MediaPlayer.Play(media);
            }
        }
        private void switch_Click(object sender, RoutedEventArgs e)
        {
            string url = "rtsp://xxx:xxx@192.168.1.120:554/ch1/main/av_stream";
            string url2 = "rtsp://xxx:xxx@192.168.1.142:554/Streaming/Channels/1";
            if (this.Tag as string != main_video.Name)
            {
                this.Tag = main_video.Name;
                using (LibVLCSharp.Shared.Media media = new Media(_libvlc, new Uri(url)))
                {
                    main_video.MediaPlayer.Play(media);
                }
                using (LibVLCSharp.Shared.Media media = new Media(_libvlc, new Uri(url2)))
                {
                    small_video.MediaPlayer.Play(media);
                }
            }
            else
            {
                this.Tag = small_video.Name;
                using (LibVLCSharp.Shared.Media media = new Media(_libvlc, new Uri(url2)))
                {
                    main_video.MediaPlayer.Play(media);
                }
                using (LibVLCSharp.Shared.Media media = new Media(_libvlc, new Uri(url)))
                {
                    small_video.MediaPlayer.Play(media);
                }
            }
        }
    }
}
  • small_video显示在前,为小屏;main_video显示在后,全屏显示

画中画

画中画本质上还是视频的重叠,可以参考视频重叠的实现思路实现。

引用

WPF中使用LibVLCSharp.WPF 播放rtsp的更多相关文章

  1. WPF中的MatrixTransform

    原文:WPF中的MatrixTransform WPF中的MatrixTransform                                                         ...

  2. WPF中timer的使用

    Timer控件/ System.Timers.Timer 不能用于WPF中.在WPF中,定时器为 DispatcherTimer. 使用方法如下: private DispatcherTimer ti ...

  3. WPF中的DoubleAnimation

    原文:WPF中的DoubleAnimation WPF中的DoubleAnimation                                                         ...

  4. WPF中实现验证码

    原文:WPF中实现验证码 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/m0_37591671/article/details/79563449 W ...

  5. 在wpf中如何让MediaElement的视频循环播放

    原文:在wpf中如何让MediaElement的视频循环播放 MediaElement原始的播放是只播放一遍:如何设置让MediaElement播放 的视频或者音频循环播放,解决如下: 修改Media ...

  6. Wpf中MediaElement循环播放

    原文:Wpf中MediaElement循环播放 前一段时间做了一个项目,里面牵涉到媒体文件的循环播放问题,在网上看了好多例子,都是在xaml中添加为MediaElement添加一个TimeLine,不 ...

  7. WPF中播放视频音频

    首先要在WPF中播放视频和音频,我们就需要用到MediaElement控件,下面我们示例播放音频和视频. 用MediaElement播放音频: 第一步:将你需要播放的音频(mp3)放在你WPF项目的D ...

  8. 示例:WPF中Slider控件封装的缓冲播放进度条控件

    原文:示例:WPF中Slider控件封装的缓冲播放进度条控件 一.目的:模仿播放器播放进度条,支持缓冲任务功能 二.进度: 实现类似播放器中带缓存的播放样式(播放区域.缓冲区域.全部区域等样式) 实现 ...

  9. WPF中的动画——(三)时间线(TimeLine)

    WPF中的动画——(三)时间线(TimeLine) 时间线(TimeLine)表示时间段. 它提供的属性可以让控制该时间段的长度.开始时间.重复次数.该时间段内时间进度的快慢等等.在WPF中内置了如下 ...

  10. WPF VlC 实现视频的播放(1)

    WPF 使用VLC实现视频的播放:网上开源代码我复制了一份:  https://github.com/someonehan/Vlc.DotNet 1. 准备阶段 (I)  libvlc.dll 和 l ...

随机推荐

  1. 我把 CPU 三级缓存的秘密,藏在这 8 张图里

    本文已收录到  GitHub · AndroidFamily,有 Android 进阶知识体系,欢迎 Star.技术和职场问题,请关注公众号 [彭旭锐] 进 Android 面试交流群. 前言 大家好 ...

  2. HTTPS - 揭秘 TLS 1.2 协议完整握手过程--此文为转发文,一定要结合wirshark工具看,很清楚

    winshark 筛选条件为:tls and ip.src==xxx 本文通过对一次 TLS 握手过程的数据抓包分析做为切入点,希望能进一步的帮助大家理解 HTTPS 原理. HTTPS 是建立在 S ...

  3. tomcat下载安装&配置教程

    tomcat下载安装&配置教程 1 安装jdk 1.1 安装jdk 1.2 安装JDK后设置环境变量 1.3 使环境变量生效 1.4 查看java版本 2 安装tomcat 2.1 在/usr ...

  4. 2流高手速成记(之九):基于SpringCloudGateway实现服务网关功能

    咱们接上回 上一节我们基于Sentinel实现了微服务体系下的限流和熔断,使得整个微服务架构的安全性和稳定性上升了一个台阶 篇尾我们引出了一个问题,众多的微服务节点,我们如何部署才能满足客户端简洁高效 ...

  5. Vue 双向绑定数据已经更新,但是视图更新:

    使用ElementUI做动态增减表单项的时候,发现数据刷新后视图未更新 Vue包装了数个数组操作函数,使用这些方法操作的数组去,其数据变动时会被vue监测: push() pop() shift() ...

  6. js中数组追加和删除

    1.push  往后追加 let arr=[1,2,3,4];arr.push(5);console.log(arr);//得到[1,2,3,4,5] 2.unshift方法 往前追加 let arr ...

  7. 多线程/GIL全局锁

    目录 线程理论 创建线程的两种方式 线程的诸多特性 GIL全局解释器 验证GIL存在 同一个进程下多线程是否有优势 死锁现象 信号量 Event事件 线程理论 进程 进程其实是资源单位 标示开辟一块内 ...

  8. 前端入门 HTTP协议 HTML简介 head内常见标签 body内常见标签 特殊符号 列表标签 表格标签 表单标签

    目录 前端和后端的概念 前端前戏之B/S架构 数据交互的协议 HTTP协议 1.四大特性 1. 基于请求响应 2. 基于TCP.IP作用与应用层之上的协议 3. 无状态 4. 无\短连接 2.数据格式 ...

  9. Windows 安装 Zookeeper 详细步骤

    Windows 安装 Zookeeper 详细步骤 一. Zookeeper 安装包下载 1.官网地址 Zookeeper官网 2.安装包下载 这里选择目前的稳定版 3.6.3 下载 可以看到有两个选 ...

  10. 网络监测工具之Zabbix的搭建与测试方法(二)-- SNMP、OID和MIB概述

    概念 SNMP是专门设计用于在 IP 网络管理网络节点的一种标准协议,它是一种应用层协议.SNMP使网络管理员能够管理网络效能,发现并解决网络问题以及规划网络增长.通过SNMP接收随机消息(及事件报告 ...