Web 音视频(二)在浏览器中解析视频

前言

浏览器中已经能直接播放视频,为什么还需要手动写代码解析?

因为,某些场景需要对视频进行更细致的处理,比如截取关键帧、提取视频中的文字、人物打码、极低延时播放视频等等。

总之,除了最单纯的视频播放外,对视频数据的一切处理都需要从解析开始。

MP4 简单介绍

MP4 是最流行兼容性最好的视频封装格式之一,在各种浏览器中也得到了良好支持;
本系列后续都以 MP4 视频作为示例,所以先简单介绍 MP4 的基本概念。
其它格式的视频文件需使用对应的解封装 SDK

MP4 可以分为普通 MP4 和 Fragment MP4;
普通 MP4 的元数据可在音视频数据前面(利于网络播放),也可在后面;
Fragment MP4 把音视频数据切成一个个小片段管理,非常方便直播场景,也是 MSE 唯一支持的格式。

图片

MP4 使用 Box 的抽象概念来描述管理数据,不同的数据抽象成不同的 Box,允许多层嵌套 Box;
下图是一个普通 MP4 文件的可视化,该文件视频分辨率存储在 moov box -> trak box -> ... -> avc1 box 中,已编码(压缩)的音视频数据则存储在 mdata box

你可以访问 mp4box.js filereader 来可视化 MP4 文件

MP4 解封装

我们使用 mp4box.js 在浏览器中解封装(demux)MP4 文件;
解封装(demux)可以理解为提取 MP4 文件的元数据,以及将音视频数据解析成一个个包(Sample)方便处理。
而 MP4 Sample 可转换为 EncodedVideoChunk EncodedAudioChunk

图片

WebAV 项目中的 SampleTransform 可将 MP4 文件流转换成 Sample 流(ReadableStream)
mp4FileStream.pipeThrough(new SampleTransform())即可得到 Sample 流。

解封装伪代码

mp4box.js API 文档

const file = mp4box.createFile()
file.onReady = info => {file.setExtractionOptions(info.videoTracks[0]?.id, 'video')file.setExtractionOptions(info.audioTracks[0]?.id, 'audio')file.start()
}file.onSamples = (id, type, samples) => {// `EncodedVideoChunk` 或 `EncodedAudioChunk`const chunks = samples.map(s => new EncodedVideoChunk({type: (s.is_sync ? 'key' : 'delta')timestamp: (1e6 * s.cts) / s.timescale,duration: (1e6 * s.duration) / s.timescale,data: s.data}))
}const mp4stream = await fetch('<mp4 url>').body
let inputBufOffset = 0
while (read ui8ArrBuf for mp4stream) {const inputBuf = ui8ArrBuf.bufferinputBuf.fileStart = inputBufOffsetinputBufOffset += inputBuf.byteLengthfile.appendBuffer(inputBuf)
}

解封装过程不会消耗过多的计算资源,一般使用 js 处理也不会碰到性能瓶颈,该过程不在 WebCodecs 的覆盖范围内。

视频解码

不同的视频需要对应的解封装程序,解封装得到的数据(如 MP4 Sample)可转换为 WebCodecs 中提供的 EncodedVideoChunk EncodedAudioChunk,然后分别由 VideoDecoder AudioDecoder 进行解码(解压)。
使用解码器之前需要初始化配置(decoder.configure),必填参数 codec 可以在解封装时拿到(onReady)。

图片

const videoDecoder = new VideoDecoder({output: (videoFrame) => {// videoFrame 可绘制到 Canvas 进行额外处理},error: console.error,
});
videoDecoder.configure({ codec: '<视频数据对应的编码格式>' });

解码视频数据得到多个 VideoFrame, AudioData 对象,这两个对象包含了对应帧视频、音频的原始数据,可通过其实例的 copyTo 方法将原始数据 copy 到 ArrayBuffer 中。

TIP

  • VideoFrame 可能占用大量显存,及时 close 避免影响性能

  • VideoFrame.copyTo 会将帧的原始数据从显存复制到内存,像素处理请优先使用 WebGL

  • VideoDecoder 输出(output)的 VideoFrame 需要及时 close 否则它将暂停解码 :::

视频帧处理

在浏览器中一般配合使用 CanvasVideoFrame 进行处理,如:

  • 降低视频分辨率

    1. 绘制 VideoFrameCanvasctx.draw(videoFrame, 0, 0)

    2. 创建新的 VideoFramenew VideoFrame(canvas, {...})

  • 裁剪视频;使用 ctx.draw 后面的定位参数,绘制 VideoFrame 指定区域

  • 叠加视频、图片、文字等;先绘制 VideoFrame 再绘制其他元素

  • 降低帧率,平均抽取丢掉多余帧;如 60FPS -> 30FPS,大概每两帧丢掉一帧不绘制

  • 滤镜、抠图、特效等复杂图形处理;使用 WebGL 或 WebGPU

WebAV 视频解析示例

mp4box.js 解封装配合 WebCodecs 解码原理上很简单,但需要阅读大量文档、API 以及编写很多细节逻辑,汇总起来就相对繁琐了。
@webav/av-cliper 提供了 MP4Clip 可以将视频流转换成视频帧(VideoFrame) 屏蔽许多繁琐过程

import { MP4Clip } from '@webav/av-cliper';// 传入一个 mp4 文件流即可初始化
const clip = new MP4Clip((await fetch('<mp4 url>')).body);
await clip.ready;let time = 0;
// 最快速度渲染视频所有帧
while (true) {const { state, video: videoFrame } = await clip.tick(time);if (state === 'done') break;if (videoFrame != null && state === 'success') {ctx.clearRect(0, 0, cvs.width, cvs.height);// 绘制到 Canvasctx.drawImage(videoFrame,0,0,videoFrame.codedWidth,videoFrame.codedHeight);// 注意,用完立即 closevideoFrame.close();}// 时间单位是 微秒,所以差不多每秒取 30 帧,丢掉多余的帧time += 33000;
}
clip.destroy();

关于优联前端

        武汉优联前端科技有限公司由一批从事前端10余年的专业人才创办,是一家致力于H5前端技术研究的科技创新型公司,为合作伙伴提供专业高效的前端解决方案,合作伙伴遍布中国及东南亚地区,行业涵盖广告,教育, 医疗,餐饮等。有效的解决了合作伙伴的前端技术难题,节约了成本,实现合作共赢。开发Web前端,微信小程序、小游戏,2D/3D游戏,动画交互与UI广告设计等各种技术研发。

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

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

相关文章

ETLCloud在iPaas中的是关键角色?

在当今的数字化时代&#xff0c;企业越来越依赖于其处理和分析数据的能力。为了实现这一目标&#xff0c;企业需要将各种异构的应用和数据源集成在一起&#xff0c;形成一个统一的数据视图。在这一过程中&#xff0c;ETL&#xff08;Extract, Transform, Load&#xff09;和iPa…

以太网实战AD采集上传上位机——FPGA学习笔记27

一、设计目标 使用FPGA实现AD模块驱动采集模拟电压&#xff0c;通过以太网上传到电脑上位机。 二、框架设计 数据位宽转换模块&#xff08;ad_10bit_to_16bit&#xff09;&#xff1a;为了方便数据传输&#xff0c;数据位宽转换模块实现了将十位的 AD 数据转换成十六位&#…

YOLOv1、YOLOv2、YOLOv3目标检测算法原理与实战第十三天|YOLOv3实战、安装Typora

1.学习哔哩哔哩《YOLOv1、YOLOv2、YOLOv3目标检测算法原理与实战》 炮哥带你学视频链接 第5章 YOLOv3实战 5.1 YOLOv3实战先导 5.2 pycharm与anaconda的安装 之前已经安装过了&#xff0c;见Pytorch框架与经典卷积神经网络与实战第一天|安装PyCharm&Anaconda&#xff0…

数据库SQLite和SCADA DIAView应用教程

课程简介 此系列课程大纲主要包含七个课时。主要使用到的开发工具有&#xff1a;SQLite studio 和 SCADA DIAView。详细的可成内容大概如下&#xff1a; 1、SQLite 可视化管理工具SQLite Studio &#xff1a;打开数据库和查询数据&#xff1b;查看视频 2、创建6个变量&#x…

YOLOv8改进,YOLOv8检测头融合DSConv(动态蛇形卷积),并添加小目标检测层(四头检测),适合目标检测、分割等

精确分割拓扑管状结构例如血管和道路,对各个领域至关重要,可确保下游任务的准确性和效率。然而,许多因素使任务变得复杂,包括细小脆弱的局部结构和复杂多变的全局形态。在这项工作中,注意到管状结构的特殊特征,并利用这一知识来引导 DSCNet 在三个阶段同时增强感知:特征…

Addressable学习

AssetsBundle是Unity的资源管理机制,将资源打包到AssetsBundle资源包并提供接口能从ab包里面加载资源出来。有了这个机制以后&#xff0c;我们要做资源管理&#xff0c;还需要做: a: 根据项目需求,编写编辑器扩展,提供指定资源打入对应bundle包工具策略; b: 根据项目的需求,资源…

概率密度函数(PDF)分布函数(CDF)——直方图累积直方图——直方图规定化的数学基础

对于连续型随机变量&#xff0c;分布函数&#xff08;Cumulative Distribution Function, CDF&#xff09;是概率密度函数&#xff08;Probability Density Function, PDF&#xff09;的变上限积分&#xff0c;概率密度函数是分布函数的导函数。 如果我们有一个连续型随机变量…

深入解析:Docker 容器如何实现文件系统与资源的多维隔离?

目录 一、RootFs1. Docker 镜像与文件系统层2. RootFs 与容器隔离的意义 二、Linux Namespace1. 进程命名空间1.1 lsns 命令说明1.2 查看“祖先进程”命名空间1.3 查看当前用户进程命名空间 2. 容器进程命名空间2.1 查看容器进程命名空间列表2.2 容器进程命名空间的具体体现 三…

深度学习|表示学习|卷积神经网络|由参数共享引出的特征图|08

如是我闻&#xff1a; Feature Map&#xff08;特征图&#xff09;的概念与 Parameter Sharing&#xff08;参数共享&#xff09;密切相关。换句话说&#xff0c;参数共享是生成 Feature Map 的基础。Feature Map 是卷积操作的核心产物&#xff0c;而卷积操作的高效性正是由参数…

【Linux网络编程】传输层协议

目录 一&#xff0c;传输层的介绍 二&#xff0c;UDP协议 2-1&#xff0c;UDP的特点 2-2&#xff0c;UDP协议端格式 三&#xff0c;TCP协议 3-1&#xff0c;TCP报文格式 3-2&#xff0c;TCP三次握手 3-3&#xff0c;TCP四次挥手 3-4&#xff0c;滑动窗口 3-5&#xf…

ARP 表、MAC 表、路由表、跨网段 ARP

文章目录 一、ARP 表1、PC2、路由器 - AR22203、交换机 - S57004、什么样的设备会有 ARP 表&#xff1f; 二、MAC 表什么样的设备会有 MAC 表&#xff1f; 三、路由表什么样的设备会有路由表&#xff1f; 四、抓取跨网段 ARP 包 所谓 “透明” 就是指不用做任何配置 一、ARP 表…

算法10(力扣20)-有效的括号

1、问题 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 每个右括号都有一个对应的相同类…

每日一题——二叉树的前序遍历和中序遍历和后序遍历

文章目录 二叉树的前序、中序与后序遍历题目描述数据范围&#xff1a;示例&#xff1a;示例 1&#xff1a; 解题思路1. 递归法2. 迭代法 代码实现&#xff08;递归法&#xff09;代码解析示例输出复杂度分析 中序遍历后序遍历 二叉树的前序、中序与后序遍历 题目描述 给定一棵…

【优选算法】8----四数之和

有看过我上篇算法博客并且去做过的铁子们&#xff0c;对这道题的话应该就不会那么陌生了&#xff0c;因为这两道题 的解题思路有着异曲同工之妙~ -----------------------------------------begin------------------------------------- 题目解析&#xff1a; 跟三数之和就多了…

【开源免费】基于SpringBoot+Vue.JS校园失物招领系统(JAVA毕业设计)

本文项目编号 T 150 &#xff0c;文末自助获取源码 \color{red}{T150&#xff0c;文末自助获取源码} T150&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

2025美赛倒计时,数学建模五类模型40+常用算法及算法手册汇总

数学建模美赛倒计时&#xff0c;对于第一次参加竞赛且没有相关基础知识的同学来讲&#xff0c;掌握数学建模常用经典的模型算法知识&#xff0c;并熟练使用相关软件进行建模是关键。本文将介绍一些常用的模型算法&#xff0c;以及软件操作教程。 数学建模常用模型包括&#xf…

【深度学习】常见模型-循环神经网络(Recurrent Neural Network, RNN)

循环神经网络&#xff08;RNN&#xff09; 概念简介 循环神经网络&#xff08;Recurrent Neural Network, RNN&#xff09;是一种用于处理序列数据&#xff08;如时间序列、文本序列等&#xff09;的神经网络模型。与传统神经网络不同&#xff0c;RNN 的结构具有记忆能力&…

Matlab总提示内存不够用,明明小于电脑内存

目录 前言情况1&#xff08;改matlab最大内存限制&#xff09;情况2&#xff08;重启电脑&#xff09;情况3 前言 在使用matlab中&#xff0c;有时候需要占用的内存并没有超过电脑内存依旧会报错&#xff0c;提示内存不够用&#xff0c;可以尝试下面几种方法&#xff0c;总有一…

数据结构(Java)——二叉树

1.概念 二叉树是一种树形数据结构&#xff0c;其中每个节点最多有两个子节点&#xff0c;通常被称为左子节点和右子节点。二叉树可以是空的&#xff08;即没有节点&#xff09;&#xff0c;或者由一个根节点以及零个或多个左子树和右子树组成&#xff0c;其中左子树和右子树也分…

Windows电脑上记录工作待办清单的工具用哪个?

在Windows电脑上记录日常工作待办清单的工具用哪一个比较好呢&#xff1f;想要工作效率高&#xff0c;借助Windows电脑上的待办清单工具&#xff0c;可以帮助大家快速完成各项任务&#xff0c;今天给大家盘点几款工作待办清单工具。 Windows自带的便笺Stickynotes Windows自…