音频和视频交付

我们可以在网页上以多种方式交付音频和视频,从“静态”媒体文件到自适应直播流。本文旨在作为探索基于网页的媒体的各种交付机制以及与流行浏览器的兼容性的起点。

音频和视频元素

无论我们处理的是预先录制的音频文件还是直播流,使它们通过浏览器的 <audio><video> 元素可用的机制基本相同。目前,为了支持所有浏览器,我们需要指定两种格式,尽管随着 MP3 和 MP4 格式在 Firefox 和 Opera 中的采用,这种情况正在迅速改变。您可以在 网页媒体类型和格式指南 中找到兼容性信息。

为了交付视频和音频,通常的通用工作流程如下

  1. 通过特征检测检查浏览器支持哪些格式(如上所述,通常是两种)。
  2. 如果浏览器不支持任何提供的格式的本机播放,则显示静止图像或使用备用技术来显示视频。
  3. 确定您希望如何播放/实例化媒体(例如 <video> 元素,或者可能是 document.createElement('video')?)。
  4. 将媒体文件传递到播放器。

HTML 音频

html
<audio controls preload="auto">
  <source src="audiofile.mp3" type="audio/mpeg" />

  <!-- fallback for browsers that don't support mp3 -->
  <source src="audiofile.ogg" type="audio/ogg" />

  <!-- fallback for browsers that don't support audio tag -->
  <a href="audiofile.mp3">download audio</a>
</audio>

上面的代码将创建一个音频播放器,该播放器将尝试预加载尽可能多的音频以实现流畅的播放。

注意:preload 属性可能会被一些移动浏览器忽略。

有关更多信息,请参阅 跨浏览器音频基础知识(HTML 音频详解)

HTML 视频

html
<video
  controls
  width="640"
  height="480"
  poster="initialimage.png"
  autoplay
  muted>
  <source src="videofile.mp4" type="video/mp4" />

  <!-- fallback for browsers that don't support mp4 -->
  <source src="videofile.webm" type="video/webm" />

  <!-- specifying subtitle files -->
  <track src="subtitles_en.vtt" kind="subtitles" srclang="en" label="English" />
  <track
    src="subtitles_no.vtt"
    kind="subtitles"
    srclang="no"
    label="Norwegian" />

  <!-- fallback for browsers that don't support video tag -->
  <a href="videofile.mp4">download video</a>
</video>

上面的代码创建了一个 640x480 像素的视频播放器,在播放视频之前显示一张海报图像。我们指示视频自动播放,但默认情况下静音。

注意:autoplay 属性可能会被一些移动浏览器忽略。此外,自动播放功能在被误用时可能存在争议。强烈建议您阅读 媒体和网页音频 API 的自动播放指南 以了解如何明智地使用自动播放。

有关更多信息,请参阅 <video> 元素创建跨浏览器视频播放器

JavaScript 音频

js
const myAudio = document.createElement("audio");

if (myAudio.canPlayType("audio/mpeg")) {
  myAudio.setAttribute("src", "audiofile.mp3");
} else if (myAudio.canPlayType("audio/ogg")) {
  myAudio.setAttribute("src", "audiofile.ogg");
}

myAudio.currentTime = 5;
myAudio.play();

我们根据浏览器支持的音频文件类型设置音频源,然后将播放头设置在 5 秒处并尝试播放它。

注意:除非由用户发起的事件发出,否则大多数浏览器将忽略播放。

还可以使用 <audio> 元素向其提供一个 base64 编码的 WAV 文件,从而允许动态生成音频

html
<audio id="player" src="data:audio/x-wav;base64,UklGRvC…"></audio>

Speak.js 使用这种技术。

JavaScript 视频

js
const myVideo = document.createElement("video");

if (myVideo.canPlayType("video/mp4")) {
  myVideo.setAttribute("src", "videofile.mp4");
} else if (myVideo.canPlayType("video/webm")) {
  myVideo.setAttribute("src", "videofile.webm");
}

myVideo.width = 480;
myVideo.height = 320;

我们根据浏览器支持的视频文件类型设置视频源,然后设置视频的宽度和高度。

网页音频 API

在此示例中,我们使用 fetch() API 检索 MP3 文件,将其加载到源中,然后播放它。

js
let audioCtx;
let buffer;
let source;

async function loadAudio() {
  try {
    // Load an audio file
    const response = await fetch("viper.mp3");
    // Decode it
    buffer = await audioCtx.decodeAudioData(await response.arrayBuffer());
  } catch (err) {
    console.error(`Unable to fetch the audio file. Error: ${err.message}`);
  }
}

const play = document.getElementById("play");
play.addEventListener("click", async () => {
  if (!audioCtx) {
    audioCtx = new AudioContext();
    await loadAudio();
  }
  source = audioCtx.createBufferSource();
  source.buffer = buffer;
  source.connect(audioCtx.destination);
  source.start();
  play.disabled = true;
});

您可以 在线运行完整示例,或 查看源代码

使用网页音频 API 中了解有关网页音频 API 基础知识的更多信息。

getUserMedia / 流 API

还可以使用 getUserMedia 和流 API 从网络摄像头和/或麦克风获取直播流。这构成了更广泛的技术(称为 WebRTC(网页实时通信))的一部分,并且与最新版本的 Chrome、Firefox 和 Opera 兼容。

要从您的网络摄像头获取流,首先设置一个 <video> 元素

html
<video id="webcam" width="480" height="360"></video>

接下来,如果受支持,将网络摄像头源连接到视频元素

js
if (navigator.mediaDevices) {
  navigator.mediaDevices
    .getUserMedia({ video: true, audio: false })
    .then(function onSuccess(stream) {
      const video = document.getElementById("webcam");
      video.autoplay = true;
      video.srcObject = stream;
    })
    .catch(function onError() {
      alert(
        "There has been a problem retrieving the streams - are you running on file:/// or did you disallow access?",
      );
    });
} else {
  alert("getUserMedia is not supported in this browser.");
}

要了解更多信息,请阅读我们的 MediaDevices.getUserMedia 页面。

Mediastream 录制

正在推出新的标准,允许您的浏览器使用 getUserMedia 从麦克风或摄像头获取媒体,并使用新的 MediaStream 录制 API 即时录制媒体。您获取从 getUserMedia 收到的流,将其传递给 MediaRecorder 对象,获取结果输出,然后将其传递到音频或视频源*。

主要机制概述如下

js
navigator.mediaDevices
  .getUserMedia({ audio: true })
  .then(function onSuccess(stream) {
    const recorder = new MediaRecorder(stream);

    const data = [];
    recorder.ondataavailable = (e) => {
      data.push(e.data);
    };
    recorder.start();
    recorder.onerror = (e) => {
      throw e.error || new Error(e.name); // e.name is FF non-spec
    };
    recorder.onstop = (e) => {
      const audio = document.createElement("audio");
      audio.src = window.URL.createObjectURL(new Blob(data));
    };
    setTimeout(() => {
      rec.stop();
    }, 5000);
  })
  .catch(function onError(error) {
    console.log(error.message);
  });

有关更多详细信息,请参阅 MediaStream 录制 API

媒体源扩展 (MSE)

媒体源扩展 是 W3C 的一个工作草案,计划扩展 HTMLMediaElement 以允许 JavaScript 生成用于播放的媒体流。允许 JavaScript 生成流有助于实现各种用例,例如自适应流和时间推移直播流。

加密媒体扩展 (EME)

加密媒体扩展 是 W3C 的一项提案,用于扩展 HTMLMediaElement,提供用于控制受保护内容播放的 API。

该 API 支持从简单的明文密钥解密到高价值视频(在适当的用户代理实现的情况下)的各种用例。许可证/密钥交换由应用程序控制,有助于开发支持各种内容解密和保护技术的强大播放应用程序。

EME 的主要用途之一是允许浏览器实现 DRM (数字版权管理),这有助于防止基于网页的内容(尤其是视频)被复制。

自适应流

正在推出新的格式和协议来简化自适应流。自适应流媒体意味着流的带宽和通常的质量可以根据用户的可用带宽实时改变。自适应流通常与直播流结合使用,在直播流中,音频或视频的平滑交付至关重要。

用于自适应流的主要格式是 HLSMPEG-DASH。MSE 是专为 DASH 而设计的。MSE 根据 ISOBMFFM2TS(DASH 都支持,后者在 HLS 中受支持)定义字节流。一般而言,如果您对标准感兴趣,正在寻求灵活性,或者希望支持大多数现代浏览器,您可能更适合使用 DASH。

注意:目前 Safari 不支持 DASH,尽管 dash.js 将在计划与 OSX Yosemite 一起发布的更新版本的 Safari 中运行。

DASH 还提供了一些配置文件,包括简单的按需配置文件,这些配置文件不需要预处理和拆分媒体文件。还有一些基于云的服务可以将您的媒体转换为 HLS 和 DASH。

有关更多信息,请参阅 直播网页音频和视频

自定义您的媒体播放器

您可能希望您的音频或视频播放器在所有浏览器中都具有统一的外观,或者只是希望调整它以匹配您的网站。实现此目的的通用技术是省略 controls 属性,以便不显示默认的浏览器控件,使用 HTML 和 CSS 创建自定义控件,然后使用 JavaScript 将控件链接到音频/视频 API。

如果您需要其他功能,可以添加目前默认播放器中不存在的功能,例如播放速度、质量流切换,甚至音频频谱。您还可以选择如何使播放器响应——例如,您可以在特定条件下删除进度条。

您可以检测点击、触摸和/或键盘事件来触发播放、暂停和拖动等操作。为了用户方便和可访问性,记住键盘控制通常很重要。

一个简单的例子 - 首先在 HTML 中设置您的音频和自定义控件

html
<audio
  id="my-audio"
  src="http://jPlayer.org/audio/mp3/Miaow-01-Tempered-song.mp3"></audio>
<button id="my-control">play</button>

添加一些 JavaScript 代码来检测播放和暂停音频的事件

js
window.onload = () => {
  const myAudio = document.getElementById("my-audio");
  const myControl = document.getElementById("my-control");

  function switchState() {
    if (myAudio.paused) {
      myAudio.play();
      myControl.textContent = "pause";
    } else {
      myAudio.pause();
      myControl.textContent = "play";
    }
  }

  function checkKey(e) {
    if (e.code === "Space") {
      // space bar
      switchState();
    }
  }

  myControl.addEventListener(
    "click",
    () => {
      switchState();
    },
    false,
  );

  window.addEventListener("keypress", checkKey, false);
};

您可以 在这里试用这个例子。有关更多信息,请参阅 创建您自己的自定义音频播放器

音频/视频的其他提示

停止媒体下载

虽然停止媒体播放与调用元素的 pause() 方法一样简单,但浏览器会继续下载媒体,直到媒体元素通过垃圾回收被处理掉。

这里有一个立即停止下载的技巧

js
const mediaElement = document.querySelector("#myMediaElementID");
mediaElement.removeAttribute("src");
mediaElement.load();

通过删除媒体元素的 src 属性并调用 load() 方法,您可以释放与视频相关的资源,从而停止网络下载。您必须在删除属性后调用 load(),因为仅仅删除 src 属性不会调用加载算法。如果 <video> 元素还有 <source> 元素子节点,则在调用 load() 之前也应该删除这些子节点。

请注意,将 src 属性设置为一个空字符串实际上会导致浏览器将其视为将视频源设置为相对路径。这会导致浏览器尝试下载另一个不太可能是有效视频的内容。

在媒体中搜索

媒体元素支持将当前播放位置移动到媒体内容中的特定点。这是通过设置元素的 currentTime 属性的值来完成的;有关元素属性的更多详细信息,请参阅 HTMLMediaElement。将值设置为您想要继续播放的时间(以秒为单位)。

您可以使用元素的 seekable 属性来确定当前可用于搜索的媒体范围。这将返回一个 TimeRanges 对象,列出您可以搜索到的时间范围。

js
const mediaElement = document.querySelector("#mediaElementID");
mediaElement.seekable.start(0); // Returns the starting time (in seconds)
mediaElement.seekable.end(0); // Returns the ending time (in seconds)
mediaElement.currentTime = 122; // Seek to 122 seconds
mediaElement.played.end(0); // Returns the number of seconds the browser has played

指定播放范围

在为 <audio><video> 元素指定媒体的 URI 时,您可以选择性地包含其他信息来指定要播放的媒体部分。为此,请附加一个井号(“#”),后面跟着媒体片段描述。

时间范围使用以下语法指定

#t=[starttime][,endtime]

时间可以指定为秒数(作为浮点值),也可以指定为以冒号分隔的小时/分钟/秒时间(例如 2:05:01 代表 2 小时 5 分钟 1 秒)。

一些例子

http://example.com/video.ogv#t=10,20

指定视频应该播放 10 秒到 20 秒的范围。

http://example.com/video.ogv#t=,10.5

指定视频应该从开始播放到 10.5 秒。

http://example.com/video.ogv#t=,02:00:00

指定视频应该从开始播放到 2 个小时。

http://example.com/video.ogv#t=60

指定视频应该从 60 秒开始播放,并播放到视频结束。

错误处理

错误将传递到与导致错误的源相对应的子 <source> 元素。

这使您可以检测哪些源加载失败,这可能很有用。考虑以下 HTML

html
<video>
<source id="mp4_src"
  src="video.mp4"
  type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>
</source>
<source id="3gp_src"
  src="video.3gp"
  type='video/3gpp; codecs="mp4v.20.8, samr"'>
</source>
<source id="ogg_src"
  src="video.ogv"
  type='video/ogv; codecs="theora, vorbis"'>
</source>
</video>

由于 Firefox 在某些平台上不支持 MP4 和 3GP(由于其专利受限的性质),因此具有 ID“mp4_src”和“3gp_src”的 <source> 元素将在加载 Ogg 资源之前收到 error 事件。源按照它们出现的顺序进行尝试,一旦一个源成功加载,其余的源将不再尝试。

检查浏览器是否支持提供的格式

在您的音频和视频元素中使用以下经过验证的源来检查支持情况。

如果这些无法播放,那么您正在测试的浏览器不支持给定的格式。请考虑使用其他格式或使用备用方案。

如果这些工作但您提供的文件不起作用,则可能存在两个问题

1. 媒体服务器没有使用文件传递正确的 MIME 类型

虽然这通常得到支持,但您可能需要在媒体服务器的 .htaccess 文件中添加以下内容。

# AddType TYPE/SUBTYPE EXTENSION

AddType audio/mpeg mp3
AddType audio/mp4 m4a
AddType audio/ogg ogg
AddType audio/ogg oga

AddType video/mp4 mp4
AddType video/mp4 m4v
AddType video/ogg ogv
AddType video/webm webm
AddType video/webm webmv

2. 您的文件编码不正确

您的文件可能编码不正确 - 请尝试使用以下工具之一进行编码,这些工具已被证明非常可靠

检测何时没有源加载

要检测所有子 <source> 元素是否加载失败,请检查媒体元素的 networkState 属性的值。如果这是 HTMLMediaElement.NETWORK_NO_SOURCE,那么您就知道所有源都加载失败了。

如果您在那时添加了另一个源(通过将新的 <source> 元素作为媒体元素的子元素插入),Gecko 将尝试加载指定的资源。

当无法解码任何源时显示备用内容

另一种方法是在最后一个源元素上添加错误处理程序,以便在当前浏览器中无法解码任何源时显示视频的备用内容。然后,您可以将视频替换为其备用内容

html
<video controls>
  <source src="dynamicsearch.mp4" type="video/mp4"></source>
  <a href="dynamicsearch.mp4">
    <img src="dynamicsearch.jpg" alt="Dynamic app search in Firefox OS">
  </a>
  <p>Click image to play a video demo of dynamic app search</p>
</video>
js
const v = document.querySelector("video");
const sources = v.querySelectorAll("source");
const lastsource = sources[sources.length - 1];
lastsource.addEventListener(
  "error",
  (ev) => {
    const d = document.createElement("div");
    d.innerHTML = v.innerHTML;
    v.parentNode.replaceChild(d, v);
  },
  false,
);

音频/视频 JavaScript 库

存在许多音频和视频 JavaScript 库。最流行的库允许您在所有浏览器中选择一致的播放器设计,并为不支持音频和视频的浏览器提供备用方案。备用方案历史上使用现在已过时的插件(如 Adobe Flash 或 Microsoft Silverlight 插件)在不支持的浏览器中提供媒体播放器,尽管这些插件在现代计算机上不再受支持。其他功能(如字幕的 <track> 元素)也可以通过媒体库提供。

仅音频

仅视频

  • flowplayer: 免费,带有 flowplayer 徽标水印。开源(GPL 许可。)
  • JWPlayer: 需要注册才能下载。开源版(知识共享许可。)
  • SublimeVideo: 需要注册。基于表单的设置,带有指向 CDN 托管库的域特定链接。
  • Video.js: 免费开源(Apache 2 许可。)

音频和视频

网页音频 API

基本教程

创建跨浏览器视频播放器

使用 <video> 元素创建基本跨浏览器视频播放器的指南。

视频播放器样式基础知识

在上一篇文章中,我们已经使用跨浏览器视频播放器,本文将介绍如何为播放器提供一些基本的响应式样式。

跨浏览器音频基础知识

本文提供创建跨浏览器 HTML 音频播放器的基本指南,并解释了所有相关属性、特性和事件,以及使用媒体 API 创建自定义控件的快速指南。

媒体缓冲、查找和时间范围

有时,了解 <audio><video> 下载了多少内容或可以无延迟播放非常有用 - 音频或视频播放器的缓冲进度条就是一个很好的例子。本文讨论了如何使用 TimeRanges 和媒体 API 的其他功能构建缓冲/搜索条。

HTML playbackRate 解释

playbackRate 属性允许我们更改播放网页音频或视频的速度或速率。本文对此进行了详细解释。

使用 Web Audio API

解释了使用 Web Audio API 抓取、操作和回放音频源的基本知识。

流媒体教程

实时流式传输网页音频和视频

实时流式传输技术通常用于转播体育赛事、音乐会以及更普遍的直播的电视和广播节目。实时流式传输通常简称为流式传输,它是将媒体“实时”传输到计算机和设备的过程。这是一个相当复杂且新兴的主题,涉及很多变量,因此在本篇文章中,我们将向您介绍这个主题,并告诉您如何开始。

设置自适应流媒体源

假设您想在服务器上设置一个自适应流媒体源,以便在 HTML 媒体元素中使用。您将如何做到这一点?本文解释了如何做到这一点,并介绍了两种最常见的格式:MPEG-DASH 和 HLS(HTTP 实时流)。

适用于 HTML 5 视频的 DASH 自适应流

详细介绍了如何使用 DASH 和 WebM 设置自适应流式传输。

高级教程

将字幕和旁白添加到 HTML 视频

本文解释了如何使用 Web_Video_Text_Tracks_Format<track> 元素为 HTML <video> 添加字幕和旁白。

Web Audio API 跨浏览器支持

编写跨浏览器 Web Audio API 代码的指南。

使用 MediaRecorder API 简易音频捕获

解释了使用 MediaStream Recording API 直接录制媒体流的基本知识。

注意: Firefox OS 1.3 及以上版本支持用于流式视频传输的 RTSP 协议。对于旧版本,可以使用 <video> 以及适合 Gecko 的格式(如 WebM)来提供备用内容作为解决方案。这方面的信息将在合适的时间发布。

参考资料