浏览器通过原生JS实现音频播放控制功能

浏览器通过原生JS实现音频播放控制功能

  • 一. AudioContext介绍
  • 二. FileReader介绍
  • 三. 音频播放执行流程
  • 四. 音频播放主要代码简述
  • 五. 播放本地文件
    • 1. 创建Input, 提供文件选择框
    • 2. 创建Button, 提供本地文件播放控制
    • 3. 播放按钮触发方法
  • 六. 播放URL地址获取音频
    • 1. 创建Input, 提供地址输入框
    • 2. 创建Button, 提供URL地址获取音频播放控制
    • 3. 播放按钮触发方法
  • 七. 将音频绑定到Audio元素上
  • 八. Audio元素播放JS控制
  • 九. Vue样式
  • 十. Vue完整代码

一. AudioContext介绍

  • AudioContext接口表示由链接在一起的音频模块构建的音频处理图,每个模块由一个AudioNode表示。音频上下文控制它包含的节点的创建和音频处理或解码的执行。在做任何其他操作之前,您需要创建一个AudioContext对象,因为所有事情都是在上下文中发生的。建议创建一个AudioContext对象并复用它,而不是每次初始化一个新的AudioContext对象,并且可以对多个不同的音频源和管道同时使用一个AudioContext对象。详情
  • AudioContext 兼容写法
createAudioContext() {
     
  if (!window.AudioContext) {
     
    window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;
  }
  return new window.AudioContext();
}

二. FileReader介绍

  • FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。详情
  • FileReader使用模板
let fileReader = new FileReader();
fileReader.onabort= (e) => {
      在读取操作被中断时触发的操作 };
fileReader.onloadstart = (e) => {
      在读取操作开始时触发的操作 };
fileReader.onload = (e) => {
      在读取操作完成时触发的操作 };
fileReader.onerror= (e) => {
      在读取操作发生错误时触发的操作 };
fileReader.onloadend= (e) => {
      在读取操作结束时(要么成功,要么失败)触发的操作 };
fileReader.abort(); // 终止操作.
fileReader.readAsArrayBuffer(data); // 读取指定的 Blob中的内容, 一旦完成, result 属性中保存的将是被读取文件的 ArrayBuffer 数据对象.
fileReader.readAsText(); // 读取指定的Blob中的内容。一旦完成,result属性中将包含一个字符串以表示所读取的文件内容。
...... // 等等其他操作

三. 音频播放执行流程

传递
传递
读取成功传递
读取失败结束
解析成功
解析失败结束
XHR通过URL获取音频ArrayBuffer或Blob
FileReader 对象
Input_type=File_选择本地音频文件
AudioContext获取实例
提示信息结束
音频源解析 decodeAudioData
创建音频源 audioBufferSourceNode
音频播放控制

四. 音频播放主要代码简述

play(file) {
     
  let audioContext = this.createAudioContext();
  if (!audioContext) {
     
    return;
  }
  let fileReader = new FileReader();
  fileReader.onload = (e) => {
     
    // 将音频源绑定到Audio元素上.
    this.relevance(e.target.result);
    audioContext.decodeAudioData(e.target.result, (buffer) => {
     
      // 创建音频源
      let audioBufferSourceNode = audioContext.createBufferSource();
      // 创建分析器
      let analyser = audioContext.createAnalyser();
      // 音频源链接到分析器
      audioBufferSourceNode.connect(analyser);
      // 分析器链接到目的地扬声器.
      analyser.connect(audioContext.destination);
      audioBufferSourceNode.buffer = buffer;

      audioBufferSourceNode.start = audioBufferSourceNode.start || audioBufferSourceNode.noteOn;
      audioBufferSourceNode.stop = audioBufferSourceNode.stop || audioBufferSourceNode.noteOff;

      audioBufferSourceNode.start(0);
      audioBufferSourceNode.onended = (e) => {
     
        console.log(e);
      };
      this.$audioContext = audioContext;
    }, (e) => {
     
      console.error(e);
    },);
  };
  fileReader.onerror = (e) => {
     
    console.error('Fail to read the file!', e);
  };
  fileReader.readAsArrayBuffer(file);
},

五. 播放本地文件

1. 创建Input, 提供文件选择框

<input id="file" type="file" placeholder="请选择本地音频文件"/>

2. 创建Button, 提供本地文件播放控制

<Button size="small" @click="file_play">播放文件内容</Button>

3. 播放按钮触发方法

file_play() {
     
  // 获取Input文件选择框元素
  let files = document.getElementById('file').files;
  if (!files) {
      // 判断是否已经选择文件
    return;
  }
  let file = files[0]; // 获取第1个文件
  this.play(file); // 触发播放控制
}

六. 播放URL地址获取音频

1. 创建Input, 提供地址输入框

<input id="url" placeholder="填写URL"/>

2. 创建Button, 提供URL地址获取音频播放控制

<Button size="small" @click="url_play">播放链接内容</Button>

3. 播放按钮触发方法

/**
 * 创建(获取)HttpRequest实例.
 * @returns {XMLHttpRequest|any}
 */
createXHR() {
     
  if (typeof XMLHttpRequest != "undefined") {
     
    return new XMLHttpRequest();
  } else if (typeof ActiveXObject != "undefined") {
     
    if (typeof arguments.callee.activeXString != "string") {
     
      let versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"];
      for (let i = 0, len = versions.length; i < len; i++) {
     
        try {
     
          new ActiveXObject(versions[i]);
          arguments.callee.activeXString = versions[i];
          break;
        } catch (ex) {
     
          //跳过
        }
      }
    }
    return new ActiveXObject(arguments.callee.activeXString);
  } else {
     
    throw new Error("No XHR object available.");
  }
}
/**
 * 获取音频进行播放.
 */
url_play() {
     
  let url = document.getElementById('url').value;
  let form = new FormData();
  let xhr = this.createXHR();
  xhr.withCredentials = true;
  xhr.responseType = "blob";
  xhr.open("GET", url, true);
  xhr.onreadystatechange = () => {
     
    if (xhr.readyState == 4) {
     
      if (xhr.status == 200) {
     
        let response = xhr.response;
        this.play(response);
      } else {
     
        console.warn('请求失败');
      }
    }
  };
  xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
  xhr.send(form);
}

七. 将音频绑定到Audio元素上

  • 音频信息绑定到Audio元素上后, 可以对Audio元素进行播放控制, 可以跳过AudioContext, audioBufferSourceNode播放控制, 两者可任选其中一种进行播放控制.
  • 相对来说, Audio元素播放控制相对方便一些.
relevance(arrayBuffer) {
     
  // 通过Blob合建对象URL本地地址
  let url = URL.createObjectURL(new Blob([arrayBuffer], {
     'type': 'audio/mpeg'}));
  // 绑定到 audio 元素上
  this.$refs.recordPlayer.src = url;
  // document.getElementById('player').src = url;
}

八. Audio元素播放JS控制

let player = document.getElementById('player')
player.paly(); // 播放
player.pause(); // 暂停

九. Vue样式

浏览器通过原生JS实现音频播放控制功能_第1张图片

十. Vue完整代码

<template>
  <div style="height: 100%;width: 350pt;margin: 100pt auto;">
    <audio id="player" ref="recordPlayer" controls src=""></audio>
    <div style="height: 20pt;"></div>
    <input id="file" type="file" placeholder="请选择本地音频文件"/>
    <Button size="small" @click="file_play">播放文件内容</Button>
    <div style="height: 20pt;"></div>
    <input id="url" placeholder="填写URL"/>
    <Button size="small" @click="url_play">播放链接内容</Button>
    <div style="height: 20pt;"></div>
    <div>
      <ButtonGroup>
        <Button size="small" @click="resume">继续</Button>
        <Button size="small" @click="suspend">暂停</Button>
      </ButtonGroup>
    </div>
  </div>
</template>

<script>
  export default {
     
    name: "home",
    mounted() {
     
    },
    methods: {
     
      /**
       * 创建(获取)HttpRequest实例.
       * @returns {XMLHttpRequest|any}
       */
      createXHR() {
     
        if (typeof XMLHttpRequest != "undefined") {
     
          return new XMLHttpRequest();
        } else if (typeof ActiveXObject != "undefined") {
     
          if (typeof arguments.callee.activeXString != "string") {
     
            let versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0", "MSXML2.XMLHttp"];
            for (let i = 0, len = versions.length; i < len; i++) {
     
              try {
     
                new ActiveXObject(versions[i]);
                arguments.callee.activeXString = versions[i];
                break;
              } catch (ex) {
     
                //跳过
              }
            }
          }
          return new ActiveXObject(arguments.callee.activeXString);
        } else {
     
          throw new Error("No XHR object available.");
        }
      },
      createAudioContext() {
     
        if (!window.AudioContext) {
     
          window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;
        }
        return new window.AudioContext();
      },
      resume() {
     
        this.$audioContext.resume();
      },
      suspend() {
     
        this.$audioContext.suspend();
      },
      file_play() {
     
        let files = document.getElementById('file').files;
        if (!files) {
     
          return;
        }
        let file = files[0];
        this.play(file);
      },
      /**
       * 获取音频进行播放.
       */
      url_play() {
     
        let url = document.getElementById('url').value;
        let form = new FormData();
        let xhr = this.createXHR();
        xhr.withCredentials = true;
        xhr.responseType = "blob";
        xhr.open("GET", url, true);
        xhr.onreadystatechange = () => {
     
          if (xhr.readyState == 4) {
     
            if (xhr.status == 200) {
     
              let response = xhr.response;
              this.play(response);
            } else {
     
              console.warn('请求失败');
            }
          }
        };
        xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
        xhr.send(form);
      },
      relevance(arrayBuffer) {
     
        // 通过Blob合建对象URL本地地址
        let url = URL.createObjectURL(new Blob([arrayBuffer], {
     'type': 'audio/mpeg'}));
        // 绑定到 audio 元素上
        this.$refs.recordPlayer.src = url;
        // document.getElementById('player').src = url;
      },
      play(file) {
     
        let audioContext = this.createAudioContext();
        if (!audioContext) {
     
          return;
        }
        let fileReader = new FileReader();
        fileReader.onload = (e) => {
     
          // 将音频源绑定到Audio元素上.
          this.relevance(e.target.result);
          audioContext.decodeAudioData(e.target.result, (buffer) => {
     
            // 创建音频源
            let audioBufferSourceNode = audioContext.createBufferSource();
            // 创建分析器
            let analyser = audioContext.createAnalyser();
            // 音频源链接到分析器
            audioBufferSourceNode.connect(analyser);
            // 分析器链接到目的地扬声器.
            analyser.connect(audioContext.destination);
            audioBufferSourceNode.buffer = buffer;

            audioBufferSourceNode.start = audioBufferSourceNode.start || audioBufferSourceNode.noteOn;
            audioBufferSourceNode.stop = audioBufferSourceNode.stop || audioBufferSourceNode.noteOff;

            audioBufferSourceNode.start(0);
            audioBufferSourceNode.onended = (e) => {
     
              console.log(e);
            };
            this.$audioContext = audioContext;
          }, (e) => {
     
            console.error(e);
          },);
        };
        fileReader.onerror = (e) => {
     
          console.error('Fail to read the file!', e);
        };
        fileReader.readAsArrayBuffer(file);
      },
    },
  }
</script>
<style scoped></style>

你可能感兴趣的:(JS,web,js,javascript,html5)