Video.js 博客

Pat O'Neill2022-08-22

Video.js 8 和 Video.js HTTP Streaming 3

注意:有关从 Video.js 7.x 迁移到 8.x 的详细信息,请参阅我们的迁移指南

我们非常高兴地宣布 Video.js 8.0 和 Video.js HTTP Streaming (VHS) 3.0 已发布!

虽然这些版本包含了许多内部清理任务,但对于 Video.js 平台的用户来说,也有一些值得关注的变更。

贡献者

在我们深入探讨软件变更之前,开源离不开**人**。非常感谢为这些版本提交拉取请求的每个人!

变更内容?

Video.js

完整的 CHANGELOG 可用,但以下是一些亮点:

  • 不再转译为 ES5 以兼容 Internet Explorer 等旧版浏览器。
  • 更新到 VHS 3.0。
  • 默认启用 sourceset 事件,可以使用 enableSourceset: false 关闭此功能。
  • 新增 TitleBar 组件,默认情况下在 UI 中不可见 (详情请见下文)。因此,我们默认将 BigPlayButton 组件移动到播放器中心。
  • addClassremoveClass 方法现在可以接收多个类名。
  • 点击播放速率按钮现在会打开菜单,而不是改变播放速率。
  • 许多旧的顶级实用方法已弃用,取而代之的是存储在对象上的实用方法 (详情请见下文)
  • 无效事件类型现在将抛出错误,而不是记录警告。
  • addRemoteTextTrackmanualCleanup 选项默认值更改为 false
  • 移除了 videojs.extend() 函数。
  • 移除了 firstplay 事件。
  • 移除了 retryOnError 选项,并将此行为设为默认值。
  • 移除了通过 createEl 方法的 props 参数设置 aria-*roletype 属性的功能。
  • 移除了所有剩余的与 Flash 和 SWF 相关的引用和逻辑。
  • 移除了对缺失 flexbox 支持的后备方案。
  • 移除了 IE 特定的代码。

总的来说,Video.js 的压缩和 Gzip 后的大小**减少了约 3%**。我们将继续寻找优化 Video.js 大小的方法。

VHS

完整的 CHANGELOG 可用,但以下是一些亮点:

  • 不再转译为 ES5 以兼容 Internet Explorer 等旧版浏览器。
  • 为使用更具包容性的语言而更改命名(例如,“master”变为“main”,“blacklist”变为“exclude”,“whitelist”变为“include”)。
  • 立即跳过检测到的空白,而不是等待空白持续时间后再跳过。
  • 移除了已弃用的 smoothQualityChange 方法。
  • 改进了遇到 output-restricted 事件处理时的行为。
  • 清理了 excludePlaylist 的参数。

总的来说,VHS 的压缩和 Gzip 后的大小**减少了约 4%**。我们将继续寻找优化 VHS 大小的方法。

浏览器/设备支持

通过这些发布,我们的新浏览器/设备目标通常专注于所谓“常青浏览器”的最后 3 个主要版本:

  • Chrome
  • Firefox
  • Safari
  • Edge (Chromium,非旧版)

然而,由于 Video.js 被用于桌面和移动网络之外的更多场景,例如智能电视或 OTT 设备,我们为*基于 Chromium 53 及更新版本的浏览器*设置了额外的最低支持阈值。这提供了对以下设备的支持:

新的 Video.js TitleBar 组件

新的 TitleBar 组件将在播放器顶部显示一个 UI 元素,用于显示当前媒体的标题和/或描述。TitleBar 在未提供标题或描述时不会显示。

使用 loadMedia 填充 TitleBar

提供标题和/或描述最简单的方法是使用播放器的 loadMedia 方法

player.loadMedia({
  artist: 'Disney',
  album: 'Oceans',
  title: 'Oceans',
  description: 'Journey in to the depths ... and race with dolphins at play.',
  poster: 'https://vjs.zencdn.net/v/oceans.png',
  src: [{
    src: 'https://vjs.zencdn.net/v/oceans.mp4',
    type: 'video/mp4'
  }, {
    src: 'https://vjs.zencdn.net/v/oceans.webm',
    type: 'video/webm'
  }]
})

如果您不熟悉 loadMedia 方法,它是一种提供除了 src 方法之外更多媒体元数据的方式。如您在上面示例中看到的,提供了 titledescription,它们将用于填充标题栏。

直接填充 TitleBar

TitleBar 也可以通过使用组件的 update 方法进行直接输入来填充。

player.titleBar.update({
  title: 'Oceans',
  description: 'Journey in to the depths ... and race with dolphins at play.'
});

可以通过为其中一个或两个值传递空字符串来删除标题和/或描述。

player.titleBar.update({
  title: '',
  description: ''
});

如果两者都移除,TitleBar 将不再可见。

新的 Video.js 实用对象

随着时间的推移,videojs 命名空间已经充斥着各种各样的实用函数。我们正在引入的其中一个改变是为这些实用函数设计一个更具目的性的接口。

这里的指导原则是,如果一个函数感觉不像库的核心部分,但对插件和其他集成仍然可能有用,我们就将其作为实用对象的一部分而不是顶级函数来暴露。

这些是 8.0.0 中附加到 videojs 的实用对象

对象描述
videojs.browser各种用户代理检测值(以前可用)
videojs.domDOM 函数(以前可用)
videojs.fn函数...函数
videojs.num数字函数
videojs.obj对象函数
videojs.str字符串函数
videojs.time时间相关函数
videojs.urlURL 相关函数

注意:有关从 Video.js 7.x 迁移到 8.x 的详细信息,请参阅我们的迁移指南

结论

再次感谢所有贡献者以及每天使用 Video.js 来支持它的广大开发社区!

如果您想为 Video.js 做出贡献,可以从 GitHub 上的CONTRIBUTING指南开始。

祝您一切顺利,并创造出伟大的作品!

Matthew McClure2019-09-13

Videojs.com 全新上线

如果您今天访问 Video.js 网站,您(希望)会注意到它看起来有点不同。您可能还会注意到您正在主域名而不是 blog.videojs.com 上阅读此内容。如果您注意到其中之一或两者,那么这有些多余,但我今天非常兴奋地宣布 Video.js 项目的新网站。

原计划这个网站需要一个月的时间来构建和发布,而我们却花了……嗯,比那更长的时间,但我们认为这是值得的。这不仅因为我是导致我们与旧网站共度约 6 年时光的负责人,还因为新设计将重点转移到我们认为 Video.js 最重要的方面:你们,构建者,使用 Video.js 进行创作。

2019 年的 Video.js

Heff 于 2010 年首次创建 Video.js 时,对视频播放器的需求和使用原因与今天不同。我问他:“2010 年使用播放器的最大动机是什么,你为什么制作 Video.js?”

嗯,有趣的是,那不是因为 Flash 已死。那要等好几年。也不是为了支持 iPhone,因为那时还无法在那里构建视频控件。仅仅是为了使用原生网络技术来构建视频,而不是第三方插件。这很有趣。

我不知道这是否回答了你的问题。其他那些原因才是大多数人最终使用 Video.js 的原因。

就我个人而言,我对在 2010 年代早期使用 Video.js 的原因会有所不同:它是一个外观漂亮的播放器,并且带有 Flash 回退以支持旧版浏览器。然而,今天 Flash 已经死了,而且无论如何也不再需要,因为浏览器对现代编解码器的支持已经好得多。当然,随着自适应码率流变得普遍,事情变得有点复杂,但即便如此,在浏览器中简单地播放视频已经成了基本要求。

这就是我们喜欢将 Video.js 视为一个播放器*框架*而不是一个播放器原因之一。Video.js 是一个经过充分测试、可扩展且高度可定制的起点,供您为观众创建自己的定制体验。我们努力确保您在使用 Video.js 时能立即获得一个出色的播放器,但如果您愿意,它也可以成为您应用程序完美播放器的起点。

新主题

All four Video.js themes
所有四个 Video.js 主题

为此,我们推出了包含四个新的纯 CSS 主题的网站。每个主题都以其所包含的网站主题命名,但重点是为了展示自定义播放器是多么容易,同时为您创建自己的自定义主题提供一些新的起点。如果您有兴趣了解更多关于使用/构建主题的过程,可以在Mux 博客上找到一个高级概述。

New Logo新 Logo

新 Logo 将在未来几天(老实说,也许是几个月)内慢慢渗透到不同的项目中,但我们有新的贴纸正在制作中!如果您有兴趣将 Video.js 贴在您的笔记本电脑或汽车保险杠上(如果那仍然流行的话),请给我们发一条推文

荣誉归属!

本次重新设计和构建由 Mux 资助(并执行),一如既往地由 Netlify 托管。Browserstack 允许我们在不同的浏览器和设备中测试每个播放器版本,而 Fastly 则提供我们的 CDN 托管版本。最后,但同样重要的是,Video.js 的企业管理者和主要赞助商是 Brightcove

去构建出色的播放器吧

我们很乐意看到您创建的播放器!

💝 @matt_mcclure

Lahiru Dayananda2019-01-16

使用 videojs-http-streaming 支持带内字幕

随着 2018 年 7 月 16 日 videojs-http-streaming (VHS) v1.2.0 的发布,Video.js 内置了对 FMP4 片段中携带的 CEA/CTA-608 字幕的支持。这意味着对于使用 FMP4 片段的 MPEG-DASH 内容和 HLS 流,封闭式字幕会自动解析并提供给 Video.js 播放器。这是一个示例播放器,它显示了字幕(带有“CC”按钮的英语是带有 CEA-608 字幕的轨道)。

如果您对 CEA-608 字幕以及我们从 fmp4 中解析它们的方法,或者对一般概述感到好奇,您可以观看我在Demuxed 2018上的演讲。

字幕解析由 mux.js 库处理,并与 VHS 交互,将解析后的字幕反馈给 Video.js。

用法

创建 CaptionParser

  import { CaptionParser } from 'mux.js/lib/mp4';

  const captionParser = new CaptionParser();

  // initalize the CaptionParser to ensure that it is ready for data
  if (!captionParser.isInitialized()) {
    captionParser.init();
  }

在使用带有 fmp4 片段的 HLS 和 MPEG-DASH 时,可能并非所有解析字幕所需的信息都包含在媒体片段本身中,并且需要将 init 片段中的元数据传递给 CaptionParser。因此,应将 init 片段中定义的视频 trackIds 和 timescales 传递给 CaptionParser。

  import mp4probe from 'mux.js/lib/mp4/probe';

  // Typed array containing video and caption data
  const data = new Uint8Array();
  // Timescale = 90000
  const timescales = mp4probe.timescale(data);
  // trackId = 1
  const videoTrackIds = mp4probe.videoTrackIds(data);

  // Parsed captions are returned
  const parsed = captionParser.parse(
    data,
    videoTrackIds,
    timescales
  );

使用包含 CEA-608 字幕的数据调用 captionParser.parse 将会得到一个具有以下结构的对象

  {
    captions: [
      {
        // You can ignore the startPts and endPts values here
        startPts: 90000,
        endPts: 99000,
        // startTime and endTime can be used for caption times in the TextTrack API
        startTime: 1,
        endTime: 1.1,
        text: 'This is a test caption',
        // This is the CEA-608 "channel" the caption belongs to
        stream: 'CC1'
      }
    ],
    // Includes any (or none) of: CC1, CC2, CC3, CC4
    // This should match the captions returned in the above caption array
    captionStreams: {
      CC1: true
    }
  };

然后,您可以取一个字幕并创建一个 VTTCue,通过 Video.js API 将其添加到 TextTrack

  const player = videojs('video');
  const track = player.addRemoteTextTrack({
    kind: 'captions',
    label: parsed.captions[0].stream,
    default: true,
    language: 'en'
  }, false);

  track.addCue(parsed.captions[0]);

VHS 默认包含在 Video.js v7.x 中。

Gary Katsevman2019-01-11

Video.js 7.4

现在来概述一下 Video.js 7.4,该版本于 12 月初首次发布。此版本最大的新功能是允许您在直播流期间进行寻道的 UI。我们更新了 focus-visible 以与我们的菜单配合使用,添加了更多翻译,为播放/暂停按钮添加了重播选项,以及许多、许多修复,其中多项与辅助功能相关。

我们还在构建过程中放弃了 Grunt 的使用。我们非常感谢 Grunt,因为它为我们提供了很好的服务,但现在是时候继续前进了。

Video.js 7.4.1 是目前的最新版本,而 7.4.2 作为预发布版本将在下周发布。

致谢

在继续之前,我谨向所有参与者表示感谢,我们非常感谢您的贡献!共有14位首次贡献者,我认为这对我们来说是历史新高,我希望这能继续下去!

直播 UI

Video.js 已经支持直播流一段时间了,无论是原生支持,还是通过videojs-http-streaming (VHS)。然而,这个 UI 非常简洁,它禁用了进度条,并且基本上只允许暂停,不过,有一个指示器表明这是一个直播流。

Video.js, with the new Live UI, playing a live stream
Video.js,使用新的直播界面,播放直播流

新 UI 与之前的直播 UI 和常规控制条非常相似。“直播”指示器移到进度条的右侧,并指示我们是在播放直播还是落后于直播。点击此按钮将寻找到“直播点”。时间显示和工具提示将显示相对于直播点的时间;因此,直播点的当前时间将是 0,如果您回退 30 秒,它将显示 -00:30

此功能仍处于实验阶段,因此,它由一个默认关闭的选项控制。我们希望您能尝试并向我们提供反馈,以便我们可以在未来的版本中默认启用它。

要启用此功能,请在播放器中传入 liveui: true:在 JavaScript 中

var player = videojs('my-id', {
  liveui: true
  }
);

或 HTML

<video-js id="my-id" data-setup='{"liveui": true}'}>
  <source src="https://example.com/live.m3u8" type="application/x-mpegurl">
</video-js>

语言

在 7.4 版本系列中,我们增加了许多语言并进行了更新。此外,我们现在将 JSON 文件复制到 dist/lang 文件夹中,以便您更轻松地将其包含在您的项目中。

新增和更新的语言

  • 奥克语 (oc)
  • 俄语 (ru)
  • 威尔士语/康瓦尔语 (cy)
  • 乌克兰语 (uk)
  • 塞尔维亚语 (sr)
  • 瑞典语 (sv)

辅助功能

一如既往,我们致力于使 Video.js 尽可能地易于访问和使用。为此,我们在这些版本中进行了一系列与无障碍功能相关的修复。

  • 使用 VoiceOver 的时间显示无障碍功能
  • 移除进度条中隐藏的控制文本
  • 使跳转到实时点按钮能正确地向屏幕阅读器报告其自身
  • 使剩余时间显示中的 - 仅供视觉显示,而不能被屏幕阅读器读取

其他功能更新

响应式字幕设置对话框

这使用了新的 responsive 设置和断点,使对话框能够根据播放器的大小进行响应,从而改善用户体验。

PlayToggle 的重播选项

当视频结束时,播放切换按钮会将图标更改为重播图标,大多数用户不介意这一点,并且这曾是一个备受请求的功能。此选项允许将其关闭。

焦点可见菜单背景

与其他按钮的轮廓一样,我们使用不同的背景颜色来表示菜单中的焦点。我们应该像处理按钮轮廓一样,在那里也遵守焦点可见的规则。

playerreset 事件

当播放器通过 reset() 方法重置时,它现在会触发一个 playerreset 事件,以告知组件和用户。

其他修复

  • 修复全屏事件触发两次的问题 (7.4.2)
  • 播放切换按钮的鼠标指针
  • 在 loadedmetadata 而非 loadstart 时选择默认字幕
  • 如果未设置语言,则不要将用户偏好应用于字幕
  • 确保 vjs-waiting 仅在我们再次开始播放时才被移除
  • 允许将持续时间设置为 NaN,使 Video.js 更符合规范
  • 修复按下菜单按钮时菜单锁定问题
  • 将子组件移动到新父级时,从旧父级中移除该子组件
  • 视频结束后快进时移除 vjs-ended
  • 鼠标悬停时不要自动隐藏控制栏

7.4.0、7.4.1 和 7.4.2 的完整 CHANGELOG

## [7.4.2](https://github.com/videojs/video.js/compare/v7.4.1...v7.4.2) (2019-01-08)

Bug 修复

  • 当光标移到控制条上方时自动隐藏 #5258 (#5692) (6ebc772)
  • css 动画速记属性顺序 (#5687) (0e69ce9)
  • fs: 确保只有一个全屏更改事件 (#5686) (2bc90a1),关闭 #5685
  • lang: 添加 liveui 组件使用的 sv 翻译 (#5704) (f38726e)
  • package: 更新 @videojs/http-streaming 到版本 1.6.0 🚀 (#5705) (3d093ed)
  • player: 在 seeked 时移除 vjs-ended 类 (#5728) (f1637cd),关闭 #5654
  • remaining-time-display: 使“-”为视觉显示且屏幕阅读器不可读 (#5671) (05513f8),关闭 #5168
  • seekbar: 如果直播追踪器的可寻道范围为无穷大,则不禁用 (#5721) (7f507df)
  • 通过 addChild 移动到新父级时,从旧父级中删除子级 (#5702) (8a3e2a7)

例行任务

文档

  • liveui: 添加 live ui 和 live api 的指南 (#5677) (c147581)
## [7.4.1](https://github.com/videojs/video.js/compare/v7.4.0...v7.4.1) (2018-12-11)

Bug 修复

例行任务

  • package: 更新 autoprefixer 到版本 9.4.2 (#5647) (19f3465)
  • package: 更新 rollup-plugin-node-resolve 到版本 4.0.0 🚀 (#5666) (d07b6c2)

文档

  • 删除 grunt 并更新构建脚本的使用方式 (#5656) (62f9e78)

测试

  • 验证播放器和控制条子项设置为 false 时的空检查 (#5670) (13b42ad)
# [7.4.0](https://github.com/videojs/video.js/compare/v7.3.0...v7.4.0) (2018-12-03)

特性

Bug 修复

例行任务

文档

Garrett Singer2018-12-17

Bugpost:断开与重连

在我以前的公寓里,每当我用微波炉加热一碗燕麦片时,我的 WIFI 就会中断。这很烦人,但我饿了,公寓太小,无法将路由器移离微波炉更远,我也不想购买任何在不同频率下运行的设备。所以我启动微波炉,看着笔记本电脑上正在播放的视频,直到缓冲耗尽,然后看着加载指示器旋转,直到微波炉发出三声提示音。

谢天谢地,视频播放器通常对网络连接(和流氓微波炉)等问题非常 robust(健壮),并且在网络恢复后视频会恢复播放。但最近,我们发现对于 Video.js 中播放的某些内容,视频没有恢复。更糟糕的是,加载指示器直接消失了,屏幕上留下了一个冻结的画面。

您可以通过查看 Video.js 7.3.0,加载 https://dash.akamaized.net/akamai/bbb_30fps/bbb_30fps.mpd 作为源,并使用 Chrome Dev Tools 断开和重新连接网络来亲身看到这种行为。

以下是发生的情况以及我们如何修复它的快速回顾。

加载指示器

为了解决这个 bug,我们从最明显的问题入手:加载指示器消失了。这个指示器由 Video.js 管理。在代码中,当技术触发 waiting 事件时,vjs-waiting 类会添加到 HTML 元素,并在下一个 timeupdate 事件中移除。

/**
 * Retrigger the `waiting` event that was triggered by the {@link Tech}.
 *
 * @fires Player#waiting
 * @listens Tech#waiting
 * @private
 */
handleTechWaiting_() {
  this.addClass('vjs-waiting');
  /**
   * A readyState change on the DOM element has caused playback to stop.
   *
   * @event Player#waiting
   * @type {EventTarget~Event}
   */
  this.trigger('waiting');
  this.one('timeupdate', () => this.removeClass('vjs-waiting'));
}

在记录了播放器发出的事件后,问题变得清晰起来。有些浏览器在waiting事件之后立即发出了timeupdate事件。

因此,timeupdate 事件本身并不可靠,但还能用什么来更好地判断我们是否在等待呢?我们检查了 timeupdate 事件中的 player.currentTime(),发现当我们捕获到最后一个 timeupdate 事件(也就是 waiting 事件之后的那个)时,播放器的时间与 waiting 事件之前的 timeupdate 事件(以及 waiting 事件触发时)的时间相同。

`timeupdate` triggered, player.currentTime = 11
`timeupdate` triggered, player.currentTime = 11.250
`waiting` triggered, player.currentTime = 11.250
`timeupdate` triggered, player.currentTime = 11.250

修复方法很简单。当播放器收到 waiting 事件时,简单地记录下播放器的时间,然后不是在下一个 timeupdate 事件时移除 vjs-waiting 类,而是在下一个与我们记录的时间不同的 timeupdate 事件时移除该类。

您可以在此处查看相关的PR,并且它已在Video.js 7.4.0中提供。

断开连接后恢复播放

加载指示器恢复后,下一个问题是确定为什么在网络重新连接时视频没有恢复播放。首先,我们测试了几种不同的内容。我们测试的 HLS 源确实重新连接了,但 DASH 源没有。更糟糕的是,当使用 DASH 源时,Chrome 的调试控制台冻结了,因为它以计算机能处理的最快速度积累了请求和控制台错误。

控制台崩溃

想象一下您的控制台被以下两条消息重复填充数千次

GET https://dash.akamaized.net/akamai/bbb_30fps/bbb_a64k/bbb_a64k_8.m4a net::ERR_INTERNET_DISCONNECTED
VIDEOJS: WARN: Problem encountered with the current HLS playlist. Trying again since it is the final playlist.

当您的控制台冻结时,调试可能会很困难。这就像在微波炉工作时尝试看视频一样。因此我们首先解决了这个问题。

查看错误消息,我们发现它反复重试上次渲染。这是预期行为,因为我们很久以前就将此功能添加到我们的 HLS 播放列表加载器中。然而,当我们添加 DASH 支持时,我们创建了一个不同的播放列表加载器,但从未添加用于重新加载最终 DASH 播放列表的相同逻辑。

添加节流之后,调试变得容易得多,我们能够再次使用控制台,并深入研究为什么 DASH 无法重新连接而 HLS 可以。

多请求多问题

最后一个问题被证明是最难调试的。最初,我们认为多路分离的内容是问题所在,因为当主片段加载器尝试从视频播放列表加载时,同时发生错误时,有一个独立的音频片段加载器从音频播放列表加载可能会导致问题。然而,HLS 也可以有多路分离的内容,而且在示例源被证明可以正常恢复后,这种方法就被排除了。

通过检查 Chrome 的网络日志,DASH 内容在某个点之后停止请求视频片段,只请求音频片段。但 DASH 的请求远不止两个。视频片段本身包含两个请求:一个用于 init 片段,另一个用于视频数据。

VHS 中的请求由一个名为 media-segment-request 的模块管理,该模块负责请求片段所需的所有内容,无论是密钥、init 片段、媒体数据,还是所有这些,然后才通知片段加载器其请求已完成。对于视频请求,在断开连接后,media-segment-request 从未调用 done 回调。

结果发现,如果我们收到一个错误,我们就会中止该组中的其他请求,并等待调用 done 回调,直到这些请求报告它们已中止。然而,根据 XHR 标准,如果请求未发送,则中止算法可能不会运行。在这种情况下,当网络断开连接时,第一个请求在第二个请求有机会发送之前就报告了错误。在我们中止第二个请求后,我们陷入了等待一个永远不会发生的错误。

我们通过在遇到第一个错误时立即回调错误来解决这个问题,而不是等待每个后续请求完成。

这个问题也应该存在于HLS中,但仅限于片段带有EXT-X-KEY或EXT-X-MAP标签以配合媒体请求的情况。在我们尝试的内容中,这两个标签都不存在,因此它似乎仅限于DASH内容。

错误解决

我们希望这对于描述我们遇到的一些 bug、我们如何进行调查以及解决方案如何等方面有所帮助。我们也很乐意听取您的意见。您可以在 Video.js Slack 的 #playback 频道找到我们,或在 https://github.com/videojs/http-streaming 查阅问题和拉取请求。

现在可以安心享用我的燕麦片和视频了,无需担心播放是否会恢复。

Garrett Singer2018-11-08

Video.js HTTP 流媒体 (VHS) 介绍

“如何让我的视频在 Video.js 中播放?”

这是我们在使用 Video.js 时最常遇到的问题之一。而且这是一个很好的问题。

如果有人查看 Video.js 的副本,他们的内容可能在一个浏览器中播放,而在另一个浏览器中不播放。为了获得特定类型内容的跨浏览器支持,他们必须找到相关的源处理程序(例如,HLS 内容的 videojs-contrib-hls)。只有包含源处理程序后,他们的视频才能在所有主流浏览器中播放。

我们希望 Video.js 易于使用,但目前的设置并不简单。因此,我们决定是时候解决这个问题了。

这就是将 Video.js HTTP 流媒体(昵称 VHS)默认集成到 Video.js 7 中的动机。

什么是 VHS?

VHS logoVHS 标志

VHS 是 videojs-contrib-hls 的继任者。它是一个从 videojs-contrib-hls 仓库分叉出来的源处理程序。虽然 videojs-contrib-hls 最初旨在为所有浏览器添加 HLS 播放功能,但我们意识到该引擎也能很好地播放其他格式。

为了证明这一点,我们添加了一个 DASH 清单解析器,经过一些小的改动,VHS 使用与 HLS 相同的代码库和 API 播放了 DASH 内容。

即使视频技术格局不断变化,Video.js 也将做好准备。如果一种新的流媒体格式流行起来,只需少量代码更改即可为 VHS 添加支持。一个引擎和 API 支持所有格式。

为什么 VHS 默认包含在 Video.js 中?

通过在 Video.js 中默认包含 VHS,您不再需要担心哪个浏览器支持哪种流媒体技术。

Video.js 的构建目的是抽象化网络浏览器之间视频 API 和功能的差异,创建一个尽可能接近网络标准的简单 API,并在可能的情况下填补功能空白。随着时间的推移,浏览器之间的一个差异领域是它们对不同媒体格式的支持。有些浏览器可能支持 DASH 的原生播放,有些支持 HLS,有些则两者都不支持。

以前,这需要通过包含源处理程序和插件来管理,但我们理解简单设置的重要性。通过默认在 Video.js 中包含 VHS,您不再需要担心哪个浏览器支持哪种流媒体技术。它应该可以直接工作。

如果我想选择不使用 VHS 怎么办?

如果您更愿意为 HLS 或 DASH 播放包含不同的源处理程序,Video.js 仍然允许您这样做。Video.js 核心是您熟悉并喜爱的 Video.js,不包含 VHS。一切都应该像以前一样工作。

欢迎贡献和反馈

一如既往,我们期待您的贡献和反馈。就评论、问题、请求、贡献或仅仅是打个招呼,联系我们的最佳方式是 VHS GitHub 页面Video.js slack 上的 #playback 频道

Gary Katsevman2018-10-29

Video.js 7.3:响应式布局、填充模式、createLogger

又过了一个月,Video.js 发布了新版本:v7.3.0。此版本带来了期待已久的功能:响应式布局。此外,填充模式已被提升为一级功能,并添加了 createLogger 以使调试和日志记录更加容易。

此版本目前是预发布版,大约一周后将提升为最新版。请尝试使用并报告您发现的任何问题

致谢

我要感谢所有参与本次版本发布变更的人。任何和所有变更都非常感谢。

响应模式

响应模式将使播放器根据播放器的大小调整 UI 组件。它使用 Video.js v6.7.0 中添加的 playerresize 事件,这使我们能够知道播放器何时改变大小。

响应模式将在播放器大小改变时设置并更改特定的断点类,例如 vjs-layout-small。这些可以进行配置。根据播放器当前拥有的类,控制栏和其他 UI 元素可以进行调整。例如,使用 vjs-layout-small 时,时间控件将不显示,因为进度条上的时间工具提示可用,并且字幕按钮更重要。在更大的尺寸下,两者都可以毫无问题地显示。

您可以在我们的文档页面中找到如何启用响应模式以及更多信息。在仓库中的沙盒文件夹中也有一个示例演练场。

填充模式

填充模式允许 Video.js 播放器动态调整大小,但保持在其父容器的边界内。这类似于流体模式,但有时容器本身已经正确设置了大小。

填充模式并不是一个全新的模式,vjs-fill 类在 Video.js 中已经存在一段时间了。这最终使其成为与流体模式并列的一级功能。

createLogger

这是 videojs.log 上的一个新方法,允许您创建一个带有特定名称的新日志器。然后,它创建一系列名称,以便更容易跟踪哪个组件记录了这条特定消息。特别是,这可以帮助插件作者记录消息,然后只筛选出与其插件相关的消息。

createLogger 返回一个与 videojs.log 具有相同 API 的函数。您可以在下面看到它的实际应用。

示例

添加了一个新方法 player.log,它在后台使用 createLogger。除了 VIDEOJS 之外,它还会记录播放器 ID

var player = videojs('myid');

player.log('foo');
// VIDEOJS: myid: foo

您还可以更进一步,创建一个子日志器

var player = videojs('myid');
var mylog = player.log.createLogger('my-plugin');

mylog.log('foo');
// VIDEOJS: myid: my-plugin: foo

如果您想为自定义插件记录警告或错误

var player = videojs('myid');
var mylog = player.log.createLogger('my-plugin');

mylog.log.warn('foo');
// VIDEOJS: myid: my-plugin: WARN: foo

mylog.log.error('bar');
// VIDEOJS: vid1: my-plugin: ERROR: bar
Gary Katsevman2018-07-10

Video.js 7.1 和 6.11:自动播放和全屏模式的变更

A laptop playing a video in fullscreen mode.
一台笔记本电脑正在全屏模式下播放视频。

距离上次发布文章已经有一段时间了。Video.js 的 7.1.06.11.0 版本充满了贡献者和维护者带来的出色功能。两大变化与自动播放——我们什么时候才能停止谈论自动播放?——和全屏模式有关。不过,里面还有很多其他内容。

Video.js 7.1.0 和 6.11.0 已分别作为 nextnext-6 发布到 npm。

通过 npm 获取 7.1.0

npm install video.js@next

并通过 npm 获取 6.11.0

npm install video.js@next-6

自动播放

我们一直在关注浏览器厂商围绕自动播放所做的变化。我们还做了大量工作,使 Video.js 尽可能地与新的自动播放策略兼容。然而,仍然有一些用例没有被考虑到。为了解决这些问题,我们决定扩展现有的 Video.js autoplay 选项,以包含几个新值:mutedplayany。当前的布尔选项将像现在一样工作,未知选项也将像现在一样处理。

  • muted - 这将在 loadstart 时调用 play() 之前静音视频元素。
  • play - 这将在 loadstart 时调用 play()。这类似于 autoplay 属性,但使用的是调用 play 而不是使用属性。
  • any - 这将在 loadstart 时调用 play(),但如果失败,它将尝试静音播放器并再次尝试 play()

全屏

这些版本中有两项与全屏相关的更改。

第一项是经常被要求的功能,现在终于实现了:双击切换全屏。双击播放器区域内——控制栏和模态对话框之外——将进入或退出全屏播放。

第二个更改是如果全屏不可用(例如,在没有 allowfullscreen 属性的 iframe 中),则禁用全屏切换

Fullscreen available
全屏可用
Fullscreen unavailable
全屏不可用

值得注意的更改

  • 将 "main-desc" 类型的音轨显示为带有音频描述图标
  • 通过 autoprefixer 运行我们的 CSS,稍微减少了输出大小。
  • 即使无法通过编程方式更改音量,如果可以静音,也显示静音开关。例如,在 iOS 上。
  • 使 setSource 成为中间件的选项。

致谢

我要感谢所有为本次发布做出贡献的人!

Gary Katsevman2018-05-11

Video.js 7 来了!🎉

我很高兴地宣布 Video.js 7 现已发布!它通过 Video.js HTTP 流媒体(VHS)项目为 Video.js 带来了 HLS 支持和实验性的 DASH 支持。Video.js 7 也放弃了对一些较旧的 Internet Explorer 浏览器的支持,仅保留了对 IE11 的支持。

虽然它已经发布,但它仍处于预发布状态,并且仅在 npm 上通过 next 标签可用。下周某个时候,我们将切换开关,使其成为最新版本。

changes for removing IE8 code
移除 IE8 代码的更改

本次发布非常令人兴奋,因为这意味着我们能够删除大量针对旧浏览器的代码,现在我们可以开始使用我们以前一直避免的更新的网络平台功能,例如 :not() CSS 选择器。它还将使我们能够展望新功能,而不必受制于支持 IE8 等旧浏览器的需求。

获取 Video.js 7

您可以从 npm 获取它,通过

npm install video.js@next

npm install video.js@7.0.0

GitHub 发布页面

或从我们或另一个 CDN

https://vjs.zencdn.net/7.0.0/video.min.js
https://vjs.zencdn.net/7.0.0/video-js.css
https://unpkg.com/video.js@7.0.0/dist/video.min.js
https://unpkg.com/video.js@7.0.0/dist/video-js.css
https://cdnjs.cloudflare.com/ajax/libs/video.js/7.0.0/video.min.js
https://cdnjs.cloudflare.com/ajax/libs/video.js/7.0.0/video-js.css

VHS 和 Video.js

Video.js 将默认捆绑 VHS,以便新用户更易于使用。但是,有些人不希望使用 VHS 或正在使用其他插件。为此,我们有一个不包含 VHS 的单独 Video.js 版本。

您可以从我们的 CDN 或其他 CDN 获取它

https://vjs.zencdn.net/7.0.0/alt/video.core.min.js
https://unpkg.com/video.js@7.0.0/dist/alt/video.core.min.js
https://cdnjs.cloudflare.com/ajax/libs/video.js/7.0.0/alt/video.core.min.js

最后,预计未来几周会有一篇关于 VHS 的更详细文章。

未来展望

Video.js 已经很长时间没有路线图了。随着这次发布,我们认为现在是时候退一步,创建一个路线图了。

该路线图将考虑到当前未解决的问题以及内部和外部的功能请求。此外,我们还将审查当前可用的功能,并查看是否值得以更现代的网络思维重构它们。

未来,我们还想为 Video.js 8 制定路线图。考虑到此版本仅添加了 VHS 并移除了旧浏览器,现在是时候移除大量已弃用的功能了。

Video.js 7 路线图的更新

Video.js 5.x

截至本次发布,Video.js 5.x 现已正式弃用。这意味着我们不再对其进行开发或向其回溯修复,但如果您仍在使用它,它仍然可用。我们确实敦促您更新到最新的 5.x,或者更好的是,升级到 6.x 或 7。

构建工具

路线图文章中,我们讨论了可能从 Rollup 切换到 webpack,以便更好地支持将 VHS 导入 Video.js。然而,在进行这项工作时,我们发现 Video.js 的文件大小将增加约 20%,这不是一个微不足道的数量,更不用说默认包含 VHS 已经会增加文件大小。

最终,经过大量工作,我们终于弄清楚了如何也使用 Rollup 捆绑 VHS,并且我们正在继续使用 Rollup 进行构建。

Google Analytics

Video.js 7 的 CDN 构建将不再通过我们简化的像素跟踪向 Google Analytics 发送任何数据。

Video.js 6 及以下版本的 CDN 构建将继续发送数据,除非您通过 window.HELP_IMPROVE_VIDEOJS = false 选择退出,但 6.8 及以上版本将在发送数据之前遵循用户可以在其 HTTP 头中设置的“禁止跟踪”选项。

我们将继续调查以公开方式收集 CDN 日志的选项,并在有任何更新时发布。

Pat O'Neill2018-04-17

Video.js 自动播放最佳实践

总结

  • 永远不要假设自动播放会成功。
  • 使用 muted 属性/选项将提高自动播放成功的几率。
  • 首选通过 player.play() 方法进行程序化自动播放,避免使用 autoplay 属性/选项。

引言

最近关于自动播放的讨论很多,我们想花几分钟分享一些使用 Video.js 进行自动播放的最佳实践。

这篇文章旨在提供信息,而不是关于自动播放视频的社论或立场声明。许多用户讨厌自动播放,因为它令人烦恼或消耗宝贵的带宽。而许多免费提供内容的发布者则依赖自动播放来获取为他们的业务提供资金的前置广告。浏览器厂商(和开源库作者)必须根据用户的利益、网络上发布者的利益以及他们自己的业务来权衡这些担忧。用户也必须选择最符合他们偏好的浏览器。

这篇文章不是关于如何规避自动播放策略的方法。那是行不通的,没有人应该浪费时间尝试这样做。我们认为积极规避浏览器内置的用户体验或用户偏好是有害的,这应该是一个不争的事实。

主流浏览器的自动播放策略

我不会详尽地介绍每个浏览器特定的算法,因为它们可能会发生变化,这将违背本文的核心观点:永远不要假设自动播放会成功。

Safari

截至 2017 年 9 月发布的 Safari 11,苹果已经更新了其自动播放策略,以阻止大多数网站上的带声音自动播放。

Chrome

早在 2017 年 9 月,Google 宣布 Chrome 的自动播放策略将在 2018 年 4 月随 Chrome 66 更改,受限于您在链接文章中可以阅读的一系列规则。

Firefox

对于 Firefox,Mozilla 暂时采取了不制定严格自动播放策略的立场。未来可能会改变。也就是说,Firefox 目前确实允许用户通过一些配置更改禁用自动播放

IE11 和 Edge

微软的浏览器没有特定的/已知的自动播放策略——在撰写本文时,自动播放在 IE11 和 Edge 中仍然有效。

如何在 Video.js 中请求自动播放:温故知新

请注意本节标题中使用了“请求”一词。这是有意的,因为它应该被视为一个请求。请记住,永远不要假设自动播放会成功。

Video.js 的优势之一在于它是围绕原生的 <video> 元素接口设计的;因此,它会遵从底层播放技术(在大多数情况下是 HTML5 视频)和浏览器。换句话说,如果浏览器允许,Video.js 也会允许

使用 Video.js 启用自动播放有两种方式

  1. <video> 元素或新的 <video-js> 元素上使用 autoplay 属性。

    <video autoplay src="https://path/to/source.mp4"></video>
    <video-js autoplay src="https://path/to/source.mp4"></video-js>
  2. 使用 autoplay 选项

    videojs('player', {autoplay: true});

默认情况下,您可以遵循 Video.js 中的默认行为。如果自动播放成功,Video.js 播放器将开始播放。如果自动播放失败,Video.js 播放器将表现得如同自动播放已关闭——即,它将在海报图像(或黑框)上方显示“大播放按钮”组件。

如果这样对您有用,那么您的工作就完成了!

提示:如果您想使用自动播放并提高其成功几率,请使用 muted 属性(或 Video.js 中的 muted 选项)。

除此之外,还有一些在处理自动播放时可能有用的通用实践:检测是否支持自动播放,或检测自动播放是成功还是失败。

检测自动播放支持

类似于检测自动播放请求的成功或失败,在创建播放器之前对浏览器执行自动播放功能检测可能很有用。在这些情况下,can-autoplay 库是最佳解决方案。它提供了一个与原生 player.play() 方法类似的基于 Promise 的 API

canAutoplay.video().then(function(obj) {
  if (obj.result === true) {
    // Can autoplay
  } else {
    // Can not autoplay
  }
});

程序化自动播放及成功/失败检测

对于那些关心自动播放请求是否成功的人,Google 和 Apple 都推荐了相同的实践来检测自动播放的成功或拒绝:监听 player.play() 方法返回的 Promise(在支持它的浏览器中),以确定自动播放是否成功。

这可以与 autoplay 属性/选项结合使用,也可以通过调用 player.play() 进行程序化操作,但我们建议完全避免使用 autoplay 属性/选项,并以程序化方式请求自动播放

<video-js id="player" src="https://path/to/source.mp4"></video-js>
var player = videojs('player');

player.ready(function() {
  var promise = player.play();

  if (promise !== undefined) {
    promise.then(function() {
      // Autoplay started!
    }).catch(function(error) {
      // Autoplay was prevented.
    });
  }
});

注意:重要的是要明白,使用这种方法,Video.js player.autoplay() 方法将返回 undefinedfalse。如果您期望您的用户或集成商依赖此方法,请考虑以下部分。

autoplay 属性/选项的程序化自动播放

在为他人构建播放器时,您可能无法始终控制用户是否在其播放器实例中包含 autoplay 属性/选项。值得庆幸的是,将其与程序化自动播放结合使用似乎对播放行为没有显著影响。

根据我们的实验,即使浏览器处理实际的自动播放操作,在开始播放(或播放失败)后调用 player.play() 似乎也不会导致当前浏览器在 Chrome 或 Firefox 中触发额外的 "play" 事件。Safari 11.1 似乎每次调用 player.play() 且自动播放失败时都会触发 "playing""pause" 事件。

尽管如此,如果您拥有完全控制权,我们建议完全避免使用 autoplay 属性/选项,并以程序化方式请求自动播放

注意:即使使用 autoplay 属性/选项结合程序化自动播放,player.autoplay() 方法在播放器准备就绪之前也将返回 undefined

用例示例

在 Brightcove,我们为改善基于 Video.js 播放器的用户体验所做的一件事是,在请求自动播放的播放器上,隐藏“大播放按钮”,直到自动播放成功或失败。这可以防止“大播放按钮”在自动播放开始前在播放器上短暂闪烁的情况发生。

虽然我们的实际实现由于播放器的特定情况而更为复杂,但其要点与此功能性 JSBin 演示相同。

结论

您的代码中可能存在与自动播放是否成功相关的决策点;然而,实际情况是,这之前的所有段落都归结为一个单一的、核心的概念

永远不要假设您的自动播放请求会成功。

牢记这一点,您就会万无一失。即使浏览器完全停止允许自动播放,我们希望推荐的这种方法在未来仍能适用。

下一页 >