音频(Audio)实现技术

重要通知

类目简介

基本概况

音频格式MIME类型

----------------------------------------------
	Format	    MIME-type
----------------------------------------------
	MP3					audio/mpeg
	Ogg					audio/ogg
	Wav					audio/wav
----------------------------------------------

音频格式

pcm格式

PCM(Pulse-code modulation,脉冲编码调制)是一种音频原始数据格式,是将模拟电信号转化为数字信号的一种技术,涉及采样、量化和编码三个过程。

代码示例

const loadAudioData = function(url) {
  return new Promise((resolve, reject) => {
    const audio = document.createElement('audio');
    audio.src = url;
    audio.onloadeddata = function() {
      resolve(audio);
    }
    audio.onerror = function() {
      reject();
    }
  });
}

const url = 'https://test.ysunlight.com/Reference/audio/mov.mp4';
loadAudioData(url).then((audio) => {
  audio.autoplay = 'autoplay';
  audio.controls = 'controls';
  audio.muted = 'muted';
  // document.body.append(audio);
  window.setTimeout(() => { 
    audio.click();
    // audio.play(); 
  });
});

Web Audio API

上传音频

const fileEl: HTMLInputElement = document.createElement("input");
if (!fileEl) return;

fileEl.setAttribute("type", "file");
fileEl.setAttribute("accept", "audio/mpeg,audio/ogg,audio/wav");
fileEl.click();

const getFileData = (fileTarget: HTMLInputElement) => {
  return new Promise((resolve) => {
    fileTarget.onchange = async function (e) {
      // @ts-ignore # 忽视本行代码的小错误
      resolve(e.target.files[0]);
    };
  });
};

const fileData = await getFileData(fileEl);


const base64AudioData = "data:audio/mpeg;base64,...";
const blobLink = base64ToBlobUrl(base64AudioData);

const audio = new Audio();
audio.src = blobLink; 
audio.play();


// 将Base64编码的字符串转换为Blob URL的函数
function base64ToBlobUrl(base64Data) {
  const byteCharacters = atob(base64Data.split(',')[1]);
  const byteNumbers = new Array(byteCharacters.length);
  for (let i = 0; i < byteCharacters.length; i++) {
    byteNumbers[i] = byteCharacters.charCodeAt(i);
  }
  const byteArray = new Uint8Array(byteNumbers);
  const blob = new Blob([byteArray], { type: 'audio/mpeg' }); // 根据你的音频类型调整MIME类型
  return URL.createObjectURL(blob); // 创建Blob URL
}

创建对象

一些经常被使用的属性,包括 src、currentTime、duration、paused、muted 和 volume。

const audioEl = new Audio("car_horn.wav");

audioEl.addEventListener("loadeddata", () => {
  let duration = audioEl.duration;
  // duration 变量现在存放音频的播放时长(单位秒)
});

音频生命周期事件

当音频/视频处于加载过程中时,会依次发生以下事件。

  • loadstart
  • durationchange
  • loadedmetadata
  • loadeddata
  • progress
  • canplay
  • canplaythrough

API事件

  • loadstart:客户端开始请求数据。
  • progress:正在播放的时候不停触发,如果暂停不会触发,触发的时间间隔比较大。
  • play:play()和autopaly播放时,类似事件onplaying。
  • pause:pause()方法触发时。
  • ended:当结束播放时。
  • timeupdate:当前播放时间发生改变的时候,播放中常用的时间处理,如果暂停不会触发,触发的时间间隔比较小。
  • canplaythrough:歌曲已经载入完成。
  • canplay:缓冲至可播放状态,类似事件onloadedmetadata、onloadedmetadata。

拼接多个base64语音流

// 语音处理模型
const audioList = [
  "data:audio/mpeg;base64,........",
  "data:audio/mpeg;base64,........",
  "data:audio/mpeg;base64,........",
  "data:audio/mpeg;base64,........"
],


function audioModel() {
  const blobList = audioList.map((blob) => {
    return base64ToBlob(blob);
  });

  concatenateBlobs(blobList).then(function (combinedBlob) {
    // 现在combinedBlob是拼接后的语音文件Blob对象
    var url = URL.createObjectURL(combinedBlob);

    // 可以使用这个URL来播放或下载语音文件
    var audio = new Audio(url);
    audio.play();

    // 注意:在实际应用中,需要在适当的时候释放创建的URL资源
    // URL.revokeObjectURL(url);
  });

}


// 将Base64字符串转换为Blob对象
function base64ToBlob(base64, mime) {
  var parts = base64.split(';base64,');
  var contentType = parts[0].split(':')[1];
  var raw = window.atob(parts[1]);
  var rawLength = raw.length;
  var uInt8Array = new Uint8Array(rawLength);
  for (var i = 0; i < rawLength; ++i) {
    uInt8Array[i] = raw.charCodeAt(i);
  }
  return new Blob([uInt8Array], { type: contentType });
}

// 拼接两个Base64编码的语音文件
async function concatenateBlobs(blobArray = []) {
  const _array = [];

  for (let i = 0; i < blobArray.length; i++) {
    const result = transFileReaders(blobArray[i]);
    _array.push(result);
  }

  return Promise.all(_array).then(function (results) {
    var combined = new Blob(results, { type: "audio/mpeg" });
    return combined;
  });
}

function transFileReaders(blob = "") {
  var reader = new FileReader();
  reader.readAsArrayBuffer(blob);

  return new Promise((resolve) => {
    reader.onload = function () {
      resolve(reader.result);
    }
  });
}

音频 (Audio)元素

<audio> 提供了播放音频文件的标准。

注意事项

现代浏览器已经屏蔽了音频自动播放时携带音量的问题,即若设置自动播放需静音模式。

音频格式的MIME类型

  • MP3:type="audio/mpeg"
  • Ogg:type="audio/ogg"
  • Wav:type="audio/wav"
<audio controls>
  <source src="music.ogg" type="audio/ogg">
  <source src="music.mp3" type="audio/mpeg">
  <source src="music.wav" type="audio/wav">
</audio>

获取音频数据

export function generateAudioData(
  url: string,
  options = {} as Record<string, any>
) {
  const { type, progress } = options;

  const audio = document.createElement("audio");
  const source = document.createElement("source");
  source.src = url;
  source.type = type || "audio/mpeg";
  audio.appendChild(source);

  return new Promise((resolve, reject) => {
    audio.onloadeddata = function () {
      resolve(audio);
    };

    audio.onprogress = function (e) {
      progress && progress(e);
    };

    audio.onerror = function () {
      reject(null);
    };
  });
}


const audio = await generateAudioData(url);
console.info(audio.duration);

场景代码

window.setTimeout(function() {
  var total = Math.floor(audioPlayer.duration);
  var audioControl = function() {
    var time = audioPlayer.currentTime;
    //防止死缓
    console.log(time);
    if (time >= total) {
      current.attr("data-state", "false");
      button.attr("src", path + controlArray[0]);
      current.removeClass('audio-play');
      audioPlayer.pause();
      window.clearInterval(interval);
    }
  };
  interval = window.setInterval(audioControl, 1000);
}, 150);

音频源

音频源渠道

  • 直接通过 Javascript 生成声音节点产生(例如一个振动发声器)
  • 由脉冲编码调制产生的原始数据(音频环境中可以调用一些方法来解码部分支持的格式)
  • 从 HTML 元素中(例如 <video> 或者 <audio> 标签)
  • 直接通过一个 WebRTC (en-US) MediaStream 获取流媒体(例如一个摄像头或麦克风)

振荡器

音频效果节点

混响

双二阶滤波器

平移

压缩

new AudioPlayer对象

Last Updated:
Contributors: 709992523