Fixes the "next chapter" button in the in-app player not advancing when a chapter starts at a non-integer second (common with m4b files). The player would land just before the chapter boundary and subsequent presses wouldn't move at all.
Which issue is fixed?
n/a, discovered while testing a separate fix. Happy to file one first if preferred
Pull Request Type
Android native plugin plus JS frontend. iOS already accepted Double values through the seek path so no Swift changes were needed.
In-depth Description
The seek plugin truncated to integer seconds: AbsAudioPlayer.seek({ value: Math.floor(time) }) on the JS side, and call.getInt("value", 0) on the Android side. If a chapter started at 100.5s, Math.floor(100.5) = 100 was sent to native, which seeked to 100000ms.
That's still inside the previous chapter, which ends at 100500ms. Pressing next again produced the same result because nextChapter is computed by comparing against currentTime, and currentTime was still less than nextChapter.start.
Traced the Math.floor back to a 2022 commit that switched the plugin contract from a millisecond string to an integer-seconds value. The floor was defensive to match the new Int required value from Android, not a deliberate precision decision. iOS already accepted Double, so it had never suffered the truncation.
The fix drops the Math.floor in both JS callers of AbsAudioPlayer.seek and switches the Android plugin to read the value as a Double and convert to ms with full precision. seekForward and seekBackward are unchanged since their values are always integer-second jump intervals from device settings.
One minor side effect is that drag-to-seek on the timeline now lands exactly where you drop rather than at the floor of the nearest second. That's an improvement IMO, but also a tiny behavior shift, so flagging it here and it could potentially be worked around to stay as it was if that's preferred.
How have you tested this?
Tested by toggling on chapters in the player and using next/previous buttons
Screenshots
N/A
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.
## 📋 Pull Request Information
**Original PR:** https://github.com/advplyr/audiobookshelf-app/pull/1848
**Author:** [@Kyrluckechuck](https://github.com/Kyrluckechuck)
**Created:** 4/14/2026
**Status:** 🔄 Open
**Base:** `master` ← **Head:** `fix/seek-to-exact-time-rather-than-floored-second`
---
### 📝 Commits (1)
- [`d4e7d0a`](https://github.com/advplyr/audiobookshelf-app/commit/d4e7d0abf9d602c1187db271f9c3c561f8b1a8ae) Seek to millisecond rather than flooring to second
### 📊 Changes
**3 files changed** (+5 additions, -4 deletions)
<details>
<summary>View changed files</summary>
📝 `android/app/src/main/java/com/audiobookshelf/app/plugins/AbsAudioPlayer.kt` (+2 -2)
📝 `components/app/AudioPlayer.vue` (+2 -1)
📝 `components/app/AudioPlayerContainer.vue` (+1 -1)
</details>
### 📄 Description
## Brief summary
Fixes the "next chapter" button in the in-app player not advancing when a chapter starts at a non-integer second (common with m4b files). The player would land just before the chapter boundary and subsequent presses wouldn't move at all.
## Which issue is fixed?
n/a, discovered while testing a separate fix. Happy to file one first if preferred
## Pull Request Type
Android native plugin plus JS frontend. iOS already accepted Double values through the seek path so no Swift changes were needed.
## In-depth Description
The seek plugin truncated to integer seconds: `AbsAudioPlayer.seek({ value: Math.floor(time) })` on the JS side, and `call.getInt("value", 0)` on the Android side. If a chapter started at 100.5s, `Math.floor(100.5) = 100` was sent to native, which seeked to 100000ms.
That's still inside the previous chapter, which ends at 100500ms. Pressing next again produced the same result because `nextChapter` is computed by comparing against `currentTime`, and `currentTime` was still less than `nextChapter.start`.
Traced the Math.floor back to a 2022 commit that switched the plugin contract from a millisecond string to an integer-seconds value. The floor was defensive to match the new Int required value from Android, not a deliberate precision decision. iOS already accepted Double, so it had never suffered the truncation.
The fix drops the Math.floor in both JS callers of `AbsAudioPlayer.seek` and switches the Android plugin to read the value as a Double and convert to ms with full precision. `seekForward` and `seekBackward` are unchanged since their values are always integer-second jump intervals from device settings.
One minor side effect is that drag-to-seek on the timeline now lands exactly where you drop rather than at the floor of the nearest second. That's an improvement IMO, but also a tiny behavior shift, so flagging it here and it could potentially be worked around to stay as it was if that's preferred.
## How have you tested this?
- Tested by toggling on chapters in the player and using next/previous buttons
## Screenshots
- N/A
---
<sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
📋 Pull Request Information
Original PR: https://github.com/advplyr/audiobookshelf-app/pull/1848
Author: @Kyrluckechuck
Created: 4/14/2026
Status: 🔄 Open
Base:
master← Head:fix/seek-to-exact-time-rather-than-floored-second📝 Commits (1)
d4e7d0aSeek to millisecond rather than flooring to second📊 Changes
3 files changed (+5 additions, -4 deletions)
View changed files
📝
android/app/src/main/java/com/audiobookshelf/app/plugins/AbsAudioPlayer.kt(+2 -2)📝
components/app/AudioPlayer.vue(+2 -1)📝
components/app/AudioPlayerContainer.vue(+1 -1)📄 Description
Brief summary
Fixes the "next chapter" button in the in-app player not advancing when a chapter starts at a non-integer second (common with m4b files). The player would land just before the chapter boundary and subsequent presses wouldn't move at all.
Which issue is fixed?
n/a, discovered while testing a separate fix. Happy to file one first if preferred
Pull Request Type
Android native plugin plus JS frontend. iOS already accepted Double values through the seek path so no Swift changes were needed.
In-depth Description
The seek plugin truncated to integer seconds:
AbsAudioPlayer.seek({ value: Math.floor(time) })on the JS side, andcall.getInt("value", 0)on the Android side. If a chapter started at 100.5s,Math.floor(100.5) = 100was sent to native, which seeked to 100000ms.That's still inside the previous chapter, which ends at 100500ms. Pressing next again produced the same result because
nextChapteris computed by comparing againstcurrentTime, andcurrentTimewas still less thannextChapter.start.Traced the Math.floor back to a 2022 commit that switched the plugin contract from a millisecond string to an integer-seconds value. The floor was defensive to match the new Int required value from Android, not a deliberate precision decision. iOS already accepted Double, so it had never suffered the truncation.
The fix drops the Math.floor in both JS callers of
AbsAudioPlayer.seekand switches the Android plugin to read the value as a Double and convert to ms with full precision.seekForwardandseekBackwardare unchanged since their values are always integer-second jump intervals from device settings.One minor side effect is that drag-to-seek on the timeline now lands exactly where you drop rather than at the floor of the nearest second. That's an improvement IMO, but also a tiny behavior shift, so flagging it here and it could potentially be worked around to stay as it was if that's preferred.
How have you tested this?
Screenshots
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.