js MediaSource h264

2023-11-07

 

 

https://stackoverflow.com/questions/24102075/mediasource-error-this-sourcebuffer-has-been-removed-from-the-parent-media-sour

 

https://blog.csdn.net/panqisheng/article/details/51470624

 

isTypeSupported

判断是否支持要解码播放的视频文件编码和类型。

MediaSource.isTypeSupported('video/webm; codecs=“vorbis,vp8”’);//是否支持webm
MediaSource.isTypeSupported('video/mp4; codecs=“avc1.42E01E,mp4a.40.2”’);//是否支持mp4
MediaSource.isTypeSupported('video/mp2t; codecs=“avc1.42E01E,mp4a.40.2”’);//是否支持ts

二、实践中的一些坑

1、mime 字符串

mime 字符串指的就是下面这个东西,会在新建 SourceBuffer 中使用到:

var mime = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'
var sourceBuffer = mediaSource.addSourceBuffer(mime);

这个神奇的字符串是什么意思呢?

首先,前面的 video/mp4 代表这是一段 mp4 格式封装的视频,同理也存在类似 video/webmaudio/mpegaudio/mp4 这样的 mime 格式。一般情况下,可以通过 canPlayType 这个方法来判断浏览器是否支持当前格式。

后面的这一段 codecs="...." 比较特别,以逗号相隔,分为两段:

第一段,'avc1.42E01E',即它用于告诉浏览器关于视频编解码的一些重要信息,诸如编码方式、分辨率、帧率、码率以及对解码器解码能力的要求。

在这个例子中,'avc1' 代表视频采用 H.264 编码,随后是一个分隔点,之后是 3 个两位的十六进制的数,这 3 个十六进制数分别代表:

  1. AVCProfileIndication(42
  2. profile_compability(E0
  3. AVCLevelIndication(1E

第一个用于标识 H.264 的 profile,后两个用于标识视频对于解码器的要求。

对于一个 mp4 视频,可以使用 mp4file 这样的命令行工具:

mp4file --dump xxx.mp4

找到 avcC Box 后,就可以看到这三个值:

 

mp4file --dump movie.mp4
...
    type avcC (moov.trak.mdia.minf.stbl.stsd.avc1.avcC) // avc1
     configurationVersion = 1 (0x01)
     AVCProfileIndication = 66 (0x42)    // 42
     profile_compatibility = 224 (0xe0)  // E0
     AVCLevelIndication = 30 (0x1e)      // 1E
...

有一处要注意,后面两个值(profile_compability、AVCLevelIndication)只是浏览器用于判断自身的解码能力能否满足需求,所以不需要和视频完全对应,更高也是可以的。


下面来看 codecs 的第二段 'mp4a.40.2',这一段信息是关于音频部分的,代表视频的音频部分采用了 AAC LC 标准:

'mp4a' 代表此视频的音频部分采用 MPEG-4 压缩编码。

随后是一个分隔点,和一个十六进制数(40),这是 ObjectTypeIndication,40 对应的是 Audio ISO/IEC 14496-3 标准。(不同的值具有不同的含义,详细可以参考官方文档

然后又是一个分隔点,和一个十进制数(2),这是 MPEG-4 Audio Object Type,维基百科中的解释是 "MPEG-4 AAC LC Audio Object Type is based on the MPEG-2 Part 7 Low Complexity profile (LC) combined with Perceptual Noise Substitution (PNS) (defined in MPEG-4 Part 3 Subpart 4)",具体是什么意思就不翻译了,其实就是一种 H.264 视频中常用的音频编码规范。

这一整段 codecs 都有完善的官方文档,可以参考:

The 'Codecs' and 'Profiles' Parameters for "Bucket" Media Types

 

2、如何转码出符合标准的视频

目前有很多开源的视频处理工具,比如 FFMPEGHandBrake,我用的后者转码,前者切割。

转码其实很简单,HandBrake 打开后,加入想要处理的视频(mp4 格式),窗口下半部分 video 标签,H.264 Profile 选择 "Baseline",level 选择 "3.0";audio 标签,选择 Encoder 为 "AAC"。

然后就是把视频切割为比较小的 chunk,ffmpeg 就可以很方便地切割:

ffmpeg -ss 00:00:00 -i source2.mp4 -c copy -t 00:00:05 xxxx.mp4

上面这段命令就切出了视频的第 0 秒到第 5 秒。

注意一个问题,ffmpeg 在切割视频的时候无法做到时间绝对准确,因为视频编码中关键帧(I帧)和跟随它的B帧、P帧是无法分割开的,否则就需要进行重新帧内编码,会让视频体积增大。所以,如果切割的位置刚好在两个关键帧中间,那么 ffmpeg 会向前/向后切割,所以最后切割出的 chunk 长度总是会大于等于应有的长度。


 

3、向 SourceBuffer 中添加多个 chunk

第一部分的范例中只是请求了一段 chunk 然后加入到播放器里,如果视频很长,存在多个chunk 的话,就需要不停地向 SourceBuffer 中加入新的 chunk。

这里就需要注意一个问题了,即 appendBuffer 是异步执行的,在完成前,不能 append 新的 chunk:

sourceBuffer.appendBuffer(buffer1)
sourceBuffer.appendBuffer(buffer2)

// Uncaught DOMException: Failed to set the 'timestampOffset' property on 'SourceBuffer': This SourceBuffer is still processing an 'appendBuffer' or 'remove' operation.

而是应该监听 SourceBuffer 上的 updateend 事件,确定空闲后,再加入新的 chunk:

sourceBuffer.addEventListener('updateend', () => {
    // 这个时候才能加入新 chunk
    // 先设定新chunk加入的位置,比如第20秒处
    sourceBuffer.timestampOffset = 20
    // 然后加入
    sourceBuffer.append(newBuffer)
}

 

4、码率自适应算法

对于随时变化的网络情况,我们会根据情况加载不同码率的视频,这里就需要一些控制算法决定当前加载哪个码率的视频。

很容易就能想到一种简单的算法:上一段 chunk 加载完后,计算出加载速度,从而决定下一个 chunk 的码率。

但这种朴素的算法有很严重的问题,即它假设网络是相当稳定的,我们可以根据当前的信息预测出未来的网速。但这已经被大量的统计数据证明是不现实的,换句话说,我们没办法预测未来的网络环境。

所以学术界提出了一系列新的算法,比如最常见的 Buffer-Based 算法,即根据当前缓冲区里视频的长度,决定下一个 chunk 的码率。如果有很长的缓冲,那么就加载高码率的视频。这在相当于一个积分控制器,把时刻变化的无法预测的网络环境在时间维度上积分,以获得一个更平缓更能预测的函数。

但是 Buffer-Based 算法依然有问题,在视频起步阶段,缓冲区里的视频很短,导致无论网络环境如何,起步阶段的码率都是很低的。所以 Buffer-Based 算法只适用于视频 startup 后的稳态阶段。在起步阶段,依然有很多优化的空间,这也不是本文的重点,具体就不再详述了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

js MediaSource h264 的相关文章

  • 仿中国婚博会微信小程序

    仿中国婚博会微信小程序 app json pages pages index index pages cash cash pages marry marry pages community community pages me me pag
  • 求二叉树中两个指定节点的最短距离

    给定一个二叉树 找到该树中两个指定节点间的最短距离 思路 求最近公共祖先节点 然后再求最近公共祖先节点到两个指定节点的路径 再求两个节点的路径之和 const shortestDistance function root p q let l
  • js倒计时

    html部分代码 div class time span 60 span span s span div js部分代码 var second document getElementById second var m 60 var time
  • html中使用js实现体彩11选5随机选号

    体彩11选5随机选号 页面预览 代码实现
  • 了解如何在20分钟内创建您的第一个Angular应用

    Angular is a JavaScript framework created my Misko Hevery and maintained by Google It s an MVC Model View Vontroller You
  • 多维数组变成一维数组

    这个问题来源于一个朋友曾经问过我的问题 当时是一个二维数组变成一维数组 后面我想整理一下 整理一个多维 并且是不定维的数组 一 二维数组变成一维数组 1 遍历数组 将元素一个个放入新数组 结果 如果元素不是数组 将会报错 下面是改良版 这样
  • Python 使用execjs调用网页js 进行数据加密

    最近做一个数据采集项目的时候需要自动采集网站的招投标数据 随便打开一个网站 打开开发者模式 输入关键词 点击搜索 获得以下内容 可以看到请求链接和请求类型 请求类型Content Type 是application x www form u
  • Vue中鼠标悬停更换图片/文字内容,动态展示/修改某些属性

    Vue中鼠标悬停更换图片 文字内容 动态展示 修改某些属性 鼠标悬停时 mouseenter 鼠标离开时 mouseleave 利用以上来绑定相应方法 例如 div 分别为鼠标悬停时和离开时绑定方法changeImageSrc 并传递参数
  • JavaScript重写Symbol(Symbol.iterator)实现迭代器(1)

    iterator迭代 做的跟java集合迭代差不多就行了 示例图 h1 对象遍历重写iterator接口1 h1
  • Ajax核心技术之XMLHttpRequest对象

    XMLHttpRequest对象到底是什么 跟Ajax到底有什么联系 在了解它之前还是要先了解一下Ajax的功能 与以往的技术不同 Ajax是为了实现异步操作 那么关于异步 好像一个管理者安排好一个项目计划后 将这个项目交给下属去做 而自己
  • JavaScript动态生成表格

    源代码
  • js 字符串拼接的4种方法

    一 使用连接符 把想要连接的字符串串起来 let shy 帅哥 let a 我是 shy console log a 我是帅哥 二 模板字符串 模板字符串 template string 是增强版的字符串 用反引号 标识 特点 1 字符串中
  • JS 时区时间转换

    业务场景 页面服务器时间是东八区时间 页面 JS 功能需要对比服务器时间和用户本地时间 为兼容世界各地时间 需要将用户本地时间转换为东八区时间 基本概念 格林威治时间 格林威治子午线上的地方时 或零时区 中时区 的区时叫做格林威治时间 也叫
  • 用于富 Web 开发的 13 个免费 JavaScript 库和插件

    在这个新的一天伴随着最新技术崛起的舞台上 让您的商业品牌绽放光芒的唯一方法就是紧跟市场流行的趋势 使用 HTML 和 JavaScript 等技术是通过其中使用的一流功能获得盈利业务的灵魂 当从技术角度谈论 JavaScript 时 考虑到
  • 微信小程序之map地图规划路线以及显示距离

    有个问题 在选择公交路线 包含步行和公交 时 怎么才能让不同的路线显示不同的颜色 ps 有个方式 自己写坐标解压往后的存入新数组 把步行时的数据标注下 有什么简单的方法呢 自定义函数文件 自动获取定位信息 function getLocat
  • js formatDate 时间转换

    formatDate function time fmt type type 类型 0 时间为秒 1 时间为毫秒 var date new Date type 0 time 1000 time var o M date getMonth 1
  • hooks实践总结

    何为hooks 在React中hook是指不编写 class 的情况下使用 state 以及其他的 React 特性 而Vue3也推出了具有相同功能的组合式API 如果你用过Vue3就会知道在 setup 中你应该避免使用 this 因为h
  • 节流与防抖

    1 我们先了解为什么要节流和防抖 我们给一个inpu输入框绑定一个oninput事件 此时我们输入 前端开发 四个字 我们 观察以下后台打印
  • JavaScript 简介

    简介 JavaScript是一门脚本语言 这门语言主要用于 HTML 和 web 更可广泛用于服务器 PC 笔记本电脑 平板电脑和智能手机等设备 前端开发中JavaScript代码可以被插入到HTML页面代码中使用 并由浏览器来执行 示例
  • Vue中的import from

    Vue中的import from 大家都知道 import from 是用来引入一些文件的 在vue中 可能有 js文件 json文件 vue文件 在JS和JSON文件引入的时候 往往需要写入一些 例如数组 export const a 例

随机推荐

  • 下载网页视频简单的办法之一

    下载网页视频简单的办法之一 下载小网站网页视频的简单办法之一 添加插件 使用方法 局限性 下载小网站网页视频的简单办法之一 经常在小网站 比如91xxx youxxxx 上看到喜欢的小视频 想要收藏 你懂的 无赖很多都要VIP才给下载 以前
  • kali_linux (install版)移动硬盘(物理机)安装记录

    作者 瓴 时间 2023 04 23 kali linux install版 移动硬盘 物理机 安装问题记录 1 安装介绍 1 1 相关参数 2 kali 安装 2 1 制作系统启动U盘 2 2 移动硬盘分区 2 2 系统安装 2 3 引导
  • UE4_异步_数据处理(Json)

    如果一个数字城市demo 需要将第三方海量的数据进行处理展示 将数据的处理放在GameThread 上显然是不合理 这个时候需要用多线程解析数据 防止游戏线程的阻塞 关于异步和多线程 前两天面试被别人问到一个问题 异步和多线程的区别 面试的
  • 代码静态测试工具

    Ounec5 0 扫描语言VB C C C Java 属于付费工具 Coverity Prevent 扫描语言有C C C Java 属于付费工具 Stake SmartRiskAnalyzer 扫描语言C C Java 属于付费工具 Ra
  • 【缓存】一种新的缓存 Caffeine Cach 介绍

    1 概述 转载 真正的缓存之王 Google Guava 只是弟弟 Guava Cache 他的优点是封装了get put操作 提供线程安全的缓存操作 提供过期策略 提供回收策略 缓存监控 当缓存的数据超过最大值时 使用LRU算法替换 这一
  • upload-labs通关秘籍和安装环境

    upload labs通关 一 什么是upload labs 二 漏洞 三 安装环境 四 小试牛刀 第一关 pass 01 客户端检测绕过 js检测 第二关 pass 02 content type 服务器端检测 MIME 类型 第三关 上
  • element-ui组件学习

    element ui组件的大致分类 element ui的组件大致分为以下几类 Basic Form Data Notice Navigation Other 组件分类的大致意思 basic组件类型 是一些关于页面布局 按钮和icon等相关
  • 后台数据转换成json数组字符串到前端方法

    1 将结果集ResultSet转化为List集合 对结果集转换成list集合 public List
  • window丢失msvcp90.dll怎么办

    今天在使用py2exe生成编译的时候出现了 No such file or directory msvcp90 dll 下面是解决的方法 1 首先把msvcp90 dll下载到本机 这个就要去网上自己找一下了 2 将下载好的 msvcp90
  • 界面组件Qt Widgets入门指南,让跨平台嵌入式界面开发更简单!

    Qt 是目前最先进 最完整的跨平台C 开发工具 它不仅完全实现了一次编写 所有平台无差别运行 更提供了几乎所有开发过程中需要用到的工具 如今 Qt已被运用于超过70个行业 数千家企业 支持数百万设备及应用 点击获取Qt Widget组件下载
  • php编译问题Cannot find OpenSSL's evp.h

    在php redis的遇到 Cannot find OpenSSL s
  • 树的遍历方式

    树的三种遍历 一棵树的三种遍历方式 先序遍历 中序遍历 后序遍历 前中后三种顺序其实指的是根的顺序 具体看后文 先序遍历 访问顺序 1 根节点 2 左子树 3 右子树 这里根节点是最优先级 因为是先序 根节点放最前 1 中序遍历 访问顺序
  • CSRF 漏洞原理详解及防御方法

    跨站请求伪造 攻击者可以劫持其他用户进行的一些请求 利用用户身份进行恶意操作 例如 请求http x com del php id 1 是一个删除ID为1的账号 但是只有管理员才可以操作 如果攻击者把这个页面嵌套到其他网站中 img src
  • 各种操作系统支持的磁盘格式对比

    各种操作系统支持的磁盘格式对比 操作系统 支持的磁盘格式 Windows FAT32 exFAT NTFS macOS HFS APFS Linux EXT2 EXT3 EXT4 XFS Btrfs BSD UFS Solaris ZFS
  • MacOS搭建Flutter 环境

    流程 第一步 官网下载对应版本的flutter SDK MacOS有两个版本 x64和 arm64 查看命令 uname a 官网链接 Flutter SDK archive Flutter 下载成功后会自动解压 把Flutter文件放到自
  • 【4】Docker容器相关命令

    1 查看 容器 1 查看正在运行的容器 docker ps 2 查看所有容器 包括 运行中的容器 和 没有运行的容器 docker ps a a 是 all 缩写 3 查看最后一次运行的容器 docker ps l l 是 last 的缩写
  • easyexcel功能扩展:读取excel日期格式(包括日期格式和文本格式)

    实体类属性 ExcelProperty value 时间 index 11 private String time 调用DateUtil DateUtil setParams yyyy MM dd yyyy MM dd DateUtil f
  • 两台计算机如何组成局域网,教你两台电脑如何建立局域网,win10系统为例

    虽然我们可以通过第三方的工具来传输文件 但是如果我们的电脑无法上网怎么办 想要两台电脑建立局域网发送大文件怎么操作呢 今天就这个两台电脑建立局域网的方法给大家讲解一下 希望可以帮助到有需要的朋友们 两台电脑建立局域网步骤 1 点击网络图标
  • 2.1 zio入门——把函数作用作为工作蓝图

    ZIO标准库的核心数据类型是ZIO R E A 这种类型的值被称为函数式作用 函数式作用是并发工作流的一种蓝图 如图1所示 该蓝图本质上是纯描述性的 必须执行才能观察到任何副作用 例如与数据库的交互 日志记录 流传输 网络中的数据 或接受请
  • js MediaSource h264

    https stackoverflow com questions 24102075 mediasource error this sourcebuffer has been removed from the parent media so