什么是Web多媒体技术
随着近几年短视频的流行,包括各大直播,音视频的技术学习又被提上新的热度。web场景的音视频技术也得到了新的应用和突破
Web前端
交互体验、前端工程化、跨端能力…
数字多媒体
音视频原理、封装容器、编解码算法…
- 点播 按照客户的需求,返回一段固定时长的视频,包括短视频(抖音),中视频(B站),长视频(电视剧、电影)
- 直播 将用户的画面和声音推送到客户端,供其他用户观看浏览
- 图片 图片下发、下载的网络链路监控诊断,图片格式的兼容性调整,图片的动态编辑
- 实时通信 高质量低延迟的音视频通信能力,视频会议,在线教育,互动娱乐
- 云游戏 运行在服务端,降低客户端的要求,对音视频的低延迟要求非常高
- 视频编辑 对视频的解码和合成
音视频基础知识
我们平时说的分辨率就是像素点,每个像素点里面又有3个子像素点,分别对应着RGB三个颜色通道
视频是由一系列连续的图像组成的,按照一定时间连续播放,速率就是我们所说的帧率,例如24帧就是每秒播放24张画面
假设8bit表示一个子像素,清晰度1280*720,帧率25fps,时长60s
未压缩视频大小 = 8bit * 3 * 1280 * 720 * 25 * 60 = 3.9G
经过H264压缩后视频大小 = 11MB
压缩比360:1
所以我们在视频生产之后需要对视频进行压缩调整,使得我们在传输和下载的过程中节省流量
视频编码:
未压缩视频—->编码器—->压缩后存储、传输
视频解码:
已压缩视频—->解码器—->还原出初始像素
假设上面左边是某个视频里面的某一帧,我们发现在蓝天部分,每一个小块的信息相似度非常高,例如左上角的四个小块,可以近似的使用一个小块的信息代替其他三个,也就是说只需要保存一个小块的信息,就能还原四个小块的信息,这样就可以节省很多容量,如果我们通过算法,把每个小块的信息冗余消除,那么需要存储的变量是非常小的。
上面说的是空间范围内的,我们现在看右边的时间范围内的,假设上下是两帧图像,那么在这两帧中,有大量的冗余信息,包括草地、足球、场地等等,那么我们可以通过算法,只记录第一帧的画面,然后在第二帧只记录与第一帧不同的信息,那么也可以达到节省存储的目的。
编码格式发展:
我们的编码技术随着需求也在不断进步,新的编码技术压缩率更高,背后的算法复杂度也更高,对我们的硬件要求也更高
H.264是在浏览器兼容性最好的,应用非常广泛
下面是谷歌公司开发的编码技术
容器封装格式:
我们将视频通过编码器进行编码之后,得到的是“裸流”,如果直接播放,只能从头播放到尾,不能进行中间操作。所以我们需要将裸流进行包装,放在固定格式的文件中,这个文件就是音视频裸流的“容器”,包括meta信息,时长、帧率、数据帧的尺寸、位置。
浏览器提供的原生多媒体能力
我们想要在浏览器播放音视频,最简单的方法就是使用video和audio元素
<!DOCTYPE html>
<html>
<body>
<video autoplay=true controls="controls" width=600 height=300>
<source src="//sf1-cdn-tos.huoshanstatic.com/obj/media-fe/xgplayer_doc_video/mp4/xgplayer-demo-720p.mp4">
</video>
<audio controls src="//sf1-cdn-tos.huoshanstatic.com/obj/media-fe/xgplayer_doc_video/music/audio.mp3">
</audio>
</body>
</html>
复制代码
作用:解码+渲染 编码格式使用的是H.264
支持视频格式:MP4、MP3
<!DOCTYPE html>
<html>
<body>
<button onclick = "palyVid()">播放视频</button>
<button onclick = "pauseVid()">暂停视频</button>
<button onclick = "loadVid()">重新加载视频</button>
<video id="vs" src="demo.mp4"></video>
<script>
const myVideo = document.getElementById("vs")
function playVid(){
myVideo.play()
}
function pauseVid(){
myVideo.pause()
}
function loadVid(){
myVideo.load()
}
</script>
</body>
</html>
复制代码
<!DOCTYPE html>
<html>
<body>
<button onclick = "getVolume()">当前播放音量</button>
<button onclick = "setVolume()">设置播放音量</button>
<button onclick = "getCurTime()">获取当前播放时间</button>
<button onclick = "setCurTime()">设置播放时间</button>
<video id="vs" src="https://juejin.cn/post/demo.mp4"></video>
<script>
const myVideo = document.getElementById("vs")
function playVid(){
alert(getVolume.play())
}
function pauseVid(){
myVideo.volume = 0.2
}
function playVid(){
alert(myVideo.currenTime)
}
function pauseVid(){
myVideo.currenTime = 5
}
</script>
</body>
</html>
复制代码
video和audio的缺点
-
不支持直接播放hls、flv等视频格式
-
视频资源的请求和加载无法通过代码控制
- 分段加载(节约流量)
- 清晰度无缝切换
- 精确预加载
主流视频网站使用video元素
上面这个demo可以看出,video元素在请求的时候,请求类型是media,代表这个请求是浏览器的媒体元素自己内部发出的
上面这个YouTube的video使用,但是src并不是直接把视频的地址赋给src,而是一个blob开头的资源链接,资源请求的类型是xhr,是web端通过js主动发出的http请求,是可以通过js代码主动进行控制的
MediaSource
扩展浏览器视频播放能力,支持视频分段加载(直接传入fmp4分片),替代flash播放器
支持播放MP4(实现流式播放)、hls、flv等
可实现视频分段加载,清晰度无缝切换、精确预加载等
上面YouTube使用的就是这种技术
let mimeCodec = "video/mp4; codecs='avc1.42E01E,mp4a.40.2'"
let mediaSource = new MediaSource()
video.src = URL.createObjectURL(mediaSouce)
mediaSource.addEventListener('sourceopen',()=>{
let mediaSource = this
let sourceBuffer = mediaSource.addSourceBuffer(mimeCodec)
fetchAB('frag_bunny.mp4',function(buf){
souceBuffer.addEventListener('updateend',function(){
video.play()
})
sourceBuffer.appendBuffer(buf)
})
})
function fetchAB(url,cb){
let xhr = new XMLHttpRequest
xhr.open('get',url)
xhr.responseType = 'arraybuffer'
xhr.onload = function(){cb(xhr.response)}
xhr.send( )
}
复制代码
上面是MP4视频文件的结构,是由一个个单元组成的,最上层是三个类型的单元组成
- ftyp 格式信息
- moov 视频源信息,meta信息,包括声轨等信息
- mdat 源数据
这上面是fMP4视频文件结构,我们发现前面两个单元跟MP4是一样的,但是后面就是一个个的段落,对音视频进行分段保存
使用mse实现MP4流式播放
先请求资源,然后H.264拿到裸流,封装成fmp4,然后放到mse里面,然后就可以播放啦
Web多媒体技术的发展和突破
加密音视频播放
我们平时看的电视剧或者电影,视频网站都会做防盗的处理,如果不做就可以直接使用检查工具查看资源。
我们在请求的时候,下发的是加密资源,下载到客户端之后再进行解密播放
自适应码率(ABR)
我们在B站看视频的时候,清晰度选择里面有一个“自动”的选项,就是在我们的网络环境变差或者播放器缓存非常高的的时候,自动切换到低码率的状态,降低视频卡顿,使用户能尽可能的进行流畅的视频观看
弹幕
弹幕使视频网站焕发了新的生机,弹幕现在基本上是每个视频网站的必备
- 无碰撞
- 交互弹幕
- 防挡人像
软解:实现Web端播放H.265格式和国产浏览器防劫持
web浏览器一般只支持H.264,但是H.265格式的压缩率比较高,所以H.265需求也是非常高,一般使用H.265就是使用webassembly技术,它支持将c语言的文件编译成js可以调用的,其实就是将c语言编译的H.265解码器,转译成js可以调用的形式,然后再浏览器中请求到资源之后,就用webassembly转译的解码器进行解码,解码的视频原始像素信息之后,使用webgl进行渲染
音频一般是AudioContext API进行解码播放,处理音视频同步问题
软解的另一个使用途径是防止国产浏览器的劫持,如下,某国产浏览器会将播放器进行替换,增加一些功能,那么我们原始的播放器的api都会被替换
劫持的原理就是检测页面的video标签,软解是webgl进行渲染,不适用video标签
网页推流
有直播需求的小伙伴知道,我们在直播的时候是需要下载OBS这个软件的,它获取到你要发送的音视频流,然后打包发送,现在只需要打开一个网页就可以完成推流,非常方便
图片解码
因为图片格式的不同,有些格式不能被浏览器渲染,这就需要工程师对图片进行解码渲染
云游戏原理和特点
云游戏就是游戏运行在远端的服务器上,然后服务器根据游戏的运行,将音视频画面推送给客户端
云游戏主要两个特点
- 无需安装、对硬件要求低
- 低延迟、强兼容性要求