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

前端实现视频/直播预览

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

这里有两种情况:

  • 如果是类似.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.valuediv_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.xdnf.cn/news/903907.html

相关文章:

  • 【Kubernetes】K8s 之 ETCD - 恢复备份
  • 职业生涯思考
  • Tomcat全方位监控实施方案指南
  • 撰写脚本,通过发布/joint_states话题改变机器人在Rviz中的关节角度
  • HakcMyVM -TheWall
  • 初识AI Agent
  • 面向开发者的提示词工程④——文本推断(Inferring)
  • 数学建模期末速成 聚类分析与判别分析
  • Caliper 配置文件解析:fisco-bcos.json
  • 【计算机组成原理 第5版】白、戴编著 第六章 总线系统 课后题总结
  • 大模型安全测试报告:千问、GPT 全系列、豆包、Claude 表现优异,DeepSeek、Grok-3 与 Kimi 存在安全隐患
  • LabVIEW工业级多任务实时测控系统
  • ComfyUI 文生图教程,进行第一次的图片生成
  • 连续小波变换(Continuous Wavelet Transform, CWT)
  • 【HarmonyOS 5】出行导航开发实践介绍以及详细案例
  • Spring Boot实现接口时间戳鉴权
  • ABAP设计模式之---“简单设计原则(Simple Design)”
  • Windows无限期暂停更新
  • 模板方法模式:优雅封装不变,灵活扩展可变
  • web3-基于贝尔曼福特算法(Bellman-Ford )与 SMT 的 Web3 DeFi 套利策略研究
  • 贝叶斯深度学习!华科大《Nat. Commun.》发表BNN重大突破!
  • Science Robotics:UCLA 贺曦敏团队综述自主软体机器人
  • dexcap升级版之DexWild——面向户外环境的灵巧手交互策略:人类和机器人演示协同训练(人类直接带上动捕手套采集数据)
  • 【Linux 学习计划】-- 简易版shell编写
  • 【大模型LLM学习】Flash-Attention的学习记录
  • 阿里140 补环境日志
  • 华为 “一底双长焦” 专利公布,引领移动影像新变革
  • Caliper 负载(Workload)详细解析
  • 【NLP中向量化方式】序号化,亚编码,词袋法等
  • MySQL数据库基础(二)———数据表管理