[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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM