mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Update:Adjust timestamps in player for playback speed #1647
This commit is contained in:
		
							parent
							
								
									042c89039c
								
							
						
					
					
						commit
						a59311f795
					
				@ -81,7 +81,7 @@ export default {
 | 
			
		||||
      sleepTimerRemaining: 0,
 | 
			
		||||
      sleepTimer: null,
 | 
			
		||||
      displayTitle: null,
 | 
			
		||||
      initialPlaybackRate: 1,
 | 
			
		||||
      currentPlaybackRate: 1,
 | 
			
		||||
      syncFailedToast: null
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
@ -152,7 +152,8 @@ export default {
 | 
			
		||||
      return this.streamLibraryItem ? this.streamLibraryItem.libraryId : null
 | 
			
		||||
    },
 | 
			
		||||
    totalDurationPretty() {
 | 
			
		||||
      return this.$secondsToTimestamp(this.totalDuration)
 | 
			
		||||
      // Adjusted by playback rate
 | 
			
		||||
      return this.$secondsToTimestamp(this.totalDuration / this.currentPlaybackRate)
 | 
			
		||||
    },
 | 
			
		||||
    podcastAuthor() {
 | 
			
		||||
      if (!this.isPodcast) return null
 | 
			
		||||
@ -255,7 +256,7 @@ export default {
 | 
			
		||||
      this.playerHandler.setVolume(volume)
 | 
			
		||||
    },
 | 
			
		||||
    setPlaybackRate(playbackRate) {
 | 
			
		||||
      this.initialPlaybackRate = playbackRate
 | 
			
		||||
      this.currentPlaybackRate = playbackRate
 | 
			
		||||
      this.playerHandler.setPlaybackRate(playbackRate)
 | 
			
		||||
    },
 | 
			
		||||
    seek(time) {
 | 
			
		||||
@ -384,7 +385,7 @@ export default {
 | 
			
		||||
        libraryItem: session.libraryItem,
 | 
			
		||||
        episodeId: session.episodeId
 | 
			
		||||
      })
 | 
			
		||||
      this.playerHandler.prepareOpenSession(session, this.initialPlaybackRate)
 | 
			
		||||
      this.playerHandler.prepareOpenSession(session, this.currentPlaybackRate)
 | 
			
		||||
    },
 | 
			
		||||
    streamOpen(session) {
 | 
			
		||||
      console.log(`[StreamContainer] Stream session open`, session)
 | 
			
		||||
@ -451,7 +452,7 @@ export default {
 | 
			
		||||
        if (this.$refs.audioPlayer) this.$refs.audioPlayer.checkUpdateChapterTrack()
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      this.playerHandler.load(libraryItem, episodeId, true, this.initialPlaybackRate, payload.startTime)
 | 
			
		||||
      this.playerHandler.load(libraryItem, episodeId, true, this.currentPlaybackRate, payload.startTime)
 | 
			
		||||
    },
 | 
			
		||||
    pauseItem() {
 | 
			
		||||
      this.playerHandler.pause()
 | 
			
		||||
 | 
			
		||||
@ -2,13 +2,13 @@
 | 
			
		||||
  <modals-modal v-model="show" name="chapters" :width="600" :height="'unset'">
 | 
			
		||||
    <div id="chapter-modal-wrapper" ref="container" class="w-full rounded-lg bg-primary box-shadow-md overflow-y-auto overflow-x-hidden" style="max-height: 80vh">
 | 
			
		||||
      <template v-for="chap in chapters">
 | 
			
		||||
        <div :key="chap.id" :id="`chapter-row-${chap.id}`" class="flex items-center px-6 py-3 justify-start cursor-pointer hover:bg-bg relative" :class="chap.id === currentChapterId ? 'bg-yellow-400 bg-opacity-10' : chap.end <= currentChapterStart ? 'bg-success bg-opacity-5' : 'bg-opacity-20'" @click="clickChapter(chap)">
 | 
			
		||||
        <div :key="chap.id" :id="`chapter-row-${chap.id}`" class="flex items-center px-6 py-3 justify-start cursor-pointer hover:bg-bg relative" :class="chap.id === currentChapterId ? 'bg-yellow-400 bg-opacity-10' : chap.end / _playbackRate <= currentChapterStart ? 'bg-success bg-opacity-5' : 'bg-opacity-20'" @click="clickChapter(chap)">
 | 
			
		||||
          <p class="chapter-title truncate text-sm md:text-base">
 | 
			
		||||
            {{ chap.title }}
 | 
			
		||||
          </p>
 | 
			
		||||
          <span class="font-mono text-xxs sm:text-xs text-gray-400 pl-2 whitespace-nowrap">{{ $elapsedPrettyExtended(chap.end - chap.start) }}</span>
 | 
			
		||||
          <span class="font-mono text-xxs sm:text-xs text-gray-400 pl-2 whitespace-nowrap">{{ $elapsedPrettyExtended((chap.end - chap.start) / _playbackRate) }}</span>
 | 
			
		||||
          <span class="flex-grow" />
 | 
			
		||||
          <span class="font-mono text-xs sm:text-sm text-gray-300">{{ $secondsToTimestamp(chap.start) }}</span>
 | 
			
		||||
          <span class="font-mono text-xs sm:text-sm text-gray-300">{{ $secondsToTimestamp(chap.start / _playbackRate) }}</span>
 | 
			
		||||
 | 
			
		||||
          <div v-show="chap.id === currentChapterId" class="w-0.5 h-full absolute top-0 left-0 bg-yellow-400" />
 | 
			
		||||
        </div>
 | 
			
		||||
@ -28,7 +28,8 @@ export default {
 | 
			
		||||
    currentChapter: {
 | 
			
		||||
      type: Object,
 | 
			
		||||
      default: () => null
 | 
			
		||||
    }
 | 
			
		||||
    },
 | 
			
		||||
    playbackRate: Number
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {}
 | 
			
		||||
@ -47,11 +48,15 @@ export default {
 | 
			
		||||
        this.$emit('input', val)
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    _playbackRate() {
 | 
			
		||||
      if (!this.playbackRate || isNaN(this.playbackRate)) return 1
 | 
			
		||||
      return this.playbackRate
 | 
			
		||||
    },
 | 
			
		||||
    currentChapterId() {
 | 
			
		||||
      return this.currentChapter ? this.currentChapter.id : null
 | 
			
		||||
    },
 | 
			
		||||
    currentChapterStart() {
 | 
			
		||||
      return this.currentChapter ? this.currentChapter.start : 0
 | 
			
		||||
      return (this.currentChapter?.start || 0) / this._playbackRate
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
@ -61,13 +66,11 @@ export default {
 | 
			
		||||
    scrollToChapter() {
 | 
			
		||||
      if (!this.currentChapterId) return
 | 
			
		||||
 | 
			
		||||
      var container = this.$refs.container
 | 
			
		||||
      if (container) {
 | 
			
		||||
        var currChapterEl = document.getElementById(`chapter-row-${this.currentChapterId}`)
 | 
			
		||||
      if (this.$refs.container) {
 | 
			
		||||
        const currChapterEl = document.getElementById(`chapter-row-${this.currentChapterId}`)
 | 
			
		||||
        if (currChapterEl) {
 | 
			
		||||
          var offsetTop = currChapterEl.offsetTop
 | 
			
		||||
          var containerHeight = container.clientHeight
 | 
			
		||||
          container.scrollTo({ top: offsetTop - containerHeight / 2 })
 | 
			
		||||
          const containerHeight = this.$refs.container.clientHeight
 | 
			
		||||
          this.$refs.container.scrollTo({ top: currChapterEl.offsetTop - containerHeight / 2 })
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -38,7 +38,8 @@ export default {
 | 
			
		||||
    currentChapter: {
 | 
			
		||||
      type: Object,
 | 
			
		||||
      default: () => {}
 | 
			
		||||
    }
 | 
			
		||||
    },
 | 
			
		||||
    playbackRate: Number
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
@ -63,6 +64,10 @@ export default {
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
    _playbackRate() {
 | 
			
		||||
      if (!this.playbackRate || isNaN(this.playbackRate)) return 1
 | 
			
		||||
      return this.playbackRate
 | 
			
		||||
    },
 | 
			
		||||
    currentChapterDuration() {
 | 
			
		||||
      if (!this.currentChapter) return 0
 | 
			
		||||
      return this.currentChapter.end - this.currentChapter.start
 | 
			
		||||
@ -81,8 +86,8 @@ export default {
 | 
			
		||||
    clickTrack(e) {
 | 
			
		||||
      if (this.loading) return
 | 
			
		||||
 | 
			
		||||
      var offsetX = e.offsetX
 | 
			
		||||
      var perc = offsetX / this.trackWidth
 | 
			
		||||
      const offsetX = e.offsetX
 | 
			
		||||
      const perc = offsetX / this.trackWidth
 | 
			
		||||
      const baseTime = this.useChapterTrack ? this.currentChapterStart : 0
 | 
			
		||||
      const duration = this.useChapterTrack ? this.currentChapterDuration : this.duration
 | 
			
		||||
      const time = baseTime + perc * duration
 | 
			
		||||
@ -111,7 +116,7 @@ export default {
 | 
			
		||||
      this.updateReadyTrack()
 | 
			
		||||
    },
 | 
			
		||||
    updateReadyTrack() {
 | 
			
		||||
      var widthReady = Math.round(this.trackWidth * this.percentReady)
 | 
			
		||||
      const widthReady = Math.round(this.trackWidth * this.percentReady)
 | 
			
		||||
      if (this.readyTrackWidth === widthReady) return
 | 
			
		||||
      this.readyTrackWidth = widthReady
 | 
			
		||||
      if (this.$refs.readyTrack) this.$refs.readyTrack.style.width = widthReady + 'px'
 | 
			
		||||
@ -124,7 +129,7 @@ export default {
 | 
			
		||||
      const time = this.useChapterTrack ? Math.max(0, this.currentTime - this.currentChapterStart) : this.currentTime
 | 
			
		||||
      const duration = this.useChapterTrack ? this.currentChapterDuration : this.duration
 | 
			
		||||
 | 
			
		||||
      var ptWidth = Math.round((time / duration) * this.trackWidth)
 | 
			
		||||
      const ptWidth = Math.round((time / duration) * this.trackWidth)
 | 
			
		||||
      if (this.playedTrackWidth === ptWidth) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
@ -133,7 +138,7 @@ export default {
 | 
			
		||||
    },
 | 
			
		||||
    setChapterTicks() {
 | 
			
		||||
      this.chapterTicks = this.chapters.map((chap) => {
 | 
			
		||||
        var perc = chap.start / this.duration
 | 
			
		||||
        const perc = chap.start / this.duration
 | 
			
		||||
        return {
 | 
			
		||||
          title: chap.title,
 | 
			
		||||
          left: perc * this.trackWidth
 | 
			
		||||
@ -141,7 +146,7 @@ export default {
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    mousemoveTrack(e) {
 | 
			
		||||
      var offsetX = e.offsetX
 | 
			
		||||
      const offsetX = e.offsetX
 | 
			
		||||
 | 
			
		||||
      const baseTime = this.useChapterTrack ? this.currentChapterStart : 0
 | 
			
		||||
      const duration = this.useChapterTrack ? this.currentChapterDuration : this.duration
 | 
			
		||||
@ -167,7 +172,7 @@ export default {
 | 
			
		||||
        this.$refs.hoverTimestampArrow.style.left = posLeft + 'px'
 | 
			
		||||
      }
 | 
			
		||||
      if (this.$refs.hoverTimestampText) {
 | 
			
		||||
        var hoverText = this.$secondsToTimestamp(progressTime)
 | 
			
		||||
        var hoverText = this.$secondsToTimestamp(progressTime / this._playbackRate)
 | 
			
		||||
 | 
			
		||||
        var chapter = this.chapters.find((chapter) => chapter.start <= totalTime && totalTime < chapter.end)
 | 
			
		||||
        if (chapter && chapter.title) {
 | 
			
		||||
 | 
			
		||||
@ -46,7 +46,7 @@
 | 
			
		||||
      <player-playback-controls :loading="loading" :seek-loading="seekLoading" :playback-rate.sync="playbackRate" :paused="paused" :has-next-chapter="hasNextChapter" @prevChapter="prevChapter" @nextChapter="nextChapter" @jumpForward="jumpForward" @jumpBackward="jumpBackward" @setPlaybackRate="setPlaybackRate" @playPause="playPause" />
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <player-track-bar ref="trackbar" :loading="loading" :chapters="chapters" :duration="duration" :current-chapter="currentChapter" @seek="seek" />
 | 
			
		||||
    <player-track-bar ref="trackbar" :loading="loading" :chapters="chapters" :duration="duration" :current-chapter="currentChapter" :playback-rate="playbackRate" @seek="seek" />
 | 
			
		||||
 | 
			
		||||
    <div class="flex">
 | 
			
		||||
      <p ref="currentTimestamp" class="font-mono text-xxs sm:text-sm text-gray-100 pointer-events-auto">00:00:00</p>
 | 
			
		||||
@ -59,7 +59,7 @@
 | 
			
		||||
      <p class="font-mono text-xxs sm:text-sm text-gray-100 pointer-events-auto">{{ timeRemainingPretty }}</p>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <modals-chapters-modal v-model="showChaptersModal" :current-chapter="currentChapter" :chapters="chapters" @select="selectChapter" />
 | 
			
		||||
    <modals-chapters-modal v-model="showChaptersModal" :current-chapter="currentChapter" :playback-rate="playbackRate" :chapters="chapters" @select="selectChapter" />
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
@ -92,6 +92,11 @@ export default {
 | 
			
		||||
      useChapterTrack: false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  watch: {
 | 
			
		||||
    playbackRate() {
 | 
			
		||||
      this.updateTimestamp()
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  computed: {
 | 
			
		||||
    sleepTimerRemainingString() {
 | 
			
		||||
      var rounded = Math.round(this.sleepTimerRemaining)
 | 
			
		||||
@ -289,14 +294,13 @@ export default {
 | 
			
		||||
      if (this.$refs.trackbar) this.$refs.trackbar.setPercentageReady(percentageReady)
 | 
			
		||||
    },
 | 
			
		||||
    updateTimestamp() {
 | 
			
		||||
      var ts = this.$refs.currentTimestamp
 | 
			
		||||
      const ts = this.$refs.currentTimestamp
 | 
			
		||||
      if (!ts) {
 | 
			
		||||
        console.error('No timestamp el')
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
      const time = this.useChapterTrack ? Math.max(0, this.currentTime - this.currentChapterStart) : this.currentTime
 | 
			
		||||
      var currTimeClean = this.$secondsToTimestamp(time)
 | 
			
		||||
      ts.innerText = currTimeClean
 | 
			
		||||
      ts.innerText = this.$secondsToTimestamp(time / this.playbackRate)
 | 
			
		||||
    },
 | 
			
		||||
    setBufferTime(bufferTime) {
 | 
			
		||||
      if (this.$refs.trackbar) this.$refs.trackbar.setBufferTime(bufferTime)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user