1
votes

I'm making an audio player with vue.js. But when I click the play button, I can hear the sound as well on the desktop chrome but can't hear in the iPhone chrome and safari browser.

Hope someone resolve this issue as soon as possible. Audio file is .wav file and audioUrl is encoded one.

This is my code snippet.

<template> 
  <div class="modal-card">
    <header class="modal-card-head">
      <p class="modal-card-title">
        {{ name }}
      </p>
    </header>
    <section class="modal-card-body">
      <div class="audioplayer">
        <i :class="playButtonClass" @click="play" style="color:#FFF" aria-hidden="true"></i>
        <div class="progress" @click="progressClick">
          <div class="current" :style="{width: currentWidth}"></div>
        </div>
        <span class="time">{{ time }}</span>
        <i class="fa fa-volume-up volumeBtn" style="color:#FFF" aria-hidden="true"></i>
        <div class="volume" @click="volumneClick">
          <div class="currentVol" :style="{width: currentVolWidth}"></div>
        </div>
      </div>
    </section>
    <footer class="modal-card-foot">
      <button class="button" type="button" @click="$parent.close()">
        {{ lang('Close') }}
      </button>
    </footer>
  </div>
</template>

<script>
export default {
  name: 'AudioPlayer',
  data() {
    return {
      audio: null,
      playButtonClass: 'fa fa-play playBtn',
      currentWidth: '0px',
      currentVolWidth: '0px',
      time: '00:00',
      progress: null,
      vProgress: null,
      modalLeft: null,
      loaded: true,
      duration: 0,
    }
  },
  props: ['audioUrl', 'name', 'size'],
  mounted() {    
    this.progress = document.querySelector(".progress")
    this.vProgress = document.querySelector('.volume')
    this.modalLeft = document.querySelector('.modal-card').offsetLeft
    this.currentVolWidth = this.vProgress.offsetWidth +'px'
    this.audio = new Audio(this.audioUrl)
    this.audio.play()
    this.duration = Math.floor(this.size / 1024 * 8 / 128)
  },
  beforeDestroy() {
    this.audio.pause()
  },
  methods: {
    play() {
      if (this.audio.paused) {
        this.audio.play()
        this.playButtonClass = "fa fa-pause playBtn"
      } else {
        this.audio.pause()
        this.playButtonClass = "fa fa-play playBtn"
      }      

      setInterval(() => {
        var seconds = Math.round(this.audio.currentTime)
        var secondsText = seconds % 60
        if (secondsText < 10) {
          secondsText = "0" + secondsText
        }
        var minutes = Math.floor(seconds / 60)
        var minutesText = minutes
        if (minutes < 10) {
          minutesText = "0" + minutes
        }

        this.currentWidth = Math.round(this.audio.currentTime) / this.duration * this.progress.offsetWidth + "px"
        this.time = minutesText + ":" + secondsText
      }, 1000)
    },
    progressClick(e) {
      var X = (e.clientX-document.querySelector('.modal-card').offsetLeft) - this.progress.offsetLeft
      this.currentWidth = X + "px"
      this.audio.currentTime = X * this.duration / this.progress.offsetWidth
    },
    volumneClick(e) {
      var X = e.clientX - document.querySelector('.modal-card').offsetLeft - this.vProgress.offsetLeft
      this.currentVolWidth = X + "px"
      this.audio.volume = X / this.vProgress.offsetWidth      
    }
  },
}

</script>
1
I know on iOS (and I think other mobile browser) you can only play via a page interaction (it may even require a button click - not sure). I wonder if the call to audio.play() in mounted is messing things up. Does it work if you remove that line?David Weldon
Thanks for your consideration. But Its still not working when I remove the audio.play() in mountedAlex Xie
Are you seeing any errors in the console?T. Short
Thanks for your comment. There is no errors in the console.Alex Xie

1 Answers

0
votes

I faced the same problem, without finding much example, here is my tested working example, hope it help. =)

<template>
<button @click="userInitiateInteraction">Click</v-btn>
</template>
<script>
export default {
data() {
    return {
        soundEffect: new Audio('/mp3/initiate.mp3'),
        sound: {
                sound1: '/mp3/sound1.mp3',
                sound2: '/mp3/sound2.mp3',
        },
    }
},
 methods: {
        userInitiateInteraction() {
            this.soundEffect.play()
            this.getDataFromServer()
        },
         playSound(sound) {
            if (sound) {
                this.soundEffect.src = sound
                this.soundEffect.play()
            }
        },
        getDataFromServer() {
            axios.get('/api/url').then(res => {
                if (res.data.success) {
                    // Test without user interaction play sound
                    this.playSound(this.sound.sound1) // this play sound1
                }
            })
        },
        anyOtherEventToPlaySound(){
            axios.get('/api/url').then(res => {
                if (res.data.success) {
                    // Test without user interaction play sound
                    this.playSound(this.sound.sound2) // this play sound2
                }
            })
        },
 }
 }
 </script>