video autoplay 自动播放策略

370 阅读3分钟

背景

最近在开发一个涉及音视频流的项目,视频需要做到在浏览器端能够自动播放,无需让用户点击开始播放,这里碰到了许多问题,记录一下。先说结论

相对所有的浏览器范围来说,肯定是存在无法自动播放音视频的情况的,需要有一个兜底方案,就是让用户手动点击播放。大部分浏览器都是在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);
            });
    });
}
        

有些上下文的代码没有搬过来,直接搬过去应该跑不了,但是思路是这个思路