WPF下播放Rtmp的解决方案
介绍
在实际的开发过程中,需要在应用内部内嵌播放器进行视频的播放。官方默认的MediaElement控件只能播放有限的视频格式,也不能播放网络流。比较流行的解决方式是vlc的库,但是在实际使用过程中发现有很多问题。这里给大家推荐另一个比较好的库。
使用
官网地址
安装库
Nuget下安装FFME.Windows
PM> Install-Package FFME.Windows
下载ffmpeg依赖
注:官网给的地址我在实际使用中发现,使用官方的代码没问题,使用给定的步骤使用就会抱错,如果你们跟我一样给大家推荐另一个ffmpeg包的地址
ffmpeg依赖下载地址
代码
- 指定ffmpeg库的地址
Unosquare.FFME.Library.FFmpegDirectory = @"C:\ffmpeg\ffmpeg-4.4-windows-desktop-vs2022-gpl-lite\bin";
- 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>
- 监听失败的事件
Media.MediaFailed += OnMediaFailed;
- 创建一个处理流地址的类
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;}}}
}
- 播放视频
//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的解决方案
介绍 在实际的开发过程中,需要在应用内部内嵌播放器进行视频的播放。官方默认的MediaElement控件只能播放有限的视频格式,也不能播放网络流。比较流行的解决方式是vlc的库,但是在实际使用过程中发现有很多问题。这里给大家推荐另一个比较好的…...
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 控制台多年来一直是一个不断发展的产品。每次学习时,我们都会思考如何改进交互框架中这个非常重要的部分。首先是控制台,它在推出后的一年内就被广泛采用。更具体地说,超过 10K 个组织。接下来是企业控制台。这从对象存储与其 GUI 之间…...
go channel中的 close注意事项 range取数据
在使用 Go 语言中的 close 函数时,有一些注意事项需要牢记,以确保程序的健壮性和正确性: 1. **仅用于通道(channel)**: - close 函数只能用于关闭通道,不能用于关闭文件、网络连接或其他资源…...
Vue3 -- 项目配置之eslint【企业级项目配置保姆级教程1】
下面是项目级完整配置1➡eslint:【吐血分享,博主踩过的坑你跳过去!!跳不过去?太过分了给博主打钱】 浏览器自动打开项目: 你想释放双手吗?你想每天早上打开电脑运行完项目自动在浏览器打开吗&a…...
鸿蒙开发应用权限管理
简介 一种允许应用访问系统资源(如:通讯录等)和系统能力(如:访问摄像头、麦克风等)的通用权限访问方式,来保护系统数据(包括用户个人数据)或功能,避免它们被…...
【数据库】如何保证数据库迁移过程中数据的一致性?
在数据库迁移过程中,保证数据的一致性是非常重要的,尤其是在涉及到多个表、多个数据库或分布式系统的情况下。以下是一些确保数据一致性的最佳实践和方法: 1. 备份数据 在开始迁移之前,进行全面的数据备份是确保数据一致性的第…...
C++之内存管理
🌹个人主页🌹:喜欢草莓熊的bear 🌹专栏🌹:C入门 目录 前言 一、C/C内存分配 二、 malloc、calloc、realloc、free 三、C内存管理方式 3.1 new/delete 操作内置类型 3.2 new和detele操作自定义类型…...
ISP是什么?
isp全称为Internet Service Provider,即互联网服务提供商,是一种向用户提供互联网接入服务的公司或组织,它们提供的服务包括互联网接入、域名注册、网站托管等等。 ISP的应用场景非常广泛,几乎所有的互联网用户都需要通过ISP来接…...
机房动环境监控用各种列表已经淘汰了,现在都是可视化图表展示了
在信息技术飞速发展的今天,机房作为数据存储、处理和传输的核心场所,其稳定运行至关重要。过去,机房动环境监控主要依赖各种列表形式来呈现数据,但如今,这种方式已经逐渐被淘汰,取而代之的是更加直观、高效…...
RHCE的练习(12)
写一个脚本,完成以下要求: 给定一个用户: 如果其UID为0,就显示此为管理员;否则,就显示其为普通用户; #!/bin/bash # 使用read命令获取用户名 read -p "请输入用户名: " username …...
uniapp自动注册机制:easycom
传统 Vue 项目中,我们需要注册、导入组件之后才能使用组件。 uniapp 框架提供了一种组件自动注册机制,只要你在 components 文件夹下新建的组件满足 /components/组件名/组件名.vue 的命名规范,就能直接使用。 注意:组件的文件夹…...
【论文阅读】(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、单一功能(Single Responsibility Principle, SRP)2、开放封闭原则(Open/Closed Principle, OCP)3、里氏替换原则(Liskov Substitution Principle, LSP)4、接口隔离原则&am…...
node.js中express的基本了解
定义 Express是基于Node.js平台,快速、开放、极简的Web开发框架。 本质 Express是一个npm上的第三方包,提供了快速创建Web服务器的便捷方法。 作用 与Node.js内置的http模块类似,Express也是专门用来创建Web服务器的,但它极大地简…...
AI大模型(一):Prompt AI编程
一、Prompt Engineering,提示工程 提示工程也叫指令工程: Prompt是发给大模型的指令,比如【讲个睡前故事】、【用Python写个消消乐游戏】等;本质上大模型相关的工程工作,都是围绕prompt展开的;提示工程门…...
ArcGIS Pro属性表乱码与字段名3个汉字解决方案大总结
01 背景 我们之前在使用ArcGIS出现导出Excel中文乱码及shp添加字段3个字被截断的情况,我们有以下应对策略: 推荐阅读:ArcGIS导出Excel中文乱码及shp添加字段3个字被截断? 那如果我们使用ArGIS Pro出现上述问题,该如何…...
小程序-基于java+SpringBoot+Vue的驾校预约平台设计与实现
项目运行 1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。 2.IDE环境:IDEA,Eclipse,Myeclipse都可以。推荐IDEA; 3.tomcat环境:Tomcat 7.x,8.x,9.x版本均可 4.硬件环境:…...
计算机网络网关简介
网关,在计算机网络中扮演着至关重要的角色,它如同不同语言间的翻译官,让不同网络协议、不同体系结构的网络能够相互通信。简而言之,网关就是一个网络连接到另一个网络的“关口”,负责数据的接收、转换与发送。 在局域…...
如何用python将pdf转换为json格式
使用 Python 将 PDF 文件转换为 JSON 格式,主要步骤如下: 读取 PDF 内容:首先使用一个库读取 PDF 文件内容,如 PyMuPDF 或 pdfplumber。这些库可以逐页提取文本,并返回结构化的数据。 组织数据到 JSON:将提…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...
Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...
windows系统MySQL安装文档
概览:本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容,为学习者提供全面的操作指导。关键要点包括: 解压 :下载完成后解压压缩包,得到MySQL 8.…...
全面解析数据库:从基础概念到前沿应用
在数字化时代,数据已成为企业和社会发展的核心资产,而数据库作为存储、管理和处理数据的关键工具,在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理,到社交网络的用户数据存储,再到金融行业的交易记录处理&a…...
DAY 26 函数专题1
函数定义与参数知识点回顾:1. 函数的定义2. 变量作用域:局部变量和全局变量3. 函数的参数类型:位置参数、默认参数、不定参数4. 传递参数的手段:关键词参数5 题目1:计算圆的面积 任务: 编写一…...
