diff --git a/server/objects/Stream.js b/server/objects/Stream.js index 288f51d4..59597369 100644 --- a/server/objects/Stream.js +++ b/server/objects/Stream.js @@ -16,6 +16,7 @@ class Stream extends EventEmitter { this.audiobook = audiobook this.segmentLength = 6 + this.maxSeekBackTime = 30 this.streamPath = Path.join(streamPath, this.id) this.concatFilesPath = Path.join(this.streamPath, 'files.txt') this.playlistPath = Path.join(this.streamPath, 'output.m3u8') @@ -67,7 +68,7 @@ class Stream extends EventEmitter { get segmentStartNumber() { if (!this.startTime) return 0 - return Math.floor(this.startTime / this.segmentLength) + return Math.floor(Math.max(this.startTime - this.maxSeekBackTime, 0) / this.segmentLength) } get numSegments() { @@ -82,6 +83,18 @@ class Stream extends EventEmitter { return this.audiobook.tracks } + get clientUser() { + return this.client.user || {} + } + + get clientUserAudiobooks() { + return this.clientUser.audiobooks || {} + } + + get clientUserAudiobookData() { + return this.clientUserAudiobooks[this.audiobookId] + } + get clientPlaylistUri() { return `/hls/${this.id}/output.m3u8` } @@ -104,18 +117,17 @@ class Stream extends EventEmitter { clientCurrentTime: this.clientCurrentTime, startTime: this.startTime, segmentStartNumber: this.segmentStartNumber, - isTranscodeComplete: this.isTranscodeComplete + isTranscodeComplete: this.isTranscodeComplete, + lastUpdate: this.clientUserAudiobookData ? this.clientUserAudiobookData.lastUpdate : 0 } } init() { - var clientUserAudiobooks = this.client.user ? this.client.user.audiobooks || {} : {} - var userAudiobook = clientUserAudiobooks[this.audiobookId] || null - if (userAudiobook) { - var timeRemaining = this.totalDuration - userAudiobook.currentTime - Logger.info('[STREAM] User has progress for audiobook', userAudiobook.progress, `Time Remaining: ${timeRemaining}s`) + if (this.clientUserAudiobookData) { + var timeRemaining = this.totalDuration - this.clientUserAudiobookData.currentTime + Logger.info('[STREAM] User has progress for audiobook', this.clientUserAudiobookData.progress, `Time Remaining: ${timeRemaining}s`) if (timeRemaining > 15) { - this.startTime = userAudiobook.currentTime + this.startTime = this.clientUserAudiobookData.currentTime this.clientCurrentTime = this.startTime } } @@ -239,22 +251,22 @@ class Stream extends EventEmitter { this.ffmpeg = Ffmpeg() - var trackStartTime = await writeConcatFile(this.tracks, this.concatFilesPath, this.startTime) + var adjustedStartTime = Math.max(this.startTime - this.maxSeekBackTime, 0) + var trackStartTime = await writeConcatFile(this.tracks, this.concatFilesPath, adjustedStartTime) this.ffmpeg.addInput(this.concatFilesPath) // seek_timestamp : https://ffmpeg.org/ffmpeg.html // the argument to the -ss option is considered an actual timestamp, and is not offset by the start time of the file - // note: this may result in the same thing as output seeking, fixes https://github.com/advplyr/audiobookshelf/issues/116 + // fixes https://github.com/advplyr/audiobookshelf/issues/116 this.ffmpeg.inputOption('-seek_timestamp 1') this.ffmpeg.inputFormat('concat') this.ffmpeg.inputOption('-safe 0') - // this.ffmpeg.inputOption('-segment_time_metadata 1') - if (this.startTime > 0) { - const shiftedStartTime = this.startTime - trackStartTime + if (adjustedStartTime > 0) { + const shiftedStartTime = adjustedStartTime - trackStartTime // Issues using exact fractional seconds i.e. 29.49814 - changing to 29.5s var startTimeS = Math.round(shiftedStartTime * 10) / 10 + 's' - Logger.info(`[STREAM] Starting Stream at startTime ${secondsToTimestamp(this.startTime)} and Segment #${this.segmentStartNumber}`) + Logger.info(`[STREAM] Starting Stream at startTime ${secondsToTimestamp(adjustedStartTime)} (User startTime ${secondsToTimestamp(this.startTime)}) and Segment #${this.segmentStartNumber}`) this.ffmpeg.inputOption(`-ss ${startTimeS}`) this.ffmpeg.inputOption('-noaccurate_seek')