浏览器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();

未完待续...

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容