uniapp实现H5、APP、微信小程序播放.m3u8监控视频

       

目录

1.APP播放.m3u8监控视频

2.H5播放.m3u8监控视频

3.微信小程序播放.m3u8监控视频


       最近在写一个uniapp实现h5、app、微信小程序兼容三端的播放监控视频功能,我原本以为一套代码多处运行,但事实并非如此,h5可以运行,微信小程序不一定可以运行,APP也是如此。上网查阅很多资料,最终3端效果实现成功。

1.APP播放.m3u8监控视频

APP对原生支持比较好,可以直接使用uniapp官网的video组件,本人亲自试过正常播放。

video地址:uni-app官网

代码实现如下:

    <!-- APP 端 --><video id="myVideo":src="videoUrl"controlsautoplayenable-play-gestureobject-fit="contain"class="video-player"@error="videoError"></video>

代码还是比较简单的,将videoUrl替换成自己的.m3u8格式Url即可。

2.H5播放.m3u8监控视频

       这里一开始我也以为直接使用上面的代码就可以,但是uniapp运行起来发现根本播放不出来,虽然 HTML5 视频播放器支持多种视频格式,但并不是所有的浏览器都支持 .m3u8 格式的视频流。确保您使用的浏览器支持 HLS。我上网查阅资料最终效果实现成功!

实现代码:

<template>		
<div id="app1"><div class="video-js" ref="videos"></div>
</div>
</template><script>
export default {data() {return {videoUrl: '',// H5 相关状态player: null,visibilityChange: null,hidden: null,}}, mounted() {// 动态加载video.js CDN资源this.loadScript('https://vjs.zencdn.net/7.21.2/video.min.js', () => {this.loadStyle('https://vjs.zencdn.net/7.21.2/video-js.min.css');// 设置页面可见性API的兼容性处理this.setupVisibilityAPI();// 等待资源加载完成setTimeout(() => {this.setupVideoPlayer();}, 300);});},beforeDestroy() {// 组件销毁时移除事件监听document.removeEventListener(this.visibilityChange, this.handleVisibilityChange);// 销毁播放器if (this.player) {this.player.dispose();this.player = null;}},methods: {loadScript(src, callback) {const script = document.createElement('script');script.src = src;script.onload = callback;document.body.appendChild(script);},loadStyle(href) {const link = document.createElement('link');link.href = href;link.rel = 'stylesheet';document.head.appendChild(link);},setupVisibilityAPI() {// 设置页面可见性API的兼容性处理if (typeof document.hidden !== "undefined") {this.hidden = "hidden";this.visibilityChange = "visibilitychange";} else if (typeof document.msHidden !== "undefined") {this.hidden = "msHidden";this.visibilityChange = "msvisibilitychange";} else if (typeof document.webkitHidden !== "undefined") {this.hidden = "webkitHidden";this.visibilityChange = "webkitvisibilitychange";}// 添加事件监听document.addEventListener(this.visibilityChange, this.handleVisibilityChange.bind(this), false);},handleVisibilityChange() {if (!this.player) return;if (document[this.hidden]) {// 页面不可见时暂停播放this.player.pause();} else {// 页面重新可见时恢复播放this.player.play().catch(e => {console.log('自动播放失败:', e);});}},setupVideoPlayer() {if (!window.videojs) {console.error('video.js未加载成功');return;}let video = document.createElement('video');video.id = 'video';video.className = 'video-js vjs-default-skin';video.preload = "auto";video.setAttribute('playsinline', true);video.setAttribute('webkit-playsinline', true);video.setAttribute('x5-video-player-type', 'h5');let source = document.createElement('source');source.src = this.videoUrl;video.appendChild(source);this.$refs.videos.appendChild(video);this.player = window.videojs('video', {autoDisable: true,preload: 'none',language: 'zh-CN',fluid: true,muted: false,aspectRatio: '16:9',controls: true,autoplay: false,loop: true,controlBar: {volumePanel: {inline: true},timeDivider: true,durationDisplay: true,progressControl: true,remainingTimeDisplay: true,fullscreenToggle: true,pictureInPictureToggle: false,}}, function() {this.on('error', function(err) {console.log("请求数据时遇到错误", err);});this.on('stalled', function(stalled) {console.log("网速失速", stalled);});});}}
}
</script>
<style>
#app1 {width: 100vw;height: 95vh;background: #000;display: flex;justify-content: center;align-items: center;}/* 视频播放器主体 */.video-js {width: 90%;max-width: 1200px;height: auto;aspect-ratio: 16/9;border-radius: 8px;overflow: hidden;box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);margin-top: -200px;}/* 控制栏整体样式 */.video-js .vjs-control-bar {background: rgba(20, 20, 20, 0.8);height: 3.5em;padding: 0 10px;}/* 按钮样式 */.video-js .vjs-control {width: 2.5em;height: 2.5em;margin: 0 2px;color: #fff;transition: all 0.3s;}.video-js .vjs-control:hover {color: #00a1d6;transform: scale(1.1);}/* 进度条样式 */.video-js .vjs-progress-control {position: absolute;top: -1em;width: 100%;height: 0.5em;}.video-js .vjs-progress-holder {height: 100%;background: rgba(255, 255, 255, 0.2);}.video-js .vjs-play-progress {background: #00a1d6;}/* 音量控制 */.video-js .vjs-volume-panel {order: 4;}/* 时间显示 */.video-js .vjs-time-control {min-width: 3em;padding: 0 5px;font-size: 1.1em;}/* 全屏按钮 */.video-js .vjs-fullscreen-control {order: 5;}/* 加载动画 */.video-js .vjs-loading-spinner {border-color: rgba(0, 161, 214, 0.7);}/* 大播放按钮 */.video-js .vjs-big-play-button {width: 2.5em;height: 2.5em;line-height: 2.5em;border-radius: 50%;border: none;background: rgba(0, 161, 214, 0.8);top: 50%;left: 50%;transform: translate(-50%, -50%);transition: all 0.3s;}.video-js .vjs-big-play-button:hover {background: rgba(0, 161, 214, 1);transform: translate(-50%, -50%) scale(1.1);}/* 响应式调整 */@media (max-width: 768px) {.video-js {width: 100%;border-radius: 0;}.video-js .vjs-control-bar {height: 2.5em;}}</style>

本人亲自实践,电脑浏览器,与手机浏览器访问,都可以成功。

3.微信小程序播放.m3u8监控视频

     在这里我是卡的最久的,因为直接使用video组件播放,在微信开发者工具中可以正常播放,但是在真机调试,小程序查看就是一直黑屏转圈圈,有时候可以播放成功,但是几秒中过后就是又是一直转圈圈,最后就会报错。有大佬会的可以在下方留言,最后采用web-view组件,实现播放,直接页面跳转。但是使用web-view跳转监控视频,又会有另一个问题,本地测试正常,但是上线,线上微信小程序就会出现提示不支持打开该页面。一定得在微信开发者后台校验文件才可以打开,因为这是微信小程序的强制规则,这个校验文件必须放在对应服务器才可以成功,假如我是调整萤石云的监控,那按照微信的说法,就要将校验文件放入萤石云服务器的后台,这样显然不现实,所以这里有两种方案,第一使用代理,第二自己在写一个页面部署到自己的服务器,通过web-view跳转到自己写的页面中,将监控视频url一并传入页面,即可完成播放。


实现代码:

 <web-view :src="'https://你的域名/player.html?videoUrl='+encodeURIComponent(videoUrl)+
'&cameraTitle='+encodeURIComponent(cameraTitle)"></web-view>

注意,这里跳转必须是https,在这里viderUrl是视频监控的链接,cameraTitle是标题,比如你播放的是那个监控,可加可不加,我这边是加上了。

跳转playeer.html页面代码实现:
其实下面的代码保存,videoUrl替换即可播放,我只不过写了两套,你们可以选择一套使用。

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title id="pageTitle">监控播放器</title><style>body {margin: 0;padding: 270px 0px 0px 0px;font-family: Arial, sans-serif;background: #000;}}/* 容器样式 */#app1 {background: #000;display: flex;justify-content: center;align-items: center;}/* 视频播放器主体 */.video-js {width: 100%;max-width: 1200px;height: auto;aspect-ratio: 16/9;border-radius: 8px;overflow: hidden;box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);}</style>
</head>
<body><div id="app1"><div class="video-js" id="videos"></div></div><script>function getQueryParam(name) {const query = window.location.search.substring(1);const vars = query.split('&');for (let i = 0; i < vars.length; i++) {const pair = vars[i].split('=');if (decodeURIComponent(pair[0]) === name) {return decodeURIComponent(pair[1]);}}return null;
}// 从URL参数获取视频地址
const videoUrl = getQueryParam('videoUrl');// 从URL获取摄像头标题并设置页面标题const cameraTitle = getQueryParam('cameraTitle');if (cameraTitle) {document.title = cameraTitle;document.getElementById('pageTitle').textContent = cameraTitle;}document.addEventListener('DOMContentLoaded', function() {const app = {player: null,visibilityChange: null,hidden: null,init: function() {// 动态加载video.js CDN资源this.loadScript('https://vjs.zencdn.net/7.21.2/video.min.js', () => {this.loadStyle('https://vjs.zencdn.net/7.21.2/video-js.min.css');// 设置页面可见性API的兼容性处理this.setupVisibilityAPI();// 等待资源加载完成setTimeout(() => {this.setupVideoPlayer();}, 300);});},loadScript: function(src, callback) {const script = document.createElement('script');script.src = src;script.onload = callback;document.body.appendChild(script);},loadStyle: function(href) {const link = document.createElement('link');link.href = href;link.rel = 'stylesheet';document.head.appendChild(link);},setupVisibilityAPI: function() {// 设置页面可见性API的兼容性处理if (typeof document.hidden !== "undefined") {this.hidden = "hidden";this.visibilityChange = "visibilitychange";} else if (typeof document.msHidden !== "undefined") {this.hidden = "msHidden";this.visibilityChange = "msvisibilitychange";} else if (typeof document.webkitHidden !== "undefined") {this.hidden = "webkitHidden";this.visibilityChange = "webkitvisibilitychange";}// 添加事件监听document.addEventListener(this.visibilityChange, this.handleVisibilityChange.bind(this), false);},handleVisibilityChange: function() {if (!this.player) return;if (document[this.hidden]) {// 页面不可见时暂停播放this.player.pause();} else {// 页面重新可见时恢复播放this.player.play().catch(e => {console.log('自动播放失败:', e);});}},setupVideoPlayer: function() {if (!window.videojs) {console.error('video.js未加载成功');return;}let video = document.createElement('video');video.id = 'video';video.className = 'video-js vjs-default-skin';video.preload = "auto";video.setAttribute('playsinline', true);video.setAttribute('webkit-playsinline', true);video.setAttribute('x5-video-player-type', 'h5');let source = document.createElement('source');source.src = videoUrl ;video.appendChild(source);document.getElementById('videos').appendChild(video);this.player = window.videojs('video', {autoDisable: true,preload: 'none',language: 'zh-CN',fluid: true,muted: false,aspectRatio: '16:9',controls: true,autoplay: false,loop: true,controlBar: {volumePanel: {inline: true},timeDivider: true,durationDisplay: true,progressControl: true,remainingTimeDisplay: true,fullscreenToggle: true,pictureInPictureToggle: false,}}, function() {this.on('error', function(err) {console.log("请求数据时遇到错误", err);});this.on('stalled', function(stalled) {console.log("网速失速", stalled);});});}};// 初始化应用app.init();});</script>
</body>
</html>

本人亲自测试,3端都可以播放,有问题可以在下方评论留言。

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

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

相关文章

萤石云实际视频实时接入(生产环境)

萤石云视频接入 本示例可用于实际接入萤石云开放平台视频&#xff0c;同时支持音频输入和输出。 实际优化内容 1.动态获取token 2.切换各公司和车间时&#xff0c;自动重新初始化播放器 let EZUIKit null; // 第三方库引用 let EZUIKitPlayers []; // 播放器实例数组 le…

【Dify平台】使用Dify API 实现网页内嵌式AI助手

使用 Dify API 实现网页内嵌式 AI 助手 一. 引言二. Dify API 概述三. 实现网页内嵌式 AI 助手的技术架构四. 前端实现五. 后端实现六. 功能扩展与优化七. 测试与部署一. 引言 随着 AI 技术的不断发展,越来越多的企业希望将智能助手集成到自己的网页中,实现用户自动接待、问…

mysql8配置文件my.ini讲解,原汁原味直接拷贝再讲解

文章目录 一、原英文版本&#xff0c;不带注释二、由原版逐字翻译成的中文版&#xff08;行行对应&#xff09;三、最常用的配置 一、原英文版本&#xff0c;不带注释 # Other default tuning values # MySQL Server Instance Configuration File # -------------------------…

Go语言中内存释放 ≠ 资源释放

// QueryUserFileMetas : 批量获取用户文件信息 func QueryUserFileMetas(username string, limit int) ([]UserFile, error) {stmt, err : mydb.DBConn().Prepare("select file_sha1,file_name,file_size,upload_at," "last_update from tbl_user_file where u…

win11+vs2022 安装opencv 4.11.0图解教程

1. 下载opencv opencv官网下载地址&#xff1a;Releases - OpenCV 2. 双击运行该exe&#xff0c;即可进行安装&#xff0c;安装文件夹可自行选择 安装后目录如下&#xff1a; 3. 配置环境变量 使用win键搜索环境变量&#xff0c;选中系统变量中的Path&#xff0c;然后点击编辑…

【Linux】进程 信号的产生

&#x1f33b;个人主页&#xff1a;路飞雪吖~ &#x1f320;专栏&#xff1a;Linux 目录 一、掌握Linux信号的基本概念 &#x1f320;前台进程 VS 后台进程 &#x1f320; 小贴士&#xff1a; &#x1fa84;⼀个系统函数 --- signal() &#x1fa84;查看信号 --- man 7 sign…

Python 网络编程入门

目录 一、前言 二、网络通信基础12&#xff1a;TCP 与 UDP 协议解析 2.1 TCP 协议&#xff1a;可靠的面向连接通信 2.2 UDP 协7议&#xff1a;无连接的快速通信 2.3 Sock12et&#xff1a;网络通信的基石 三、TCP 编程实15战&#xff1a;从单工通信到双向聊天 3.1 TCP 客…

Django压缩包形式下载文件

通过web将minio上的文件以压缩包-文件夹-文件的形式下载到本地 import os from bx_mes import settings from io import BytesIO import zipfile from django.http import StreamingHttpResponse class FileRemote(GenericAPIView):def post(self,request):# 压缩包名folder_n…

Enhancing Relation Extractionvia Supervised Rationale Verifcation and Feedback

Enhancing Relation Extraction via Supervised Rationale Verification and Feedback| Proceedings of the AAAI Conference on Artificial Intelligencehttps://ojs.aaai.org/index.php/AAAI/article/view/34631 1. 概述 关系抽取(RE)任务旨在抽取文本中实体之间的语义关

【RAG】ragflow源码亮点:文档embedding向量化加权融合

引言&#xff1a; 最近在看ragflow源码&#xff0c;其中有一个较为巧妙地设计&#xff1a;分别将 文字 、 标题 行向量化 之后&#xff0c;直接根据权重&#xff0c;进行加法运算&#xff0c;得到向量融合&#xff0c;增强了文本向量化的表示能力&#xff0c;这里开始讨论一下…

限流系列:sentinel

目录 滑动窗口算法 Sentinel 数据模型 示例 大致流程 ​​​​​​​entry ​​​​​​​entryWithPriority ​​​​​​​FlowSlot.entry ​​​​​​​checkFlow ​​​​​​​canPass ​​​​​​​avgUsedTokens ​​​​​​​passQps ​​​​​​​pa…

Java 访问者模式深度重构:从静态类型到动态行为的响应式设计实践

一、访问者模式的本质与核心价值 在软件开发的漫长演进中&#xff0c;设计模式始终是架构师手中的利刃。当我们面对复杂对象结构上的多种操作需求时&#xff0c;访问者模式&#xff08;Visitor Pattern&#xff09;犹如一把精密的手术刀&#xff0c;能够优雅地分离数据结构与作…

UE 5 C++设置物体位置和旋转,初始化虚幻引擎样条线、加载引用虚幻编辑器中的蓝图、设置虚幻编辑器中Actor大小

一、设置物体位置和旋转 UE.cpp文件中代码&#xff1a; Mesh->SetWorldLocationAndRotation(FVector(50.0f, 50.0f, 50.0f),FRotator(0,-90,0)); vs代码编辑器中旋转信息顺序&#xff08;yzx&#xff09;&#xff1a; Pitch、 Yaw、 Roll UE编辑器中旋转信息顺序&#xf…

【文本分类】KG-HTC 知识图谱提升分类准确率

最近看到一篇论文“KG-HTC: Integrating Knowledge Graphs into LLMs for Effective Zero-shot Hierarchical Text Classification”&#xff0c;介绍了文本分类的技巧&#xff0c;这篇文航主要利用了知识图谱大模型的思路&#xff0c;实验效果不错&#xff0c;里面的一些论述也…

三大微调技术对比:Prompt/Prefix/P-Tuning

Prompt Tuning、Prefix Tuning和P - Tuning的区别 概念方面: Prompt Tuning:在输入序列前添加可训练的额外Token以适配下游任务,预训练语言模型参数不变。比如在文本分类中,在句子前加特定Token如“(OPINION)”,让模型理解是对观点进行分类的任务。Prefix Tuning:在每层T…

14.「实用」扣子(coze)教程 | Excel文档自动批量AI文档生成实战,中级开篇

随着AI编程工具及其能力的不断发展&#xff0c;编程将变得越来越简单。 在这个大趋势下&#xff0c;大师兄判断未来的编程将真正成为像office工具一样的办公必备技能。每个人通过 &#xff08;专业知识/资源编程&#xff09;将自己变成一个复合型的人才&#xff0c;大大提高生…

量子-经典协同计算新路径:NISQ 时代混合算法对后量子密码学的适应性探索

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 文丨浪味仙 排版丨浪味仙 行业动向&#xff1a;3700字丨10分钟阅读 5 月 20 日&#xff0c;由北京量子院、清华大学、数学工程与先进计算国家重点实验室、南洋理工大学、量子信息前沿科学中心…

CentOS中安装Docker Compose

在CentOS中安装Docker Compose的步骤如下&#xff1a; 步骤 1&#xff1a;确保Docker已安装 Docker Compose依赖Docker环境&#xff0c;请先安装Docker&#xff1a; # 添加Docker官方仓库 sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://downlo…

电商小程序店铺详情页:头部无限分类与筛选功能实现

电商小程序店铺详情页:头部无限分类与筛选功能实现 一、场景需求与技术选型二、头部无限分类导航三、筛选功能实现:Picker多列选择组件一、场景需求与技术选型 在电商小程序生态中,店铺详情页作为用户浏览商品的核心流量入口,其交互效率与功能完整性直接影响商品转化率。传…

Graph Neural Network(GNN)

我们首先要了解什么是图,图是由节点和边组成的,边的不一样也导致节点的不同(参考化学有机分子中的碳原子) gnn可以处理classification的问题,也就是分类的问题 也可以处理generation的问题 借一部日剧来说明,这个日剧是讲主角寻找杀害他父亲的凶手的,剧中的人物有姓名和特征 …