zoukankan      html  css  js  c++  java
  • [JavaScript] audio在浏览器中自动播放

    audio 在浏览器中自动播放

    autoplay 属性

    autoplay 属性规定一旦音频就绪马上开始播放。
    如果设置了该属性,音频将自动播放。

    使用 autoplay 属性进行播放

        //使用autoplay属性
        var src = "./award.wav";
        var body = document.getElementsByTagName("body")[0];
    
        if (body.getElementsByTagName("audio").length <= 0) {
          var audio = document.createElement("audio");
          audio.setAttribute("id", "awardAudio");
          audio.setAttribute("autoplay", "autoplay");
          audio.setAttribute("src", src);
          body.appendChild(audio);
    
          setTimeout(function() {
            body.removeChild(audio);
          }, 2300);
        }
    
    

    oncanplaythrough 事件

    oncanplaythrough 事件在视频/音频(audio/video)可以正常播放且无需停顿和缓冲时触发。
    在视频/音频(audio/video)加载过程中,事件的触发顺序如下:

    1. onloadstart
    2. ondurationchange
    3. onloadedmetadata
    4. onloadeddata
    5. onprogress
    6. oncanplay
    7. oncanplaythrough
    //1
    <audio oncanplaythrough="event">
    //2
    audio.oncanplaythrough=function(){event()};
    //3
    audio.addEventListener("canplaythrough", event;
    

    监听 canplaythrough 事件进行播放

        // 监听加载事件执行play方法
        var src = "./award.wav";
        var body = document.getElementsByTagName("body")[0];
    
        if (body.getElementsByTagName("audio").length <= 0) {
          var audio = document.createElement("audio");
          audio.setAttribute("id", "awardAudio");
          audio.setAttribute("src", src);
          body.appendChild(audio);
    
          //判断音频是否加载完成?
          audio.addEventListener(
            "canplaythrough",
            function() {
              audio.play();
              setTimeout(function() {
                body.removeChild(audio);
              }, audio.duration * 1000 + 100);
            },
            false
          );
        }
    

    duration 在 autoplay 下回失效,返回 NaN

    JS 报错:Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first.

    https://goo.gl/xX8pDD这里是官方给出的解释,chrome66 之后反正是不能用了

    解决方法

    1. 在 chrome 浏览器中输入 chrome://flags/#autoplay-policy
    2. 在 Autoplay policy 下拉中设置无需用户手势
    3. 重启 chrome

    1. chrome.exe --disable-features=AutoplayIgnoreWebAudio

    MDN->audio

    • MDN->audio 属性
      • src 歌曲的路径
      • preload 是否在页面加载后立即加载(设置 autoplay 后无效)
      • controls 显示 audio 自带的播放控件
      • loop 音频循环
      • autoplay 音频加载后自动播放
      • currentTime 音频当前播放时间
      • duration 音频总长度
      • ended 音频是否结束
      • muted 音频静音为 true
      • volume 当前音频音量
      • readyState 音频当前的就绪状态
    • MDN->audio 事件
      • abort 当音频/视频的加载已放弃时
      • canplay 当浏览器可以播放音频/视频时
      • canplaythrough 当浏览器可在不因缓冲而停顿的情况下进行播放时
      • durationchange 当音频/视频的时长已更改时
      • emptied 当目前的播放列表为空时
      • ended 当目前的播放列表已结束时
      • error 当在音频/视频加载期间发生错误时
      • loadeddata 当浏览器已加载音频/视频的当前帧时
      • loadedmetadata 当浏览器已加载音频/视频的元数据时
      • loadstart 当浏览器开始查找音频/视频时
      • pause 当音频/视频已暂停时
      • play 当音频/视频已开始或不再暂停时
      • playing 当音频/视频在已因缓冲而暂停或停止后已就绪时
      • progress 当浏览器正在下载音频/视频时
      • ratechange 当音频/视频的播放速度已更改时
      • seeked 当用户已移动/跳跃到音频/视频中的新位置时
      • seeking 当用户开始移动/跳跃到音频/视频中的新位置时
      • stalled 当浏览器尝试获取媒体数据,但数据不可用时
      • suspend 当浏览器刻意不获取媒体数据时
      • timeupdate 当目前的播放位置已更改时
      • volumechange 当音量已更改时
      • waiting 当视频由于需要缓冲下一帧而停止

    在react中做成组件

    /**
     * Created by easterCat on 2017/10/13.
     */
    
    import React from 'react';
    import ReactDOM from 'react-dom';
    import {connect} from 'react-redux';
    import {Icon} from 'antd';
    
    
    class RecordAudio extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                isPlay: false,
                openMuted: false,
                volume: 100,
                allTime: 0,
                currentTime: 0
            };
    
            this.millisecondToDate = (time) => {
                const second = Math.floor(time % 60);
                let minite = Math.floor(time / 60);
                return `${minite}:${second >= 10 ? second : `0${second}`}`
            };
    
            this.controlAudio = (type, e) => {
                const audio = ReactDOM.findDOMNode(this.refs['audio']);
                switch (type) {
                    case 'allTime':
                        this.setState({
                            allTime: audio.duration
                        });
                        break;
                    case 'play':
                        audio.play();
                        this.setState({
                            isPlay: true
                        });
                        break;
                    case 'pause':
                        audio.pause();
                        this.setState({
                            isPlay: false
                        });
                        break;
                    case 'changeCurrentTime':
                        this.setState({
                            currentTime: e.target.value
                        });
                        audio.currentTime = e.target.value;
                        if (e.target.value === audio.duration) {
                            this.setState({
                                isPlay: false
                            })
                        }
                        break;
                    case 'getCurrentTime':
                        this.setState({
                            currentTime: audio.currentTime
                        });
                        if (audio.currentTime === audio.duration) {
                            this.setState({
                                isPlay: false
                            })
                        }
                        break;
                    //    是否静音
                    case 'muted':
                        audio.muted = !audio.muted;
                        //为true,则是静音模式
                        if (audio.muted) {
                            this.setState({
                                openMuted: true,
                                volume: 0
                            });
                        } else {
                            this.setState({
                                openMuted: false,
                                volume: 100
                            });
                        }
                        break;
                    //    调节音量
                    case 'changeVolume':
                        /**
                         * muted=true开启静音模式,muted=false开启声音
                         * @type {number}
                         */
                        audio.volume = e.target.value / 100;
                        this.setState({
                            volume: e.target.value,
                        });
                        //如果声音为0,开起静音
                        if (e.target.value <= 0) {
                            audio.muted = true;
                            this.setState({
                                openMuted: true
                            })
                        } else if (e.target.value >= 0) {
                            audio.muted = false;
                            this.setState({
                                openMuted: false
                            })
                        }
                        break
                }
            }
        }
    
        componentDidMount() {
    
        }
    
        render() {
            const {src} = this.props;
    
            return (
                <div className="audioBox">
                    <audio ref="audio"
                           src={src}
                           preload={true}
                           onCanPlay={() => this.controlAudio('allTime')}
                           onTimeUpdate={(e) => this.controlAudio('getCurrentTime')}
                    >
                        音乐播放器
                    </audio>
                    <i className={this.state.isPlay ? 'pause' : 'play'}
                       onClick={() => this.controlAudio(this.state.isPlay ? 'pause' : 'play')}
                    >
                        {
                            this.state.isPlay ? <Icon className="pause-btn" type="pause"/> :
                                <Icon className="play-btn" type="caret-right"/>
                        }
                    </i>
    
                    <span className="current">
                        {
                            this.millisecondToDate(this.state.currentTime) + '/' + this.millisecondToDate(this.state.allTime)
                        }
                    </span>
    
                    <input type="range"
                           className="time"
                           min="0"
                           step="0.01"
                           max={this.state.allTime}
                           value={this.state.currentTime}
                           onChange={(e) => this.controlAudio('changeCurrentTime', e)}
                    />
    
                    <i className={this.state.openMuted ? 'mute' : 'nomute'}
                       onClick={() => this.controlAudio('muted')}
                    >
                        {
                            this.state.openMuted ? <Icon className="nomute-btn" type="check"/> :
                                <Icon className="mute-btn" type="close"/>
                        }
                    </i>
                    <input type="range"
                           className="volume"
                           min="0"
                           step="1"
                           max="100"
                           onChange={(e) => this.controlAudio('changeVolume', e)}
                           value={this.state.openMuted ? 0 : this.state.volume}
                    />
                </div>
            )
        }
    }
    
    const mapStateToProps = (state) => {
        return {}
    };
    
    const mapActionCreators = {};
    
    export default connect(mapStateToProps, mapActionCreators)(RecordAudio);
    

    HTML 5 视频/音频参考手册
    HTML5 声音引擎 Howler.js
    MDN audio
    基于 react 的 audio 组件
    HTML5 Audio 的兼容性问题和优化
    html5 audio 音频播放全解析
    音频 API => AudioContext

  • 相关阅读:
    日志规范实践
    序列化和反序列化及Protobuf 基本使用
    简述TCP网络编程本质
    笔记:多线程服务器的适用场合(1)
    聊聊同步、异步、阻塞与非阻塞(转)
    《EntrePreneur》发刊词
    make和makefile简明基础
    luogu P3687 [ZJOI2017]仙人掌 |树形dp
    luogu P3172 [CQOI2015]选数 |容斥原理
    luogu P4513 小白逛公园 |线段树
  • 原文地址:https://www.cnblogs.com/mybilibili/p/10376528.html
Copyright © 2011-2022 走看看