You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
exportdefaultclassPlaySoundWithAudioContext{constructor(){if(PlaySoundWithAudioContext.isSupportAudioContext()){this.duration=0;this.currentTime=0;this.nextTime=0;this.pending=[];this.mutex=false;this.audioContext=new(window.AudioContext||window.webkitAudioContext)();}}staticisSupportAudioContext(){returnwindow.AudioContext||window.webkitAudioContext;}play(buffer){varsource=this.audioContext.createBufferSource();source.buffer=buffer;source.connect(this.audioContext.destination);source.start(this.nextTime);this.nextTime+=source.buffer.duration;}addChunks(buffer){this.pending.push(buffer);letcustomer=()=>{if(!this.pending.length)return;letbuffer=this.pending.shift();this.audioContext.decodeAudioData(buffer,buffer=>{this.play(buffer);console.log(buffer)if(this.pending.length){customer()}},(err)=>{console.log('decode audio data error',err);});}if(!this.mutex){this.mutex=true;customer()}}clearAll(){this.duration=0;this.currentTime=0;this.nextTime=0;}}
谈起音视频,前端能做些什么
@(音视频)[Audio|Video|MSE]
音视频随着互联网的发展,对音视频的需求越来越多,然而音视频无乱是播放还是编解码,封装对性能要求都比较高,那现阶段的前端再音视频领域都能做些什么呢。
[TOC]
音频或视频的播放
html5 audio
提起音视频的播放,我萌首先想到的是HTMLMediaElement,
video
播放视频,audio
播放音频。举个栗子:controls
指定浏览器渲染成html5audio
.autoplay
属性告诉浏览器,当加载完的时候,自动播放.loop
属性循环播放.preload
当渲染到audio元素时,便加载音频文件.autoplay
和preload
属性,即不会自动加载音频文件,只有通过一些事件触发,比如touch
、click
事件等触发加载然后播放.AudioContext
虽然使用html5的
audio
可以播放音频,但是正如你看到存在很多问题,同时我萌不能对音频的播放进行很好的控制,比如说从网络中获取到音频二进制数据,有的时候我萌想顺序播放多段音频,对于使用audio元素也是力不从心,处理起来并不优雅。举个栗子:
监听
audio
元素的onended
事件,顺序播放。为了更好的控制音频播放,我萌需要AudioContext.
可能理解起来比较晦涩,简单的来说,AudioContext 像是一个工厂,对于一个音频的播放,从音源到声音控制,到链接播放硬件的实现播放,都是由各个模块负责处理,通过connect 实现流程的控制。

现在我萌便能实现音频的播放控制,比如从网络中获取。利用AJAX中获取 arraybuffer类型数据,通过解码,然后把音频的二进制数据传给AudioContext创建的BufferSourceNode,最后通过链接
destination
模块实现音频的播放。AJAX调用
使用Ajax播放对于小段的音频文件还行,但是一大段音频文件来说,等到下载完成才播放,不太现实,能否一边下载一边播放呢。这里就要利用 fetch 实现加载
stream
流。简单的来说,就是
fetch
的response
返回一个readableStream接口,通过从中读取流,不断的喂给audioContext 实现播放,测试发现移动端不能顺利实现播放,pc端浏览器可以。PCM audio
实现audioContext播放时,我萌需要解码,利用
decodeAudioData
api实现解码,我萌都知道,一般音频都要压缩成mp3,aac这样的编码格式,我萌需要先解码成PCM数据才能播放,那PCM 又是什么呢?我萌都知道,声音都是由物体振动产生,但是这样的声波无法被计算机存储计算,我萌需要使用某种方式去刻画声音,于是乎便有了PCM格式的数据,表示麦克风采集声音的频率,采集的位数以及声道数,立体声还是单声道。Media Source Extensions
Media Source Extensions可以动态的给

Audio
和Video
创建stream流,实现播放,简单的来说,可以很好的播放进行控制,比如再播放的时候实现 seek 功能什么的,也可以在前端对某种格式进行转换进行播放,并不是支持所有的格式的。通过将数据append进
SourceBuffer
中,MSE把这些数据存进缓冲区,解码实现播放。这里简单的举个使用MSE播放audio
的栗子:HTML5 播放器
谈起html5播放器,你可能知道bilibili的flv.js,它便是依赖Media Source Extensions将flv编码格式的视频转包装成mp4格式,然后实现播放。

从流程图中可以看到,
IOController
实现对视频流的加载,这里支持fetch
的 stream能力,WebSocket
等,将得到的视频流,这里指的是flv格式的视频流,将其转封装成MP4格式,最后将MP4格式的数据通过appendBuffer将数据喂给MSE,实现播放。未来
上面谈到的都是视频的播放,你也看到,即使播放都存在很多限制,MSE的浏览器支持还不多,那在视频的编码解码这些要求性能很高的领域,前端能否做一些事情呢?

前端性能不高有很多原因,在浏览器这样的沙盒环境下,同时js这种动态语言,性能不高,所以有大佬提出把c++编译成js ,然后提高性能,或许你已经知道我要说的是什么了,它就是ASM.js,它是js的一种严格子集。我萌可以考虑将一些视频编码库编译成js去运行提高性能,其中就不得不提到的FFmpeg,可以考虑到将其编译成asm,然后对视频进行编解码。
写在最后
我萌可以看到,前端对音视频的处理上由于诸多原因,可谓如履薄冰,但是在视频播放上,随着浏览器的支持,还是可以有所作为的。
The text was updated successfully, but these errors were encountered: