LoginSignup
2
1

More than 1 year has passed since last update.

ブラウザで音声ファイルを任意のタイミングで再生する方法

Last updated at Posted at 2022-12-22

概要

 ブラウザで音声ファイルを再生する実装をする際に多くの場合は、HTMLMediaElementベースのaudioタグAudio()コンストラクターで事足りると思います。が、iOS Safari16.0ではClick Eventを都度拾わないと再生ができない状況に出くわしました。そこで本記事では、その回避策としてAudioContextを利用したWebブラウザで音声ファイルを任意のタイミングで再生する実装を以下に記します。(iOS Safari16.0, Android Chrome108で動作確認)

実装方法

// WebKitを使えるように型拡張
declare global {
  interface Window {
    webkitAudioContext: typeof AudioContext
  }
}
/**
 * 一度のclickイベントの後なら自由に音声ファイルを操作できるようにするクラス
 */
export default class Sound {
  audioArrayBuffer?: ArrayBuffer
  soundPath: string
  constructor(soundPath: string) {
    this.soundPath = soundPath
  }
  /**
   * 音声ファイルをロードするメソッド
   */
  async load() {
    // audioデータをArrayBufferに詰める。
    // XMLHttpRequest, fetch() or FileReaderのどれかを利用すれば良し
    const audioResponse = await fetch(this.soundPath)
    this.audioArrayBuffer = await audioResponse.arrayBuffer()
  }
  /**
   * 音声ファイルを任意のタイミングで再生するメソッド
   */
  async playSound() {
    if (!this.audioArrayBuffer)
      throw new Error('load メソッドを実行してください。')
    const audioContext = new (window.AudioContext ||
      window.webkitAudioContext)()
    const source = audioContext.createBufferSource()
    source.buffer = await audioContext.decodeAudioData(
      this.audioArrayBuffer.slice(0)
    )
    source.loop = false
    source.connect(audioContext.destination)
    source.start(0)
  }
}

使い方

どこかでClick Eventを受けた後に以下のように利用してください。おそらく、複数回playSoundメソッドを叩いても動作するはずです。

const soundPath = 'path'
const sound = new Sound(soundPath)
sound.load()
sound.playSound()
// ...何かの処理(Click Eventを受け取る必要なし)
sound.playSound()
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1