整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

前端必须理解知识点—HTML5音视频处理

天小编将分享前端开发中必学的知识点,HTML5中关于音视频处理

视频处理

基本内容:目前国内的视频网站 - Flash技术,HTML5的视频处理首先替换Flash技术,支持的视频格式有:

1.MP4 - .mp4 目前比较主流的视频格式。

2.OGG - .ogv 手机端的视频格式。

3.WebM - 目前唯一一个支持超高清视频格式,该视频格式出自Goggle公司。

问: 如何处理视频?

答:<video>元素 - 引入单个格式视频文件,它由自己的属性组成。 src属性 - 指定视频文件的地址, width属性 - 设置视频宽度, height属性 - 设置视频高度。语法规范:<video src="视频文件路径" width=“100px”>

!!需要注意的是:视频的宽高比不会改变, 在video元素内定义不支持的提示内容。

如果要想在<video>元素引入多个格式视频文件,那么就使用<source/>,使用这种方式能够实现各个浏览器的兼容性,语法规范:

<video>

<source src="视频文件路径1"/>

<source src="视频文件路径2"/>

<source src="视频文件路径3"/>

</video>

  • <video>元素的属性

autoplay属性 - 自动播放

controls属性 - 提供控制面板

loop属性 - 循环播放

poster属性 - 播放之前显示一张图片

preload属性 - 预加载(视频)

none - 不加载

auto - (默认值)自动(尽快加载完毕)

metadata - 只加载除视频之外的信息(宽和高)

  • video的高级用法 方法

play() - 播放视频

pause() - 暂停视频

load() - 加载视频

canPlayType() - 判断是否支持该格式

  • 事件

play - 播放视频时触发

pause - 暂停视频时触发

ended - 结束播放时触发

error - 播放错误时触发

canplay - 可播放时触发(不考虑整体)

canplaythrough - 整体播放顺利时触发

progress - 下载进度

  • 属性

paused - 判断视频当前是否暂停,如果暂停状态,返回true

ended - 判断视频当前是否结束播放,如果结束播放,返回true

duration - 当前视频的总时长

currentTime - 获取或设置当前视频播放的位置

音频处理

基本内容:目前HTML页面实现音频处理,将Windows Media Player播放器,内置页面中,使用Flash技术实现音频处理,HTML5实现音频处理支持的音频格式有:

1.mp3 - 感谢百度(MP3)

2.ogg

3.wav

问: 如何使用音频?

答: audio元素 - 引入一种音频格式。

  • <audio>元素的属性

src属性 - 引入音频文件,作用 - 实现页面背景音乐播放

audio元素 - 引入多种音频格式

source元素

autoplay - 自动播放

controls - 提供控制面板

loop - 循环播放

preload - 预加载

audio的高级用法

  • 事件

play - 播放音频时触发

  • 方法

play() - 播放音频

pause() - 暂停音频

  • 属性

paused - true,表示暂停状态

!! 需要特别注意,IE 8及之前的版本都不支持

H5 视频兼容性处理总结:跨平台视频播放解决方案

**引言:H5视频的重要性及挑战**

随着HTML5标准的发展和完善, `<video>` 标签已经成为现代Web开发中实现内嵌视频播放的重要手段。然而,不同浏览器和设备对HTML5视频的支持程度存在差异,这就要求开发者掌握一套行之有效的视频兼容性处理策略,确保视频在多种环境下流畅播放。本文将深入探讨H5视频兼容性的关键问题,并分享实战经验与代码示例。

---

### **一、视频编码格式与容器的选择**

**标题:了解MIME类型与视频格式兼容性**

为了保证视频在所有浏览器中都能正确播放,你需要考虑视频编码格式(如H.264、VP8/VP9)以及封装容器(MP4、WebM、Ogg)的兼容性。

```html

<video width="320" height="240" controls>

<!-- MP4 for Safari, IE, and old Firefox versions -->

<source src="movie.mp4" type="video/mp4">

<!-- WebM for most modern browsers -->

<source src="movie.webm" type="video/webm">

<!-- Ogg for older Firefox versions -->

<source src="movie.ogg" type="video/ogg">

<!-- Fallback content for browsers that don't support the video tag -->

<p>您的浏览器不支持内嵌视频标签,请升级或更换浏览器。</p>

</video>

```

在上述代码中,我们按照浏览器对视频格式的支持优先级,依次提供了MP4、WebM和Ogg格式的视频源文件。

---

### **二、自动检测与适配**

**标题:JavaScript辅助实现智能切换**

通过JavaScript动态检测浏览器对不同视频格式的支持情况,可以自动调整播放源。

```javascript

var videoElement = document.querySelector('video');

var sources = [

{src: 'movie.mp4', type: 'video/mp4'},

{src: 'movie.webm', type: 'video/webm'},

{src: 'movie.ogg', type: 'video/ogg'}

];

sources.forEach(function(source) {

var sourceElement = document.createElement('source');

sourceElement.src = source.src;

sourceElement.type = source.type;

videoElement.appendChild(sourceElement);

});

// 检测是否能播放第一个源,若不能则移除并尝试下一个

function tryNextSource(video) {

if (video.paused && video.error) {

var nextSource = video.getElementsByTagName('source')[0];

if (nextSource) {

video.removeChild(nextSource);

tryNextSource(video);

}

}

}

videoElement.addEventListener('error', function() {

tryNextSource(this);

}, true);

// 开始播放视频

videoElement.load();

videoElement.play();

```

这段代码会在遇到无法播放的视频源时,自动切换至下一个可用的源。

---

### **三、响应式设计与全屏控制**

**标题:适应不同屏幕尺寸与设备特性**

针对移动端设备和桌面端的不同需求,视频元素应当具有响应式布局,并且提供全屏播放的功能。

```html

<video width="100%" height="auto" playsinline controls>

<!-- Video sources... -->

</video>

<script>

// 全屏控制

var video = document.querySelector('video');

if (video.requestFullscreen) {

video.requestFullscreen();

} else if (video.mozRequestFullScreen) { /* Firefox */

video.mozRequestFullScreen();

} else if (video.webkitRequestFullscreen) { /* Chrome, Safari & Opera */

video.webkitRequestFullscreen();

}

</script>

```

这里通过CSS设置宽度为100%,高度自适应以实现响应式布局,并利用浏览器的Fullscreen API来控制视频全屏播放。

---

### **四、视频加载优化与错误处理**

**标题:提高加载速度与用户体验**

对于大体积视频,可采用预加载或缓冲技术改善用户体验。

```html

<video preload="auto" poster="thumbnail.jpg" controls>

<!-- Video sources... -->

</video>

<script>

// 监听视频加载事件

video.addEventListener('loadedmetadata', function() {

console.log('视频元数据已加载,可以获取时长等信息');

});

video.addEventListener('canplay', function() {

console.log('视频可以开始播放,但可能需要缓冲');

});

video.addEventListener('canplaythrough', function() {

console.log('视频可以流畅播放,无需额外缓冲');

});

// 错误处理

video.addEventListener('error', function(event) {

console.error('视频加载失败:', event.target.error.code);

});

</script>

```

通过设置preload属性为"auto"可提前加载视频资源,同时监听不同的视频加载状态事件,以便更好地处理加载错误和提升用户体验。

---

**结语:**

通过对H5视频兼容性处理的深入探讨,我们已了解了视频编码格式选择、智能切换源、响应式设计、全屏控制以及加载优化等方面的关键技术。在实践中灵活运用这些策略,将有助于构建出更加稳定、高性能、跨平台的Web视频播放环境。持续关注浏览器发展趋势,及时更新视频处理方案,方能在Web前端开发领域始终保持领先优势。

定义原生播放器控制器功能限制下载

html5 播放器默认是可以下载视频的,在默认的控制器(给 video 标签添加 controls 属性开启)上会有下载菜单, 即使不使用默认提示的控制器,右键弹出的上下文菜单中也会有保存视频的选项。



通过 controlslist 属性可以设置浏览器提供的控制器,不让下载菜单显示出来。controlslist 还可以设置不显示全屏等功能同,但是浏览器 支持较差,尤其是移动端浏览器。

<video src="test.mp4" playsinline autoplay="false" controls controlslist="nodownload"></video>

将 controlslist 的值设置为 nodownload ,就不会出现下载菜单了,不过 PC 上点击右键的上下文菜单的保存视频选项仍然有用,还是很容易被下载。

如果是通过自定义样式来控制播放暂时等操作的控制条,还可以将 video 禁右键或者蒙上一层 div 来阻止弹出上下文菜单,防止下载。

利用 Media Source Extensions (MSE) 实现加密防下载

虽然通过 controlslist 可以防止下载,但是有些浏览器不支持,很多移动端的浏览器会直接接管播放器。 如果用户懂一点技术,捕获视频文件的链接,就可以直接打开链接进行下载了。 我们可以利用 Media Source Extensions API 来给文件做加密,这套技术本来是用于扩展的,通过扩展可以兼容更多 的视频格式,可以认为是前端的一套自定义转码的接口,将文件实时转码成浏览器支持的格式。

服务器端做好视频的加密,将原视频文件通过对称性加密生成一个加密新文件,客户端将加密的新文件加载后进行解密, 然后将解密后的原文件内容通过 MediaSource 推送,完成视频的播放。

<canvas height="240" width="320" id="player" onclick="playOrPause()"></canvas>


const video = document.getElementById('videoId')
// 视频编码译码器,使用工具 mp4info 可以查看
const mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'

const mediaSource = new MediaSource()
video.src = URL.createObjectURL(mediaSource)
mediaSource.addEventListener('sourceopen', e => {
  const sourceBuffer = mediaSource.addSourceBuffer(mimeCodec)
  // 请求加密文件,然后解密添加到 sourceBuffer,也可以将文件裁切成多个部分,分多次加载
  fetch('./chunk')
    .then(async resp => {
      const blob = await resp.blob()
      const buf = await blob.arrayBuffer()
      sourceBuffer.addEventListener('updateend', () => {
        // 如果是多个文件块,可以在判定已经添加完所有块后结束(一般会搞个块列表做比对的)
        mediaSource.endOfStream()
      })
      // decode 是自定义的解码函数,将请求到的加密文件 chunk 内容解密成为真正的 mp4 文件
      // ,要与前面的 mimeCodec 对应,否则会有错误
      // 这个示例省略了很多错误处理,要处理错误需要对 mediaSource 和 sourceBuffer 做 error 事件处理
      sourceBuffer.appendBuffer(decode(buf))
      console.log('appendBuffer after')
    })
    .catch(console.error)
})

这样处理后,通过控制台 network 查看到的是加密文件的请求地址,拿到后也不能播放,查看 video 标签源地址是 生成的临时地址,也无法直接打开。并且,通过 Media Source Extensions API 还可以实现视频分块做按需加载。 其实 video 标签播放视频也会自动按需请求内容(仅部分浏览器),需要服务器做好对 Range 消息头的支持,根据参数来返回部分文件内容。 不过 Media Source Extensions API 的兼容性不是很好,ie 和 safari 都是不支持的, 新版本 mac 上的 safari 不知道是否能支持。经过测试,小部分移动端浏览器也不支持,无法显示出视频,大部分移动端浏览都可以支持的很好。 有些网站的播放器做了兼容,对于不支持 MSE 的浏览器仍然使用 video 标签播放原 mp4 文件。

基于 canvas 实现播放器

基于 canvas 也是一种方案,好处是不会被浏览器识别成视频,也就不会被接管。很多不太规范的移动端浏览器 都是直接接管视频播放器,自定义的播放器样式完全没用,不会被显示出来,使用 canvas 就可以解决这个问题。


const canvas = document.getElementById('player')
/** @type {CanvasRenderingContext2D} */
const ctx = canvas.getContext('2d')

const video = document.createElement('video')
video.addEventListener('canplay', e => {
  // 渲染封面
  this.renderCover()
})
fetch('./test.mp4')
  .then(async resp => {
    const blob = await resp.blob()
    video.src = URL.createObjectURL(blob)
  })
  .catch(console.error)

function playOrPause() {
  if (video.ended) {
    return
  }
  if (video.paused) {
    video.play()
    startRender()
  } else {
    video.pause()
  }
}

function startRender() {
  requestAnimationFrame(() => {
    renderVideo()
    if (!video.paused && !video.ended) {
      startRender()
    }
  })
}

function renderCover() {
  ctx.clearRect(0, 0, 320, 240)
  ctx.fillStyle = '#000000'
  ctx.fillRect(0, 0, 320, 240)
  ctx.font = '40px Arial'
  ctx.fillStyle = '#ffffff'
  const text = '点击播放'
  const m = ctx.measureText(text)
  ctx.fillText(text, 320 / 2 - m.width / 2, 240 / 2 + 40 / 2)
}

function renderVideo() {
  ctx.clearRect(0, 0, 320, 240)
  ctx.drawImage(video, 0, 0, 320, 240)
  if (video.paused) {
    ctx.font = '40px Arial'
    ctx.fillStyle = '#ffffff'
    const text = '已暂停'
    const m = ctx.measureText(text)
    ctx.fillText(text, 320 / 2 - m.width / 2, 240 / 2 + 40 / 2)
  }
}

以上仅仅是非常简单的 demo,这个方案真要完善工作量还是挺大的,除操作条和字幕功能外,视频全屏还需要做一定的重新渲染处理, 有些浏览器还不支持全屏 API (requestFullscreen),导致没有办法将视频全屏展示。 即便如此,也无法保证百分百不能被下载, 有些浏览器还有媒体嗅探功能,当请求了媒体文件后,就会被检测到,提示用户检测到有媒体文件, 询问用户是否要下载。


经过我对某个移动端浏览器的测试,改 content-type 和后缀名也不行,只要请求的是视频文件就会被检测到。 只有把文件加密,请求的是加密文件,不是真正的视频文件,这样就不能被检测到了,然后客户端解密后再播放。

实测这个方案兼容性也不是很好,部分移动端浏览器会渲染不出来视频内容,有些还会出现卡顿和图像错乱。不过微信内置 以及火狐等一些较为先进的移动端浏览器支持的都比较好。不过,使用了 canvas 方案就没有一些原生功能的支持的,如 小窗播放(画中画模式)。

总结

经过我的测试,对 MSE 和 canvas 方案无法支持的浏览器,恰恰是一些以下载视频为特色的移动端浏览器, 这些浏览器内核可能也比较旧,或者是因为修改内核导致的不兼容,不考虑这些浏览器 MSE 应该是最佳方案, 因为 MSE 可以实现按需渐近加载视频。

由于视频本身就非常耗资源,即时加密对服务器要求高,最好是先加密好。 加密必须是对称性的,能加密也能解密,通过破解前端代码掌握解密方法,仍然有办法解开视频内容。 如果视频是提前加密好再存储的,也不好去搞动态密钥。

html5 视频播放器想要下载并做好兼容是非常困难的,基本上不太可能。有些对版权保护比较严格的网站,采取了 只能使用客户端看视频的方案,体验上就差一些了。比如 cctalk 这个平台,视频作者可以设置保护,对于需要保护的 视频只能通过客户端观看,其它的视频仍然可以网页上直接播放。