@@ -63,6 +69,12 @@ export default {
}
},
computed: {
+ isCasting() {
+ return this.$store.state.globals.isCasting || false
+ },
+ isSmartSpeedEnabled() {
+ return this.$store.getters['user/getUserSetting']('enableSmartSpeed') || false
+ },
_playbackRate() {
if (!this.playbackRate || isNaN(this.playbackRate)) return 1
return this.playbackRate
diff --git a/client/components/player/PlayerUi.vue b/client/components/player/PlayerUi.vue
index f929943c4..64fee1ad2 100644
--- a/client/components/player/PlayerUi.vue
+++ b/client/components/player/PlayerUi.vue
@@ -326,11 +326,22 @@ export default {
if (this.$refs.trackbar) this.$refs.trackbar.setUseChapterTrack(this.useChapterTrack)
this.setPlaybackRate(this.playbackRate)
+
+ const enableSmartSpeed = this.$store.getters['user/getUserSetting']('enableSmartSpeed')
+ const smartSpeedRatio = this.$store.getters['user/getUserSetting']('smartSpeedRatio')
+ if (this.playerHandler && this.playerHandler.isPlayingLocalItem) {
+ this.playerHandler.setSmartSpeed(enableSmartSpeed || false, smartSpeedRatio || 2.5)
+ }
},
settingsUpdated(settings) {
if (settings.playbackRate && this.playbackRate !== settings.playbackRate) {
this.setPlaybackRate(settings.playbackRate)
}
+ if (this.playerHandler && this.playerHandler.isPlayingLocalItem && (settings.enableSmartSpeed !== undefined || settings.smartSpeedRatio !== undefined)) {
+ const enableSmartSpeed = settings.enableSmartSpeed !== undefined ? settings.enableSmartSpeed : this.$store.getters['user/getUserSetting']('enableSmartSpeed')
+ const smartSpeedRatio = settings.smartSpeedRatio !== undefined ? settings.smartSpeedRatio : this.$store.getters['user/getUserSetting']('smartSpeedRatio')
+ this.playerHandler.setSmartSpeed(enableSmartSpeed || false, smartSpeedRatio || 2.5)
+ }
},
closePlayer() {
if (this.isFullscreen) {
diff --git a/client/players/PlayerHandler.js b/client/players/PlayerHandler.js
index 5c5f281f6..37a72cb15 100644
--- a/client/players/PlayerHandler.js
+++ b/client/players/PlayerHandler.js
@@ -383,6 +383,13 @@ export default class PlayerHandler {
this.player.setPlaybackRate(playbackRate)
}
+ setSmartSpeed(enabled, ratio = 2.5) {
+ if (this.player && this.player instanceof LocalAudioPlayer) {
+ this.player.smartSpeedRatio = ratio
+ this.player.setSmartSpeed(enabled)
+ }
+ }
+
seek(time, shouldSync = true) {
if (!this.player) return
this.player.seek(time, this.playerPlaying)
diff --git a/client/store/user.js b/client/store/user.js
index 368bd8a41..12f8d8be3 100644
--- a/client/store/user.js
+++ b/client/store/user.js
@@ -19,7 +19,8 @@ export const state = () => ({
authorSortDesc: false,
jumpForwardAmount: 10,
jumpBackwardAmount: 10,
- enableSmartSpeed: false
+ enableSmartSpeed: false,
+ smartSpeedRatio: 2.5
}
})
@@ -200,5 +201,17 @@ export const mutations = {
if (!settings) return
localStorage.setItem('userSettings', JSON.stringify(settings))
state.settings = settings
+ },
+ SET_SMART_SPEED_ENABLED(state, enabled) {
+ state.settings.enableSmartSpeed = enabled !== undefined ? enabled : !state.settings.enableSmartSpeed
+ localStorage.setItem('userSettings', JSON.stringify(state.settings))
+ },
+ SET_SMART_SPEED_RATIO(state, ratio) {
+ let clampedRatio = Number(ratio)
+ if (isNaN(clampedRatio)) clampedRatio = 2.5
+ if (clampedRatio < 1.5) clampedRatio = 1.5
+ if (clampedRatio > 5.0) clampedRatio = 5.0
+ state.settings.smartSpeedRatio = clampedRatio
+ localStorage.setItem('userSettings', JSON.stringify(state.settings))
}
}
diff --git a/client/strings/en-us.json b/client/strings/en-us.json
index fb2bcb281..34d361a9c 100644
--- a/client/strings/en-us.json
+++ b/client/strings/en-us.json
@@ -712,6 +712,8 @@
"LabelUploaderItemFetchMetadataHelp": "Automatically fetch title, author, and series",
"LabelUseAdvancedOptions": "Use Advanced Options",
"LabelUseChapterTrack": "Use chapter track",
+ "LabelEnableSmartSpeed": "Enable Smart Speed",
+ "LabelSmartSpeedRatio": "Smart Speed Compression Ratio",
"LabelUseFullTrack": "Use full track",
"LabelUseZeroForUnlimited": "Use 0 for unlimited",
"LabelUser": "User",
diff --git a/test/client/store/user.test.js b/test/client/store/user.test.js
new file mode 100644
index 000000000..d97841502
--- /dev/null
+++ b/test/client/store/user.test.js
@@ -0,0 +1,65 @@
+import { state, mutations } from '../../../client/store/user.js'
+import { expect } from 'chai'
+
+describe('User Store Mutations', () => {
+ let mockState
+
+ beforeEach(() => {
+ mockState = state()
+ // Mock localStorage
+ global.localStorage = {
+ store: {},
+ getItem(key) {
+ return this.store[key] || null
+ },
+ setItem(key, value) {
+ this.store[key] = value
+ },
+ removeItem(key) {
+ delete this.store[key]
+ }
+ }
+ })
+
+ it('Default state has enableSmartSpeed = false', () => {
+ expect(mockState.settings.enableSmartSpeed).to.be.false
+ })
+
+ it('Default state has smartSpeedRatio = 2.5', () => {
+ expect(mockState.settings.smartSpeedRatio).to.equal(2.5)
+ })
+
+ it('SET_SMART_SPEED_ENABLED mutation toggles the value', () => {
+ mutations.SET_SMART_SPEED_ENABLED(mockState)
+ expect(mockState.settings.enableSmartSpeed).to.be.true
+ mutations.SET_SMART_SPEED_ENABLED(mockState)
+ expect(mockState.settings.enableSmartSpeed).to.be.false
+
+ // Check setting explicitly
+ mutations.SET_SMART_SPEED_ENABLED(mockState, true)
+ expect(mockState.settings.enableSmartSpeed).to.be.true
+ })
+
+ it('SET_SMART_SPEED_RATIO mutation sets the value', () => {
+ mutations.SET_SMART_SPEED_RATIO(mockState, 3.0)
+ expect(mockState.settings.smartSpeedRatio).to.equal(3.0)
+ })
+
+ it('Ratio is clamped to valid range [1.5, 5.0]', () => {
+ mutations.SET_SMART_SPEED_RATIO(mockState, 1.0)
+ expect(mockState.settings.smartSpeedRatio).to.equal(1.5)
+
+ mutations.SET_SMART_SPEED_RATIO(mockState, 6.0)
+ expect(mockState.settings.smartSpeedRatio).to.equal(5.0)
+ })
+
+ it('Settings persist to localStorage', () => {
+ mutations.SET_SMART_SPEED_ENABLED(mockState, true)
+ let savedSettings = JSON.parse(localStorage.getItem('userSettings'))
+ expect(savedSettings.enableSmartSpeed).to.be.true
+
+ mutations.SET_SMART_SPEED_RATIO(mockState, 4.0)
+ savedSettings = JSON.parse(localStorage.getItem('userSettings'))
+ expect(savedSettings.smartSpeedRatio).to.equal(4.0)
+ })
+})