WPF下播放Rtmp的解决方案

news2024/11/20 2:44:33

介绍

在实际的开发过程中,需要在应用内部内嵌播放器进行视频的播放。官方默认的MediaElement控件只能播放有限的视频格式,也不能播放网络流。比较流行的解决方式是vlc的库,但是在实际使用过程中发现有很多问题。这里给大家推荐另一个比较好的库。

使用

官网地址

安装库

Nuget下安装FFME.Windows

PM> Install-Package FFME.Windows

下载ffmpeg依赖

注:官网给的地址我在实际使用中发现,使用官方的代码没问题,使用给定的步骤使用就会抱错,如果你们跟我一样给大家推荐另一个ffmpeg包的地址
ffmpeg依赖下载地址

代码

  1. 指定ffmpeg库的地址
Unosquare.FFME.Library.FFmpegDirectory = @"C:\ffmpeg\ffmpeg-4.4-windows-desktop-vs2022-gpl-lite\bin";
  1. xaml中插入控件
<Window x:Class="WpfApp1.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:local="clr-namespace:WpfApp1" 
        xmlns:ffme="clr-namespace:Unosquare.FFME;assembly=ffme.win"
        mc:Ignorable="d"
        Loaded="Window_Loaded"
        Closed="Window_Closed"
        Title="MainWindow" Height="300" Width="600">
    <Grid>
        <ffme:MediaElement x:Name="Media" Background="Gray" LoadedBehavior="Play" UnloadedBehavior="Manual" />
        <Button Content="Play" Click="PlayButton_Click" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="10"/>
        <Button Content="Stop" Click="StopButton_Click" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Margin="100,10,0,0"/>
    </Grid>
</Window>

  1. 监听失败的事件
Media.MediaFailed += OnMediaFailed;
  1. 创建一个处理流地址的类FileInputStream
namespace Unosquare.FFME.Windows.Sample.Foundation;

using Common;
using FFmpeg.AutoGen;
using System;
using System.IO;
using System.Runtime.InteropServices;

/// <inheritdoc />
/// <summary>
/// Provides an example of a very simple custom input stream.
/// </summary>
/// <seealso cref="IMediaInputStream" />
public sealed unsafe class FileInputStream : IMediaInputStream
{
    private readonly FileStream BackingStream;
    private readonly object ReadLock = new();
    private readonly byte[] ReadBuffer;

    /// <summary>
    /// Initializes a new instance of the <see cref="FileInputStream"/> class.
    /// </summary>
    /// <param name="path">The path.</param>
    public FileInputStream(string path)
    {
        var fullPath = Path.GetFullPath(path);
        BackingStream = File.OpenRead(fullPath);
        var uri = new Uri(fullPath);
        StreamUri = new Uri(uri.ToString().ReplaceOrdinal("file://", Scheme));
        CanSeek = true;
        ReadBuffer = new byte[ReadBufferLength];
    }

    /// <summary>
    /// The custom file scheme (URL prefix) including the :// sequence.
    /// </summary>
    public static string Scheme => "customfile://";

    /// <inheritdoc />
    public Uri StreamUri { get; }

    /// <inheritdoc />
    public bool CanSeek { get; }

    /// <inheritdoc />
    public int ReadBufferLength => 1024 * 16;

    /// <inheritdoc />
    public InputStreamInitializing OnInitializing { get; }

    /// <inheritdoc />
    public InputStreamInitialized OnInitialized { get; }

    /// <inheritdoc />
    public void Dispose()
    {
        BackingStream?.Dispose();
    }

    /// <summary>
    /// Reads from the underlying stream and writes up to <paramref name="targetBufferLength" /> bytes
    /// to the <paramref name="targetBuffer" />. Returns the number of bytes that were written.
    /// </summary>
    /// <param name="opaque">The opaque.</param>
    /// <param name="targetBuffer">The target buffer.</param>
    /// <param name="targetBufferLength">Length of the target buffer.</param>
    /// <returns>
    /// The number of bytes that have been read.
    /// </returns>
    public int Read(void* opaque, byte* targetBuffer, int targetBufferLength)
    {
        lock (ReadLock)
        {
            try
            {
                var readCount = BackingStream.Read(ReadBuffer, 0, ReadBuffer.Length);
                if (readCount > 0)
                    Marshal.Copy(ReadBuffer, 0, (IntPtr)targetBuffer, readCount);
                else if (readCount == 0)
                    return ffmpeg.AVERROR_EOF;

                return readCount;
            }
            catch (Exception)
            {
                return ffmpeg.AVERROR_EOF;
            }
        }
    }

    /// <inheritdoc />
    public long Seek(void* opaque, long offset, int whence)
    {
        lock (ReadLock)
        {
            try
            {
                return whence == ffmpeg.AVSEEK_SIZE ?
                    BackingStream.Length : BackingStream.Seek(offset, SeekOrigin.Begin);
            }
            catch
            {
                return ffmpeg.AVERROR_EOF;
            }
        }
    }
}

  1. 播放视频
//var target = new Uri(@"rtmp://127.0.0.1/live/test1231233");
var target = new Uri(@"D:\视频\泥坑.mp4");
if (target.ToString().StartsWith(FileInputStream.Scheme, StringComparison.OrdinalIgnoreCase))
    await Media.Open(new FileInputStream(target.LocalPath));
else
    await Media.Open(target);

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

esp32c3开发板通过micropython的mqtt库连MQTT物联网消息服务器

MQTT介绍 MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;是一种轻量级的消息协议&#xff0c;旨在设备之间进行通信&#xff0c;尤其是在网络条件较差的情况下。MQTT v3.1.1 和 MQTT v5 是该协议的两个主要版本。 MQTT v3.1.1&#xff1a; 优点&#xff…

2、 家庭网络发展现状

上一篇我们讲了了解家庭网络历史(https://blog.csdn.net/xld_hung/article/details/143639618?spm1001.2014.3001.5502),感兴趣的同学可以看对应的文章&#xff0c;本章我们主要讲家庭网络发展现状。 关于家庭网络发展现状&#xff0c;我们会从国内大户型和小户型的网络说起&…

element ui 走马灯一页展示多个数据实现

element ui 走马灯一页展示多个数据实现 element ui 走马灯一页展示多个数据实现 element ui 走马灯一页展示多个数据实现 主要是对走马灯的数据的操作&#xff0c;先看js处理 let list [{ i: 1, name: 1 },{ i: 2, name: 2 },{ i: 3, name: 3 },{ i: 4, name: 4 },]let newL…

linux文件与重定向

目录 一、共识原理 二、回顾C语言文件函数 1.fopen 2.fwrite 3.fclose 三、文件系统调用 1.open 2.write 3.访问文件的本质 4.stdin&&stdout&&stderror 5.文件的引用计数 四、重定向 1.文件描述符的分配规则 2. 输出重定向 3.重定向系统调用 4.…

CS DAC的Matlab建模与电路设计

在模拟电路设计的复杂世界里&#xff0c;每一个细节都至关重要。Current Steering DAC作为模拟数字转换的核心组件&#xff0c;其设计和性能优化一直是工程师们追求的目标。 “什么是Current Steering DAC&#xff1f; CS DAC通过控制电流源的开关&#xff0c;将数字输入信号…

网络传输:网卡、IP、网关、子网掩码、MAC、ARP、路由器、NAT、交换机

目录 网卡IP网络地址主机地址子网子网掩码网关默认网关 MACARPARP抓包分析 路由器NATNAPT 交换机 网卡 网卡(Network Interface Card&#xff0c;简称NIC)&#xff0c;也称网络适配器。 OSI模型&#xff1a; 1、网卡工作在OSI模型的最后两层&#xff0c;物理层和数据链路层。物…

STM32完全学习——系统时钟设置

一、时钟框图的解读 首先我们知道STM32在上电初始化之后使用的是内部的HSI未经过分频直接通过SW供给给系统时钟&#xff0c;由于内部HSI存在较大的误差&#xff0c;因此我们在系统完成上电初始化&#xff0c;之后需要将STM32的时钟切换到外部HSE作为系统时钟&#xff0c;那么我…

基于Java Springboot滁州市特产销售系统

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 数据…

H.265流媒体播放器EasyPlayer.js视频流媒体播放器关于直播流播放完毕是否能监听到

EasyPlayer属于一款高效、精炼、稳定且免费的流媒体播放器&#xff0c;可支持多种流媒体协议播放&#xff0c;无须安装任何插件&#xff0c;起播快、延迟低、兼容性强&#xff0c;使用非常便捷。 EasyPlayer.js播放器不仅支持H.264与H.265视频编码格式&#xff0c;也能支持WebS…

Ubuntu22.04基于ROS2-Humble安装moveit2教程(亲测)

一、安装ROS2-Humble 1、参考&#xff1a;Ubuntu22.04安装ROS2-humble-CSDN博客 2、确保安装完成 source /opt/ros/humble/setup.bash 方法一&#xff1a;二进制安装 sudo apt install ros-humble-moveit* 方法二&#xff1a;安装源码编译 一、卸载二进制安装包 sudo a…

SpringBoot学习记录(三)之多表查询

SpringBoot学习记录&#xff08;三&#xff09;之多表查询 一、多表查询概述1、数据准备2、介绍3、分类 二、内连接三、外连接四、子查询1、标量子查询2、列子查询3、行子查询4、表子查询 三、案例1、准备环境2、需求实现3、&#xff08;附&#xff09;数据准备 一、多表查询概…

Ubuntu 的 ROS 操作系统 turtlebot3 SLAM仿真

引言 SLAM&#xff08;同步定位与地图构建&#xff09;在Gazebo仿真环境中的应用能够模拟真实机器人进行环境建图和导航。通过SLAM仿真&#xff0c;开发者可以在虚拟环境中测试算法&#xff0c;而不必依赖真实硬件&#xff0c;便于调试与优化。 Gazebo提供了多个虚拟环境&…

TCP连接秘籍:三次握手建立连接,四次挥手优雅告别

在数字通信的广阔天地中&#xff0c;TCP协议如同一座稳固的桥梁&#xff0c;连接着网络世界的每一个角落。它不仅确保了数据的可靠传输&#xff0c;还通过精细设计的连接建立与断开机制&#xff0c;展现了其无与伦比的优雅与智慧。TCP的三次握手&#xff0c;犹如初次相遇时的礼…

【惠州大亚湾】之维修戴尔服务器DELLR730XD

1&#xff1a;广东省惠州市大亚湾某游客服务中心来电报修1台DELL PowerEdge R730xd服务器无法正常开机的问题。听该负责描述这台服务器因为服务中心电力切换导致意外关机&#xff0c;来电后发现就无法正常开机了。所以找到我们希望配合维修。 2&#xff1a;该机器由于特别着急…

常见网络厂商设备默认用户名/密码大全

常见网络厂商的默认用户名/密码 01 思科 (Cisco) 设备类型&#xff1a;路由器、交换机、防火墙、无线控制器 默认用户名&#xff1a;cisco 默认密码&#xff1a;cisco 设备类型&#xff1a;网管型交换机 默认用户名&#xff1a;admin 默认密码&#xff1a;admin 02 华…

PH热榜 | 2024-11-18

DevNow 是一个精简的开源技术博客项目模版&#xff0c;支持 Vercel 一键部署&#xff0c;支持评论、搜索等功能&#xff0c;欢迎大家体验。 在线预览 1. Momen 标语&#xff1a;快速搭建你的最小可行产品&#xff0c;然后扩展它&#xff0c;无需任何编程经验。 介绍&#xff…

LoFTR: Detector-Free Local Feature Matching with Transformers—特征点匹配算法系列

LoFTR: Detector-Free Local Feature Matching with Transformers 受到&#xff1a;受到开创性作品 SuperGlue 的启发 摘要总结&#xff1a; 提出了一种局部图像特征匹配的新方法。更为突出说明的是室内场景下的特征点的匹配问题。 不是依次执行图像特征检测、描述和匹配&#…

Percona XtraBackup备份docker版本mysql 5.7

my.cnf配置文件 [client] default_character_setutf8[mysqld] # 数据存储目录&#xff08;必须手动指定&#xff09; datadir/var/lib/mysql/data# 字符集 collation_server utf8_general_ci character_set_server utf8 # 二进制日志 server-id1 log_bin/var/log/mysql/binl…

Windows安装vcpkg教程(VS2022)

内容摘要&#xff1a; 本文详细介绍如何在Windows系统上使用 Git 克隆 vcpkg 仓库来安装vcpkg工具&#xff0c;并链接Visual Studio 2022。 目录 一、关于vcpkg 二、开发环境 三、安装Git 四、使用 Git 克隆 vcpkg 仓库 一、关于vcpkg vcpkg 是一个开源的 C 包管理工具&am…

nodejs入门(1):nodejs的前后端分离

一、引言 我关注nodejs还是从前几年做了的一个电力大数据展示系统开始的&#xff0c;当然&#xff0c;我肯定是很多年的计算机基础的&#xff0c;万变不离其宗。 现在web网站都流行所谓的前后端结构&#xff0c;不知不觉我也开始受到这个影响&#xff0c;以前都是前端直接操作…