整合营销服务商

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

免费咨询热线:

html5 视频播放防下载的几种方案盘点

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

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 这个平台,视频作者可以设置保护,对于需要保护的 视频只能通过客户端观看,其它的视频仍然可以网页上直接播放。

希望可以通过这篇文章,能够给你得到帮助。(感谢一键三连)

学习深入理解HTML5audiovideo

HTML5视频概述

HTML5播放一个视频,很简单,只需要一行代码:

<video src="resources/dadaqianduan.mp4" autoplay></video>

了解多媒体术语

了解视频文件格式:

Audio Video InterLeaved .avi

Flash Video .flv

MPEG-4 .mp4

Matroska .mkv

Ogg .ogv

音频和视频编解码器

编解码器可以理解为一些算法代码,用于处理视频,音频或者其元数据的编码格式。对音频或视频文件进行编码,可使得文件大大缩小,便于在因特网上传输。

音频编解码器:

MP3,使用ACC音频

Wav,使用Wav音频

Ogg,使用OggVorbis音频

视频编解码器:

MP4,使用H.264视频,AAC音频

WebM,使用VP8视频,OggVorbis音频

Ogg,使用Theora视频,OggVorbis音频

多媒体文件格式

audio元素支持的音频格式MP3,Wav,Oggvideo元素支持的格式MP4,WebM,Ogg

  • audio元素是专门用于在网页中播放网络音频的
  • video元素是专门用于在网页中播放视频的

HTML5audiovideo元素提供的接口包含了一系列的属性,方法和事件,这些接口可以帮助开发完成对音频和视频的操作。

那么如何在页面中添加音频和视频呢?

音频

<audio src="resources/audio.mp3">
</audio>

视频

<video src="resources/video.mp4" width="600" height="200">
</video>

使用source元素

因为各种浏览器对音频和视频的编解码器的支持不一样,为了能够在各种浏览器中正常使用,可以提供多个源文件。

<audio src="resources/audio.mp3">
 <source src="song.ogg" type="audio/ogg">
 <source src="song.mp3" type="audio/mpeg">
</audio>
<video src="resources/video.mp4" width="600" height="200" controls>
 <source src="movie.ogg" type="video/ogg codes=`theora,vorbis` ">
 <source src="movie.mp4" type="video/mp4">
</video>

使用source元素替代了audiovideo的标签属性src

  1. src属性用于指定媒体文件的url地址
  2. type属性用于指定媒体文件的类型,属性值为媒体文件的MIME类型,该属性值还可以通过codes参数指定编码格式

audiovideo特性和属性

元素的标签特性

  1. src,源文件特性,用于指定媒体文件的url地址
  2. autoplay,自动播放特性,表示媒体文件加载后自动播放。
<video src="resources/video.mp4" autoplay></video>
  1. controls,控制条特性,表示为视频或音频添加自带的播放控制条。
<video src="resources/video.mp4" controls></video>
  1. loop,循环特性,表示音频或视频循环播放。
<video src="resources/video.mp4" controls loop></video>
  1. preload,预加载特性,表示页面加载完成后如何加载视频数据。
  • none表示不进行预加载
  • metadata表示只加载媒体文件的元数据
  • auto表示加载全部视频或音频,默认值为auto
<video src="resources/video.mp4" controls preload="auto"></video>
  1. postervideo元素独有的特性,替代内容属性,用于指定一副替代图片的url地址,当视频不可以用时,会显示该替代图片。
<video src="resources/video.mp4" controls poster="images/none.jpg"</video>
  1. widthheightvideo元素独有的特性,用于指定视频的宽度和高度
<video src="resources/video.mp4" width="600" height="200" controls></video>

接口属性

  1. currentSrc,只读,获取当前正在播放或已加载的媒体文件的url地址
  2. videoWidth,只读,video元素特有属性,获取视频原始的宽度
  3. videoHeight,只读,video元素特有属性,获取视频原始的高度
  4. currentTime,获取或设置当前媒体播放位置的时间点
  5. startTime,只读,获取当前媒体播放的开始时间
  6. duration,只读,获取整个媒体文件的播放时长
  7. volume,获取或设置媒体文件播放时的音量,取值范围在0.00.1之间
  8. muted,获取或设置媒体文件播放时是否静音。true表示静音,false表示消除静音
  9. ended,只读,如果媒体文件已经播放完毕则返回true,否则返回false
  10. error,只读,读取媒体文件的错误代码
  11. played,只读,获取已播放媒体的TimesRanges对象,该对象内容包括已播放部分的开始时间和结束时间。
  12. paused,只读,如果媒体文件当前是暂停或未播放则返回true,否则返回false
  13. seeking,只读,获取浏览器是否正在请求媒体数据
  14. seekable,只读,获取媒体资源已请求的TimesRanges对象,该对象内容包括已请求部分的开始时间和结束时间
  15. networkState,只读,获取媒体资源的加载状态
  16. buffered,只读,获取本地缓存的媒体数据的TimesRanges对象
  17. readyState,只读,获取当前媒体播放的就绪状态
  18. playbackRate,获取或设置媒体当前的播放速率
  19. defaultPlaybackRate,获取或设置媒体默认的播放速率

视频播放的快进

<!DOCTYPEHTML>
<html>
<head>
<meta charset="utf-8">
<title>视频播放时的快进</title>
<script type="text/javascript">
function Forward() {
 var el = document.getElementById("myPlayer");
 var time = el.currentTime;
 el.currentTime = time+300;
}
</script>
</head>
<body>
<video id="myPlayer" src="resources/video.mp4" width="600" height="200" controls>
</video>
<br/>
<input type="button" value="快进" onclick="Forward()"/>
</body>
</html>

audiovideo接口方法

接口方法

  1. load(),加载媒体文件,为播放做准备。
  2. play(),播放媒体文件。
  3. pause(),暂停播放媒体文件。
  4. canPlayType(),测试浏览器是否支持指定的媒体类型。

代码示例使用接口:

<!DOCTYPEHTML>
<html>
<head>
<meta charset="utf-8">
<title>播放与暂停</title>
<script type="text/javascript">
var videoEl = null;
function Play() {
 videoEl.play();
}
function Pause() {
 videoEl.pause();
}
window.onload = function(){
 videoEl = document..getElementById("myPlayer");
}
</script>
</head>
<body>
<video id="myPlayer" width="600">
 <source src="resources/video.mp4" type="video/mp4">
</video><br>
<input type="button" value="播放" onclick="Play()"/>
<input type="button" value="暂停" onclick="Pause()"/>
</body>
</html>

audiovideo事件

捕获事件的方式

捕获事件有两种方法:一种是添加事件句柄,一种是监听。

<video id="myPlayer" src="resources/video.mp4" width="500" onplay="video_playing()">
</video>

// 监听方式
var videoEl = document.getElementById("myPlayer");
videoEl.addEventListener("play",video_playing);

接口事件

  1. play,当执行方法play()时触发
  2. playing,正在播放时触发
  3. pause,当执行了方法pause()时触发
  4. timeupdate,当播放位置被改变时触发
  5. ended,当播放结束后停止播放时触发
  6. waiting,在等待加载下一帧时触发
  7. ratechange,在当前播放速率改变时触发
  8. volumechange,在音量改变时触发
  9. canplay,以当前播放速率需要缓冲时触发
  10. canplaythrough,以当前播放速率不需要缓冲时触发
  11. durationchange,当播放时长改变时触发
  12. loadstart,当浏览器开始在网上寻找数据时触发
  13. progress,当浏览器正在获取媒体文件时触发
  14. suspend,当浏览器暂停获取媒体文件,且文件获取并不是正常结束时触发
  15. abort,当终止获取媒体数据时触发
  16. error,在获取媒体过程中出错时触发
  17. emptied,当所在网络变为初始化状态时触发
  18. stalled,在浏览器尝试获取媒体数据失败时触发
  19. seeking,在浏览器正在请求数据时触发
  20. seeded,在浏览器停止请求数据时触发

定义全局的视频对象

代码如下:

<script type="text/javascript">
// 定义全局视频对象
var videoEl = null;
// 网页加载完毕后,读取视频对象
window.addEventListener("load", function() {
 videoEl = document.getElementById("myPlayer")
});
</script>

添加进度显示功能

代码如下:

<script type="text/javascript">
function Progress() {
 var el = document.getElementById("progress");
 el.style.width = (videoEl.currentTime/videoEl.duration)*720 + "px"
 document.getElementById("info").innerHTML = s2time(videoEl.currentTime) + "/" + s2time(videoEl.duration);
}

function s2time(s) {
 var m = parseFloat(s/60).toFixed(0);
 s = parseFloat(s%60).toFixed(0);
 return (m<10?"0"+m:m)+":"+(s<10?"0"+s:s);
}
window.addEventListener("load",function(){videoEl.addEventListener("timeupdate",Progress)});
window.addEventListener("load",Progress)

添加静音和调节音量的功能

消除静音videoEl.muted=false;静音效果videoEl.muted=truevideoEl.volume=e.value;修改音量的值。

添加慢进和快进功能

天小编将分享前端开发中必学的知识点,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及之前的版本都不支持