前端实现视频/直播预览

news2025/6/7 17:51:24

有一个需求:后端返回视频的预览地址,不仅要支持这个视频的预览,还需要设置视频封面。

这里有两种情况:

  • 如果是类似.mp4,.mov等格式的视频可以选用原生 video 进行视频展示,并且原生的 video 也支持全屏、音量调节、倍速调节、视频下载、封面设置等等...
  • 如果是类似.m3u8等格式的直播不推荐使用 video,可以使用 Plyr 等实现, 这个我会放在后面讲。(一开始我使用的是 ckPlayer, 但它在 ios 系统中无法播放带有一些携带 token 等参数的视频地址,因此换了 Plyr)

一、.mp4,.mov 视频预览

<video width="100%" controls :src="video_url" :poster="poster_img" class="video-player"/>
  • src为视频地址,poster为封面图地址, controls为显示浏览器默认的视频控制栏(播放/暂停,音量调节,进度调节,倍速控制,全屏播放,视频下载...);
  • 如果不加 controls,用户无法控制视频。

样式方面不过多赘述,可根据实际情况进行调整: 

.video-player {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

 如果需要支持更多格式的视频播放并进行具体的类型控制,可以用下面的写法:

<video width="100%" controls :poster="posterImage" class="video-player">
    <!-- 支持 MP4 格式 -->
    <source :src="video_url" type="video/mp4">
    
    <!-- 支持 MOV 格式 -->
    <source :src="video_url.replace('.mp4', '.mov')" type="video/quicktime">
    
    <!-- 支持 WebM 格式 -->
    <source :src="video_url.replace('.mp4', '.webm')" type="video/webm">
    
    <!-- 支持 Ogg 格式 -->
    <source :src="video_url.replace('.mp4', '.ogv')" type="video/ogg">
    
    暂不支持播放
</video>

注意:有些 .mp4 视频是 HEVC 编码的(如下图),这类视频在谷歌浏览器中可以播放,但在 Edge 等的浏览器会无法播放,这与内核浏览器的视频格式支持有关,不是 video 标签的问题,如果要做兼容性处理,可以进行转码、使用播放插件,或推荐使用谷歌浏览器访问。

二、直播预览

这里模拟一个场景:在某段时间内进行直播,直播开始前和直播结束后将播放器替换为封面图。

页面结构:

<div v-show="showPlayer" class="live-header-video">
    <video id="live-header-video" playsinline :poster="cover_url"></video>
</div>

<img v-show="!showPlayer" :src="cover_url" alt="">

注意:这里不要写成自闭合的<video /> !!!

  • v-show="showPlayer":仅在满足直播时间条件时显示视频容器
  • id="live-header-video":用于 JS 中获取 video DOM
  • playsinline:在移动设备上避免自动全屏播放
  • :poster:设置视频封面

变量定义:

import Plyr from 'plyr';
import Hls from 'hls.js';
import 'plyr/dist/plyr.css'

const showPlayer = ref(false)
const header_url = ref('')
const live_start_time = ref('')
const live_end_time = ref('')
const cover_url = ref('')
let videoPlayer = null
let div_video = null
  • showPlayer:控制是否显示播放器
  • header_url:视频地址
  • cover_url:封面地址
  • live_start_time和live_end_time:直播开始和结束时间
  • videoPlayer:保存 Plyr 播放器实例
  • div_video:video DOM 元素,用于绑定 Hls 或 Plyr

核心函数:

const setVideoPlayer = () =>{
  if (header_url.value){
    div_video = document.getElementById('live-header-video')
    videoPlayer = new Plyr(div_video, {
      controls: ['play-large',
        'play',
        'mute',
        'volume',
        'captions',
        'pip',
        'airplay',
        'fullscreen'
      ],
      settings: [],
      fullscreen: {
        enabled: true,
        fallback: true,
        iosNative: true
      }
    })
    const urlObj = new URL(header_url.value);
    if (urlObj.pathname.endsWith('.m3u8')) {
      if (Hls.isSupported()) {
        const hls = new Hls();
        hls.loadSource(header_url.value);
        hls.attachMedia(div_video);
        videoPlayer.play()
        hls.on(Hls.Events.MANIFEST_PARSED, () => {
          console.log('HLS 流准备就绪');
        });

        hls.on(Hls.Events.ERROR, (event, data) => {
          console.error('HLS 错误:', data);
        });
      }
      else if (div_video.canPlayType('application/vnd.apple.mpegurl')) {
        console.log("不支持Hls.isSupported")
        div_video.src = header_url.value;
      }
      else {
        console.error('不支持 HLS 播放');
      }
    }
    else {
      div_video.src = header_url.value
      div_video.load();
      div_video.addEventListener('loadeddata', () => {
        videoPlayer.play();
      });
    }

    if(live_start_time.value && live_end_time.value) {
      const startDate = new Date(live_start_time.value.replace(" ", "T"));
      const endDate = new Date(live_end_time.value.replace(" ", "T"));

      const currentDate = new Date();

      showPlayer.value = currentDate >= startDate && currentDate <= endDate;
    }
  }
}

代码解析:

div_video = document.getElementById('live-header-video')
videoPlayer = new Plyr(div_video, { ... })
  • 获取 video 元素并初始化 Plyr
  • Plyr 是视频播放器库,初始化后控制按钮等都由它管理
if (urlObj.pathname.endsWith('.m3u8')) {
  • 判断是否是 .m3u8 流地址

如果是 .m3u8:

  • 使用 Hls.js 加载并绑定流:
if (Hls.isSupported()) {
  const hls = new Hls();
  hls.loadSource(header_url.value);
  hls.attachMedia(div_video);
  videoPlayer.play()
  ...
}
  • 若不支持 Hls.js,但浏览器原生支持 .m3u8(如 Safari):
else if (div_video.canPlayType('application/vnd.apple.mpegurl')) {
  div_video.src = header_url.value;
}
  • 否则提示不支持 HLS 播放。
  • 如果是普通视频文件(非 .m3u8)
div_video.src = header_url.value
div_video.load();
div_video.addEventListener('loadeddata', () => {
  videoPlayer.play();
});
  • 当视频数据加载完成后自动播放
if(live_start_time.value && live_end_time.value) {
  const startDate = new Date(live_start_time.value.replace(" ", "T"));
  const endDate = new Date(live_end_time.value.replace(" ", "T"));
  const currentDate = new Date();

  showPlayer.value = currentDate >= startDate && currentDate <= endDate;
}
  • 判断是否在直播时间段:时间格式转为 Date 对象后进行比较,控制 showPlayer 的值,从而决定是否显示播放器。

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

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

相关文章

React源码阅读-fiber核心构建原理

React源码阅读(2)-fiber核心构建原理 好的&#xff0c;我明白了。您提供的文本主要介绍了 React 源码中 Fiber 核心的构建原理&#xff0c;涵盖了从执行上下文到构建、提交、调度等关键阶段&#xff0c;以及相关的代码实现。 您提出的关联问题也很重要&#xff0c;它们深入探讨…

视频监控管理平台EasyCVR与V4分析网关对接后告警照片的清理优化方案

一、问题概述​ 在安防监控、设备运维等场景中&#xff0c;用户将视频监控管理平台EasyCVR与V4网关通过http推送方式协同工作时&#xff0c;硬件盒子上传的告警图片持续累积&#xff0c;导致EasyCVR服务器存储空间耗尽&#xff0c;影响系统正常运行与告警功能使用。 二、解决方…

机器学习:决策树和剪枝

本文目录&#xff1a; 一、决策树基本知识&#xff08;一&#xff09;概念&#xff08;二&#xff09;决策树建立过程 二、决策树生成&#xff08;一&#xff09;ID3决策树&#xff1a;基于信息增益构建的决策树。&#xff08;二&#xff09;C4.5决策树&#xff08;三&#xff…

vscode自定义主题语法及流程

vscode c/c 主题 DIY 启用自己的主题(最后步骤) 重启生效 手把手教你制作 在C:\Users\jlh.vscode\extensions下自己创建一个文件夹 里面有两个文件一个文件夹 package.json: {"name":"theme-jlh","displayName":"%displayName%&qu…

vue中加载Cesium地图(天地图、高德地图)

目录 1、将下载的Cesium包移动至public下 2、首先需要将Cesium.js和widgets.css文件引入到 3、 新建Cesium.js文件&#xff0c;方便在全局使用 4、新建cesium.vue文件&#xff0c;展示三维地图 1、将下载的Cesium包移动至public下 npm install cesium后​​​​​​​ 2、…

SpringBoot整合RocketMQ与客户端注意事项

SpringBoot整合RocketMQ 引入依赖&#xff08;5.3.0比较稳定&#xff09; <dependencies><dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-spring-boot-starter</artifactId><version>2.3.1</version&…

Mysql的卸载与安装

确保卸载干净mysql 不然在进行mysal安装时候会出现不一的页面和问题 1、卸载 在应用页面将查询到的mysql相关应用卸载 2、到c盘下将残留的软件包进行数据删除 3、删除programData下的mysql数据 4、检查系统中的mysql是否存在 cmd中执行 sc deleted mysql80 5、删除注册表中的…

Excel处理控件Aspose.Cells教程:使用 C# 在 Excel 中创建组合图表

可视化项目时间线对于有效规划和跟踪至关重要。在本篇教程中&#xff0c;您将学习如何使用 C# 在 Excel 中创建组合图。只需几行代码&#xff0c;即可自动生成动态、美观的组合图。无论您是在构建项目管理工具还是处理内部报告&#xff0c;本指南都将向您展示如何将任务数据转换…

【多线程初阶】阻塞队列 生产者消费者模型

文章目录 一、阻塞队列二、生产者消费者模型(一)概念(二)生产者消费者的两个重要优势(阻塞队列的运用)1) 解耦合(不一定是两个线程之间,也可以是两个服务器之间)2) 削峰填谷 (三)生产者消费者模型付出的代价 三、标准库中的阻塞队列(一)观察模型的运行效果(二)观察阻塞效果1) 队…

《100天精通Python——基础篇 2025 第5天:巩固核心知识,选择题实战演练基础语法》

目录 一、踏上Python之旅二、Python输入与输出三、变量与基本数据类型四、运算符五、流程控制 一、踏上Python之旅 1.想要输出 I Love Python,应该使用()函数。 A.printf() B.print() C.println() D.Print() 在Python中想要在屏幕中输出内容&#xff0c;应该使用print()函数…

机器人夹爪的选型与ROS通讯——机器人抓取系统基础系列(六)

文章目录 前言一、夹爪的选型1.1 任务需求分析1.2 软体夹爪的选型 二、夹爪的ROS通讯2.1 夹爪的通信方式介绍2.2 串口助手测试2.3 ROS通讯节点实现 总结Reference: 前言 本文将介绍夹爪的选型方法和通讯方式。以鞋子这类操作对象为例&#xff0c;将详细阐述了对应的夹爪选型过…

第二十八章 RTC——实时时钟

第二十八章 RTC——实时时钟​​​​​​​ 目录 第二十八章 RTC——实时时钟 1 RTC实时时钟简介 2 RTC外设框图剖析 3 UNIX时间戳 4 与RTC控制相关的库函数 4.1 等待时钟同步和操作完成 4.2 使能备份域涉及RTC配置 4.3 设置RTC时钟分频 4.4 设置、获取RTC计数器及闹钟 5 实时时…

使用 DuckLake 和 DuckDB 构建 S3 数据湖实战指南

本文介绍了由 DuckDB 和 DuckLake 组成的轻量级数据湖方案&#xff0c;旨在解决传统数据湖&#xff08;如HadoopHive&#xff09;元数据管理复杂、查询性能低及厂商锁定等问题。该方案为中小规模数据湖场景提供了简单、高性能且无厂商锁定的替代选择。 1. 什么是 DuckLake 和 D…

大语言模型提示词(LLM Prompt)工程系统性学习指南:从理论基础到实战应用的完整体系

文章目录 前言&#xff1a;为什么提示词工程成为AI时代的核心技能一、提示词的本质探源&#xff1a;认知科学与逻辑学的理论基础1.1 认知科学视角下的提示词本质信息处理理论的深层机制图式理论的实际应用认知负荷理论的优化策略 1.2 逻辑学框架下的提示词架构形式逻辑的三段论…

如何基于Mihomo Party http端口配置git与bash命令行代理

如何基于Mihomo Party http端口配置git与bash命令行代理 1. 确定Mihomo Party http端口配置 点击内核设置后即可查看 默认7892端口&#xff0c;开启允许局域网连接 2. 配置git代理 配置本机代理可以使用 127.0.0.1 配置局域网内其它机代理需要使用本机的非回环地址 IP&am…

埃文科技智能数据引擎产品入选《中国网络安全细分领域产品名录》

嘶吼安全产业研究院发布《中国网络安全细分领域产品名录》&#xff0c;埃文科技智能数据引擎产品成功入选数据分级分类产品名录。 在数字化转型加速的今天&#xff0c;网络安全已成为企业生存与发展的核心基石&#xff0c;为了解这一蓬勃发展的产业格局&#xff0c;嘶吼安全产业…

NLP学习路线图(二十六):自注意力机制

一、为何需要你&#xff1f;序列建模的困境 在你出现之前&#xff0c;循环神经网络&#xff08;RNN&#xff09;及其变种LSTM、GRU是处理序列数据&#xff08;如文本、语音、时间序列&#xff09;的主流工具。它们按顺序逐个处理输入元素&#xff0c;将历史信息压缩在一个隐藏…

Unity3D仿星露谷物语开发60之定制角色其他部位

1、目标 上一篇中定制了角色的衬衫、手臂。 本篇中将定制角色其他部位的图形&#xff0c;包括&#xff1a;裤子、发型、皮肤、帽子等。 2、定制裤子 &#xff08;1&#xff09;修改ApplyCharacterCustomisation.cs脚本 我们需要设置一个输入框选择裤子的颜色。 // Select …

Google机器学习实践指南(机器学习模型泛化能力)

&#x1f525; Google机器学习(14)-机器学习模型泛化能力解析 Google机器学习(14)-机器学习模型泛化原理与优化&#xff08;约10分钟&#xff09; 一、泛化问题引入 ▲ 模型表现对比&#xff1a; 假设森林中树木健康状况预测模型&#xff1a; 图1&#xff1a;初始模型表现 …

MySQL性能调优:Mysql8高频面试题汇总

1&#xff0c;主键和唯一键有什么区别&#xff1f; 主键不能重复&#xff0c;不能为空&#xff0c;唯一键不能重复&#xff0c;可以为空。 建立主键的目的是让外键来引用。 一个表最多只有一个主键&#xff0c;但可以有很多唯一键 2&#xff0c;MySQL常用的存储引擎有哪些&…