背景
最近在开发一个涉及音视频流的项目,视频需要做到在浏览器端能够自动播放,无需让用户点击开始播放,这里碰到了许多问题,记录一下。先说结论
相对所有的浏览器范围来说,肯定是存在无法自动播放音视频的情况的,需要有一个兜底方案,就是让用户手动点击播放。大部分浏览器都是在video标签设置静音的时候(muted)才能支持自动播放的,小部分浏览器支持携带声音自动播放(微信浏览器,360浏览器,safari浏览器),如果你的代码是运行在native APP上的WebView应用的情况下,可以让APP的同事处理这个声音的问题
相关代码示例
相关html代码
<video
id="video"
autoplay
muted
playsinline
preload="auto"
webkit-playsinline
x-webkit-airplay="allow"
x5-playsinline
x5-video-player-type="h5"
x5-video-orientation="portraint"
poster="xxx"
></video>
相关js代码,这里的video 被我包装成了一个SDK类了,这里可以把videoInstance 看成一个video的实例,我把相关播放代码放在这里
play(stream?: MediaStream) {
if (stream) {
this.videoInstance.srcObject = stream;
}
if (!this.videoInstance.paused) return Promise.resolve();
return new Promise<void>((resolve, reject) => {
this.videoInstance
.play()
.then(() => {
this.isPlay = true;
this.emit('Play');
resolve();
})
.catch(() => {
this.videoInstance.muted = true;
this.videoInstance
.play()
.then(() => {
this.isPlay = true;
this.emit('Play');
})
.catch(error => {
reject(error);
});
});
});
}
这里主要做了三步处理,第一步的play方法如果可以走到then的状态,那么就说明自动播放成功了,如果走到了catch方法就走到了第二步处理,我们假设大部分情况是不支持携带声音自动播放,将示例的声音设置为静音,然后尝试再尝试自动播放,如果还是不成功,那我们走到第三步的兜底方案。
坑1: 微信浏览器自动播放策略如何支持携带声音
开发过程中,发现不同设备,不同的系统在微信浏览器下自动播放表现不尽相同,安卓可以静音自动播放,不过的苹果手机,或者说不同的ios的有些支持,有些不支持。然后看了下有些已经商用的应用可以做到携带声音自动播放。搜索了一下,发现是微信JSSDK做的支持,实际就是微信的native提供的桥接能力。具体怎么申请微信JSSDK的权限,要看下微信的文档,这里不扩展:微信JS-SDK接入文档
这里贴一下处理代码:
// 第一步,先初始化
wx.config({
debug: false,
...res.info, // 服务端的信息,这里直接复写
nonceStr: res.info.noncestr, // 服务端把这个字段写成小写了,手动改一下
jsApiList: ['closeWindow', 'checkJsApi', 'scanQRCode', 'getLocation']
});
// 第二步,执行自动播放
wx.ready(() => {
handleWxAutoPlay(videoInstance!.videoInstance)
.then(() => {
state.videoState = VideoState.Playing;
})
.catch(err => {
console.error('播放错误', err.message);
});
if (!store.muted && videoInstance) {
videoInstance.videoInstance.src = PreVideo;
videoInstance.allowSoundPlay();
}
});
/** 微信的Native能力, 只需要wx.ready IOS 就可以自动播放 */
export function handleWxAutoPlay(video: HTMLVideoElement) {
if (!isiOS() || !video.paused) return Promise.resolve();
console.log('微信dsbridge尝试执行播放', video);
return new Promise<void>((resolve, reject) => {
video
.play()
.then(() => {
resolve();
})
.catch(err => {
reject(err);
});
});
}
有些上下文的代码没有搬过来,直接搬过去应该跑不了,但是思路是这个思路