2

I have an audio file which plays songs. I am currently making a slider that is equal to the songs length and current time. You can't use player.currentTime in the watch component in Vue so how would you go about updating a value in realtime equal to player current time.

I currently have the v-model="player.currentTime" but that only updates when I pause the songs and not real-time.

This is what I have so far

player: new Audio()
this.player.src = this.songs[this.songIndex].src
this.player.play()

Player:

<input
  type="range"
  name="timeStamp"
  ref="time"
  v-model.lazy="this.player.currentTime"
  step="0.1"
  class="w-[100%] hover:cursor-pointer"
/>
kissu
  • 40,416
  • 14
  • 65
  • 133
Mat
  • 405
  • 4
  • 12
  • 1
    Not sure what is the emitted event in that case, but maybe `v-model` is only being triggered on `blur` event or a `lazy` one. Depending on how you did your player implementation, you may need to transform your `v-model` into something maybe more specific like an `@input` or something specific if you're using a Vue specific package. Check your Vue devtools for any events or inspect the element itself to see if there are any listeners tied to it. – kissu Aug 15 '22 at 10:13
  • my player just lives in the data section of the main app component as player = new Audio() .I pass it to a child component as a prop. all my other v-models change realtime but not this one for some reason – Mat Aug 15 '22 at 10:16
  • 1
    Looking [at this](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video#events), it looks like the event for that one is `timeupdate` if I'm not mistaken. Maybe try a `@timeupdate` on the player to see if it brings something up each second. – kissu Aug 15 '22 at 10:18
  • I don't have a player element that's the issue, I only have a variable that's a player – Mat Aug 15 '22 at 10:43
  • Some actual code would be welcome here (as text). How do you display it in your template so? Still, it should work the same way even if you don't have an HTML element. – kissu Aug 15 '22 at 10:59
  • I don't display it as its only audio I play it in the background. – Mat Aug 15 '22 at 11:02
  • when the user clicks play it just runs the function player.play() – Mat Aug 15 '22 at 11:02
  • player: new Audio(), this.player.src = this.songs[this.songIndex].src; this.player.play(); – Mat Aug 15 '22 at 11:25
  • Did you checked the link I gave you? You can totally wire an event listener on it as shown in the documentation. – kissu Aug 15 '22 at 12:24
  • yes, I am trying to use the ontimeupdate() however I can't use out in an html element because I create it using js and im trying to use it in a watcher but it just gives an error when I try and do player.ontimeuodate. So idk how I would listen for that – Mat Aug 15 '22 at 12:33
  • `this.player.addEventListener('timeupdate', (event) => {` doesn't work? – kissu Aug 15 '22 at 12:38
  • no it throws an error on the . – Mat Aug 15 '22 at 12:43
  • Hm alright, a [repro] or more code would be highly welcome here. Because I'm pretty sure this may work. Otherwise, you can always use a `video` tag in the main file of your Vue app and hide it with CSS. – kissu Aug 15 '22 at 12:45
  • I added the actually slider but idk what else I could add without clogging the question up. I already have a player which is used for all my other fucntions so I would have to rewrite them if I changed it to a html element. Otherwise, the GitHub repo is here: https://github.com/Kroplewski-M/simple-music-app but idk is you want that, the slider is in the appPlayer.vue – Mat Aug 15 '22 at 12:54
  • somehow if I pause or change the volume the slider updates but not on its own – Mat Aug 15 '22 at 12:55
  • I had the.lazy before and it doesn't work for some reason I thought it would fix the problem but it didn't – Mat Aug 15 '22 at 13:05

1 Answers1

2

You have to listen to the timeupdate event. I made a simple sample code:

Output:

enter image description here

<template>
  <div style="border: 1px solid gray; border-radius: 5px; padding: 5px;">
    <div>
      <button @click="play">Play | Pause</button>
      {{ timeLabel }}
    </div>
    <div>
      <input
        type="range"
        :min="0"
        :max="duration"
        v-model="currentTime"
        @input="updateTime"
      >
    </div>
  </div>
</template>

<script>
export default {
  name: 'BaseAudioPlayerTest',

  data() {
    return {
      src: 'Spring-Flowers.mp3',
      player: null,
      duration: 0,
      currentTime: 0,
      timeLabel: '00:00:00',
    };
  },

  methods: {
    play() {
      if (this.player.paused) {
        this.player.play();
        this.duration = this.player.duration;
      } else {
        this.player.pause();
      }
    },
    updateTime() {
      this.player.currentTime = this.currentTime;
    },
    timeupdate() {
      this.currentTime = this.player.currentTime;
      const hr = Math.floor(this.currentTime / 3600);
      const min = Math.floor((this.currentTime - (hr * 3600)) / 60);
      const sec = Math.floor(this.currentTime - (hr * 3600) - (min * 60));
      this.timeLabel = `${hr.toString()
        .padStart(2, '0')}:${min.toString()
        .padStart(2, '0')}:${sec.toString()
        .padStart(2, '0')}`;
    },
  },

  mounted() {
    this.player = new Audio(this.src);
    this.player.addEventListener('timeupdate', this.timeupdate, false);
  },
};
</script>

You can find more info here.

Raeisi
  • 1,647
  • 1
  • 6
  • 18