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

WPF下播放Rtmp的解决方案

介绍

在实际的开发过程中,需要在应用内部内嵌播放器进行视频的播放。官方默认的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));
elseawait Media.Open(target);

相关文章:

WPF下播放Rtmp的解决方案

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

7.高可用集群架构Keepalived双主热备原理

一. 高可用集群架构Keepalived双主热备原理 (1)主机+备机keepalived配置(192.168.1.171) ! Configuration File for keepalivedglobal_defs {# 路由id:当前安装keepalived节点主机的标识符,全局唯一router_id keep_101 } #计算机节点(主机配置) vrrp_instance VI_1 {</...

为以人工智能为中心的工作负载重新设计的全局控制台

MinIO 控制台多年来一直是一个不断发展的产品。每次学习时&#xff0c;我们都会思考如何改进交互框架中这个非常重要的部分。首先是控制台&#xff0c;它在推出后的一年内就被广泛采用。更具体地说&#xff0c;超过 10K 个组织。接下来是企业控制台。这从对象存储与其 GUI 之间…...

go channel中的 close注意事项 range取数据

在使用 Go 语言中的 close 函数时&#xff0c;有一些注意事项需要牢记&#xff0c;以确保程序的健壮性和正确性&#xff1a; 1. **仅用于通道&#xff08;channel&#xff09;**&#xff1a; - close 函数只能用于关闭通道&#xff0c;不能用于关闭文件、网络连接或其他资源…...

Vue3 -- 项目配置之eslint【企业级项目配置保姆级教程1】

下面是项目级完整配置1➡eslint&#xff1a;【吐血分享&#xff0c;博主踩过的坑你跳过去&#xff01;&#xff01;跳不过去&#xff1f;太过分了给博主打钱】 浏览器自动打开项目&#xff1a; 你想释放双手吗&#xff1f;你想每天早上打开电脑运行完项目自动在浏览器打开吗&a…...

鸿蒙开发应用权限管理

简介 一种允许应用访问系统资源&#xff08;如&#xff1a;通讯录等&#xff09;和系统能力&#xff08;如&#xff1a;访问摄像头、麦克风等&#xff09;的通用权限访问方式&#xff0c;来保护系统数据&#xff08;包括用户个人数据&#xff09;或功能&#xff0c;避免它们被…...

【数据库】如何保证数据库迁移过程中数据的一致性?

在数据库迁移过程中&#xff0c;保证数据的一致性是非常重要的&#xff0c;尤其是在涉及到多个表、多个数据库或分布式系统的情况下。以下是一些确保数据一致性的最佳实践和方法&#xff1a; 1. 备份数据 在开始迁移之前&#xff0c;进行全面的数据备份是确保数据一致性的第…...

C++之内存管理

​ &#x1f339;个人主页&#x1f339;&#xff1a;喜欢草莓熊的bear &#x1f339;专栏&#x1f339;&#xff1a;C入门 目录 前言 一、C/C内存分配 二、 malloc、calloc、realloc、free 三、C内存管理方式 3.1 new/delete 操作内置类型 3.2 new和detele操作自定义类型…...

ISP是什么?

isp全称为Internet Service Provider&#xff0c;即互联网服务提供商&#xff0c;是一种向用户提供互联网接入服务的公司或组织&#xff0c;它们提供的服务包括互联网接入、域名注册、网站托管等等。 ISP的应用场景非常广泛&#xff0c;几乎所有的互联网用户都需要通过ISP来接…...

机房动环境监控用各种列表已经淘汰了,现在都是可视化图表展示了

在信息技术飞速发展的今天&#xff0c;机房作为数据存储、处理和传输的核心场所&#xff0c;其稳定运行至关重要。过去&#xff0c;机房动环境监控主要依赖各种列表形式来呈现数据&#xff0c;但如今&#xff0c;这种方式已经逐渐被淘汰&#xff0c;取而代之的是更加直观、高效…...

RHCE的练习(12)

写一个脚本&#xff0c;完成以下要求&#xff1a; 给定一个用户&#xff1a; 如果其UID为0&#xff0c;就显示此为管理员&#xff1b;否则&#xff0c;就显示其为普通用户&#xff1b; #!/bin/bash ​ # 使用read命令获取用户名 read -p "请输入用户名: " username ​…...

uniapp自动注册机制:easycom

传统 Vue 项目中&#xff0c;我们需要注册、导入组件之后才能使用组件。 uniapp 框架提供了一种组件自动注册机制&#xff0c;只要你在 components 文件夹下新建的组件满足 /components/组件名/组件名.vue 的命名规范&#xff0c;就能直接使用。 注意&#xff1a;组件的文件夹…...

【论文阅读】(Security) Assertions by Large Language Models

论文笔记:(Security) Assertions by Large Language Models 来源:IEEE TRANSACTIONS ON INFORMATION FORENSICS AND SECURITY I. 引言 计算机系统的安全性通常依赖于硬件的根信任。硬件漏洞可能对系统造成严重影响,因此需要支持安全验证的技术。断言验证是一种流行的验证…...

C++ 编程基础(5)类与对象 | 5.8、面向对象五大原则

文章目录 一、面向对象五大原则1、单一功能&#xff08;Single Responsibility Principle, SRP&#xff09;2、开放封闭原则&#xff08;Open/Closed Principle, OCP&#xff09;3、里氏替换原则&#xff08;Liskov Substitution Principle, LSP&#xff09;4、接口隔离原则&am…...

node.js中express的基本了解

定义 Express是基于Node.js平台&#xff0c;快速、开放、极简的Web开发框架。 本质 Express是一个npm上的第三方包&#xff0c;提供了快速创建Web服务器的便捷方法。 作用 与Node.js内置的http模块类似&#xff0c;Express也是专门用来创建Web服务器的&#xff0c;但它极大地简…...

AI大模型(一):Prompt AI编程

一、Prompt Engineering&#xff0c;提示工程 提示工程也叫指令工程&#xff1a; Prompt是发给大模型的指令&#xff0c;比如【讲个睡前故事】、【用Python写个消消乐游戏】等&#xff1b;本质上大模型相关的工程工作&#xff0c;都是围绕prompt展开的&#xff1b;提示工程门…...

ArcGIS Pro属性表乱码与字段名3个汉字解决方案大总结

01 背景 我们之前在使用ArcGIS出现导出Excel中文乱码及shp添加字段3个字被截断的情况&#xff0c;我们有以下应对策略&#xff1a; 推荐阅读&#xff1a;ArcGIS导出Excel中文乱码及shp添加字段3个字被截断&#xff1f; 那如果我们使用ArGIS Pro出现上述问题&#xff0c;该如何…...

小程序-基于java+SpringBoot+Vue的驾校预约平台设计与实现

项目运行 1.运行环境&#xff1a;最好是java jdk 1.8&#xff0c;我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境&#xff1a;IDEA&#xff0c;Eclipse,Myeclipse都可以。推荐IDEA; 3.tomcat环境&#xff1a;Tomcat 7.x,8.x,9.x版本均可 4.硬件环境&#xff1a…...

计算机网络网关简介

网关&#xff0c;在计算机网络中扮演着至关重要的角色&#xff0c;它如同不同语言间的翻译官&#xff0c;让不同网络协议、不同体系结构的网络能够相互通信。简而言之&#xff0c;网关就是一个网络连接到另一个网络的“关口”&#xff0c;负责数据的接收、转换与发送。 在局域…...

如何用python将pdf转换为json格式

使用 Python 将 PDF 文件转换为 JSON 格式&#xff0c;主要步骤如下&#xff1a; 读取 PDF 内容&#xff1a;首先使用一个库读取 PDF 文件内容&#xff0c;如 PyMuPDF 或 pdfplumber。这些库可以逐页提取文本&#xff0c;并返回结构化的数据。 组织数据到 JSON&#xff1a;将提…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...

Webpack性能优化:构建速度与体积优化策略

一、构建速度优化 1、​​升级Webpack和Node.js​​ ​​优化效果​​&#xff1a;Webpack 4比Webpack 3构建时间降低60%-98%。​​原因​​&#xff1a; V8引擎优化&#xff08;for of替代forEach、Map/Set替代Object&#xff09;。默认使用更快的md4哈希算法。AST直接从Loa…...

windows系统MySQL安装文档

概览&#xff1a;本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容&#xff0c;为学习者提供全面的操作指导。关键要点包括&#xff1a; 解压 &#xff1a;下载完成后解压压缩包&#xff0c;得到MySQL 8.…...

全面解析数据库:从基础概念到前沿应用​

在数字化时代&#xff0c;数据已成为企业和社会发展的核心资产&#xff0c;而数据库作为存储、管理和处理数据的关键工具&#xff0c;在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理&#xff0c;到社交网络的用户数据存储&#xff0c;再到金融行业的交易记录处理&a…...

DAY 26 函数专题1

函数定义与参数知识点回顾&#xff1a;1. 函数的定义2. 变量作用域&#xff1a;局部变量和全局变量3. 函数的参数类型&#xff1a;位置参数、默认参数、不定参数4. 传递参数的手段&#xff1a;关键词参数5 题目1&#xff1a;计算圆的面积 任务&#xff1a; 编写一…...