浏览器audio、video相关

音频、视频常用标签属性

  • airplay
    远程播放功能
    x-webkit-airplay="true"
    airplay="allow"

  • playsinline
    webkit-playsinline="true"
    视频播放时局域播放,不脱离文档流 。
    这个属性需要嵌入网页的APP
    比如WeChat中UI的webview
    allowsInlineMediaPlayback = YES
    webview.allowsInlineMediaPlayback = YES,才能生效。

  • muted
    添加了这个属性,就可以自动播放了

muted 属性是一个 boolean(布尔) 属性。
muted 属性设置或返回音频/视频是否应该被静音(关闭声音)。
问题

为了更好的提升用户体验,浏览器厂商不希望视频自动播放,所以audio标签上的autoplay属性,在浏览器限制下,可能不好使
主要的问题有:

  1. 渐进性、向下兼容优化
    关于音频,可以在浏览器切换当前窗口显示与否时候,对音频进行处理,减少音乐对用户影响
try{
    document.addEventListener("visibilitychange", function() {
      var _visibilityState = document.visibilityState;
      if (_visibilityState === 'visible') {
        //backgroundMusic.play();
      } else {
        //backgroundMusic.pause();
      }
    });
}catch(err){ }
  1. 阻止IOS系统手机,全屏播放视频
    playsinline这个属性是ios 10中设置可以让视频在小窗内播放,也就是不是全屏播放
//video标签挂载属性
webkit-playsinline="true"
playsinline="true" 
  1. 关于video设置autoplay自动播放
  • PC浏览器不生效


    浏览器需要权限

    需要用户手动,打开浏览器权限
    建议的方案:
    通过引导用户点击,调用JS脚本来使视频播放 ( 无需上面浏览器授权 )

  • 微信浏览器环境下,可以通过WeixinJSBridgeReady事件,来自动播放
    IOS iphone plus7 可以
    安卓 小米5 可以,按照以往经验,应该是安卓机不支持的

//--html
<video 
    id="banVideo" 
    x-webkit-airplay="true" 
    webkit-playsinline="true"
    playsinline="true"
    poster="videos/video2.jpg"
    autoplay
    preload="auto"
>
    <source src="videos/video2.ogv" type="video/ogg"></source>
    <source src="videos/video2.webm" type="video/webm"></source>
    <source src="videos/video2.mp4" type="video/mp4"></source>
    <p>Video is not visible, most likely your browser does not support HTML5 video</p>
</video>

//----js 代码
//浏览器对象
var browser = {
    versions: function() {
        var u = navigator.userAgent,
        app = navigator.appVersion;
        return {
            trident: u.indexOf('Trident') > -1,
            //IE内核
            presto: u.indexOf('Presto') > -1,
            //opera内核
            webKit: u.indexOf('AppleWebKit') > -1,
            //苹果、谷歌内核
            gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1,
            //火狐内核
            mobile: !!u.match(/AppleWebKit.*Mobile.*/),
            //是否为移动终端
            ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/),
            //ios终端
            android: u.indexOf('Android') > -1 || u.indexOf('Adr') > -1,
            //android终端
            iPhone: u.indexOf('iPhone') > -1,
            //是否为iPhone或者QQHD浏览器
            iPad: u.indexOf('iPad') > -1,
            //是否iPad
            Safari: u.indexOf('Safari') > -1,
            //是否Safari
            weixin: u.indexOf('MicroMessenger') > -1,
            //是否微信 (2015-01-22新增)
            qq: u.match(/\sQQ/i) == " qq" //是否QQ
        };
    } (),
    language: (navigator.browserLanguage || navigator.language).toLowerCase()
}
//获取video元素
var oBanVideo = document.getElementById('banVideo');
//添加事件
function addHandler(element,type,handler) {
    var isIE8 = !+"\v1";
    if(element.addEventListener){
        //检测是否为DOM2级方法
        element.addEventListener(type,handler,{ passive: false });
    }else if(element.attachEvent){
        //检测是否为IE级方法
        if(!isIE8){
            //--IE9+
            element.attachEvent("on" + type, function () {
                //通过call或者apply解决IE下this指向问题
                handler.apply(element);
            });
        }else{
            //--IE8↓
            element["on" + type] = handler;
        };
    }else {
        //检测是否为DOM0级方法
        element["on" + type] = handler;
    }
};
//播放
function playFn(){
    oBanVideo.play();
    //调整声音 -- volume 属性设置或返回视频的当前音量,从 0.0 (静音) 到 1.0 (最大声)。
    if(oBanVideo.volume){
        oBanVideo.volume = 0.8;
    }
}
//微信浏览器自动播放
if(browser.versions.iPhone && browser.versions.weixin){
    //微信webview全局内嵌,WeixinJSBridgeReady方法
    addHandler(document,"WeixinJSBridgeReady",playFn);
}
  • 移动端一般浏览器播放情况
    IOS safari 无法自动播放
    安卓 小米机百度 无法自动播放,地球浏览器 可以自动播放

  • PC端chrome浏览器中,如果打开浏览器授权,视频仍无法自动播放
    方案:
    为audio标签增加muted属性
    效果:
    视频可以自动播放了,但是声音处于静音状态,需要用户手动打开视频声音

  • PC端chrome浏览器中,音频播放报错:
    play() failed because the user didn't interact with the document first
    说明打开页面,不被信任,存在授权问题。
    方案:
    查看网站信息 - 网站设置 - 隐私设置与安全性 - 声音 选择允许

  1. 关于音频文件预加载
    通过canplaythrough事件来监听
//音频加载
function loadAudio(_src,_cbFn){
  var oTag = new Audio();
  oTag.oncanplaythrough = function(res){
    _cbFn && _cbFn();
  }; 
  oTag.src = _src;
}

常用对象的属性与方法

  1. 查看当前浏览器是否支持音频
!!(document.createElement('video').canPlayType);
  1. 获取音频的总时长 (直接获取会为NaN,所以在onplay内修正)
oBanVideo.onplay = function(){
    if(oBanVideo.duration){
        console.log(oBanVideo.duration);
    };
};

[补充]:
在微信浏览器内打开,即便是在onplay的情况下,也会由于网络情况,第一次出现NaN音频时长的情况。
解决方法,开启一个循环定时器,在真实获取时长后,关闭这个定时器。

  1. 获取音频播放进度( 当前播放时间/总时长 )
oBanVideo.ontimeupdate = function(){
    console.log(Math.floor(oBanVideo.currentTime/oBanVideo.duration*100)+'%');
};
  1. 播放结束时候触发
oBanVideo.onended = function() {
    console.log('播放完毕');
};

音频精灵

说明:
将多个散碎的音效合并为一个整体的音频文件,并通过调整播放帧移动至特定位置播放,并播放一次或(伪无限)循环播放

定义一个创建音频标签的函数
拥有:

  • 创建音频标签能力
  • 设置音频是否可以循环与否
  • 将播放的音频,音量过渡至某个值
  • 修改音频资源,并加载
  • 在音频资源特定位置播放,一次或多次
  • 暂停上述播放
  • 播放一些预设的音频
function createAudioFn(tagId){
    var _tempTag = null;
    //是否支持音频标签
    if(!!document.createElement('audio').play){
        
        //是否已经创建了音效标签
        if(!document.getElementById(tagId)){
            _tempTag = document.createElement('audio');
            _tempTag.id = tagId;
            // _tempTag.muted = true;
            document.getElementsByTagName('body')[0].appendChild(_tempTag);
        };

        //设置音频的循环
        _tempTag.setItLoop = function(btn){
            if(btn){
                _tempTag.setAttribute('loop','loop');
            }else{
                _tempTag.removeAttribute('loop');
            };
        };

        /*音量过渡到某值
        * target - (0~100)
        * cbFn - 回调
        */
        var vStepNum = 2;
        _tempTag.setVolumeTo = function(target,cbFn){
            if(Math.abs((_tempTag.volume)*100-target)<vStepNum){
                _tempTag.volume = target/100;
                return false;
            };
            //需要过渡修改音量的话
            if(_tempTag.volume*100>target){
                vStepNum = -1*vStepNum;
            }else{
                vStepNum = Math.abs(vStepNum);
            };
            clearInterval(_tempTag.vTimer);
            _tempTag.vTimer = setInterval(function(){
                _tempTag.volume = (Math.floor(_tempTag.volume*100+vStepNum))/100;
                if(Math.abs(_tempTag.volume*100-target)<Math.abs(vStepNum) || _tempTag.volume*100==target){
                    _tempTag.volume = target/100;
                    clearInterval(_tempTag.vTimer);
                    //回调
                    cbFn && cbFn();
                }
            },30);
        };

        //加载音频
        _tempTag.loadSource = function(_src){
            _tempTag.pause && _tempTag.pause();
            //mp3音频资源
            if(!_tempTag.aSource){
                //创建标签
                _tempTag.aSource = document.createElement('source');
                _tempTag.aSource.src = _src;
                _tempTag.aSource.type = "audio/mpeg";
                _tempTag.appendChild(_tempTag.aSource);
            }else{
                //修改资源
                _tempTag.aSource.src = _src;
            };
            //更改视频来源,并重载视频
            _tempTag.load && _tempTag.load();
        };

        /*在某范围内重复播放
        * startTime - 播放开始
        * endTime   - 播放结束
        * loopTime  - 循环次数
        */
        _tempTag.playDuration = function(startTime,endTime,loopTime){
            //初次播放
            clearInterval(_tempTag.iTimer);
            _tempTag.loopTime = 1;
            _tempTag.currentTime = startTime;
            _tempTag.play && _tempTag.play();

            //播放结束与循环
            _tempTag.iTimer = setInterval(function(){
                //播放结束
                if(_tempTag.currentTime>=endTime){
                    //是否需要循环
                    if(loopTime && loopTime>1){
                        //需要循环
                        if(_tempTag.loopTime>=loopTime){
                            clearInterval(_tempTag.iTimer);
                            _tempTag.pause && _tempTag.pause();
                            _tempTag.loopTime = 0;
                            return false;
                        };
                        //未循环结束
                        _tempTag.loopTime++;
                        _tempTag.currentTime = startTime;
                        _tempTag.play && _tempTag.play();
                    }else{
                        //不需要循环
                        clearInterval(_tempTag.iTimer);
                        _tempTag.pause && _tempTag.pause();
                    };
                };
            },30);
        };

        //停止播放
        _tempTag.pauseDuration = function(){
            clearInterval(_tempTag.iTimer);
            _tempTag.pause && _tempTag.pause();
        };

        //播放(预定义区间)的声音
        _tempTag.playDurationInTag = function(audioName){
            var _tar = this;
            switch(audioName){
                //走在大厅
                case 'walkInHall':
                    _tar.loadSource('../audio/foot_step.mp3');
                    _tar.playDuration(0.2,0.8,99);
                    break;
                //走在金属
                case 'walkInMetal':
                    _tar.loadSource('../audio/foot_step.mp3');
                    _tar.playDuration(4,5,99);
                    break; 
                //mp5开火
                case 'mp5fire':
                    _tar.loadSource('../audio/weapon.mp3');
                    _tar.playDuration(0,0.8,99);
                    break;
            }
        };

    };
    return _tempTag;
};

使用:

//创建一个音频标签
window.effAudioObj1 = createAudioFn('effAudioObj1');
//播放某个预设的音频
effAudioObj1.playDurationInTag && effAudioObj1.playDurationInTag('mp5fire');
//预设播放结束
effAudioObj1.pauseDuration && effAudioObj1.pauseDuration();

未完待续...

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容