progress skipping backwards after open the main app while playing
I have been tracking "play in stream mode, progress skipping backwards" issue for some time.
According to my test, there are 2 conditions.
1.
The first one is pressing the system backButton, the log shows "App destroyed", in this condition, only player is running, progress can not sync to server.
Another one is more subtle, maybe caused by my os I think. My os is MIUI12.5 (Android 11). When the screen locked and play audiobooks in stream mode for a period of time, it seems that the app will be hibernated by the os.
According to the log, the app can sync CurrentTime to server at the beginning. But the playInterval will stop after about 10 minutes.
Of course, we can the listening for the backButton and disable the default behaviour in the 1st condition, but I think it is not necessary to.
My methods is when the app runs again, read status and data from the player, and restore these data to the app after some processing. Such as do not initPlayer if the audiobook is the same one and the player is in playing.
I have been testing this code for a while, it worked fine.
other improvements
fix bug: player init cause stream retranscoding
The init progress is call mPlayer.setMediaSource() and prepare() first, when the state turns to READY, then call seekTo() to jump to the startTime. That will call the server for the file output-0.ts.
add auto seekback
I mentioned this in #12, when playing the paused audiobook again, seekback a bit of time can help user recall where they were last stopped.
There are 2 conditions too:
One is the player is still running, and no audiobook switch. The seekback is handled by the player which record the pauseTime when paused and calc seekback time when start to play.
Another one is switch audiobook or restart the app (player). Becase there is no data for the player to calc, so there need help from the server. We need the lastUpdate time of the audiobook, use it as the last paused time. The seekback is handled in the app, before player init.
And there is another problem, the seekback may cause stream retranscoding in the same way. So the server should transcode a little more befroe the clientCurrentTime at the beginning.
I will open a pull request to the server code at the same time.
We can discuss whether there is a more suitable solution.
🔄 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/18
**Author:** [@svdztn](https://github.com/svdztn)
**Created:** 10/26/2021
**Status:** ✅ Merged
**Merged:** 10/26/2021
**Merged by:** [@advplyr](https://github.com/advplyr)
**Base:** `master` ← **Head:** `stream-sync`
---
### 📝 Commits (7)
- [`44a782b`](https://github.com/advplyr/audiobookshelf-app/commit/44a782b6591be4b3212086405ef814740ddc403e) restore from App “stop" & "destroyed", get data from player, avoid progress loss
- [`1a86621`](https://github.com/advplyr/audiobookshelf-app/commit/1a866210a28ffa6e2fda1acd28168b284a1ca0b2) native plugin: add getStreamSyncData()
- [`be02219`](https://github.com/advplyr/audiobookshelf-app/commit/be02219f1a6ad6004fb3b42d2209d738ca827edd) native plugin: change setMediaSource() to the api with startPositionMs, avoid call output-0.ts (will cause server retranscoding)
- [`81316c7`](https://github.com/advplyr/audiobookshelf-app/commit/81316c73c8c255c4fa8f57aa8eb123e789ecf9ef) add auto seekback
- [`9a684aa`](https://github.com/advplyr/audiobookshelf-app/commit/9a684aa8404995ba299b00fd05b7717a69e7851c) Merge branch 'advplyr:master' into stream-sync
- [`a08b09f`](https://github.com/advplyr/audiobookshelf-app/commit/a08b09f9a9c7a203ac8c9187f4fd4a0679ad9bbf) del debug log
- [`2ba41fe`](https://github.com/advplyr/audiobookshelf-app/commit/2ba41fe47cd990a70da0234f45d514dbf3975fee) fix min pause time to 3000 ms
### 📊 Changes
**4 files changed** (+120 additions, -15 deletions)
<details>
<summary>View changed files</summary>
📝 `android/app/src/main/java/com/audiobookshelf/app/MyNativeAudio.kt` (+20 -0)
📝 `android/app/src/main/java/com/audiobookshelf/app/PlayerNotificationService.kt` (+41 -3)
📝 `components/AudioPlayerMini.vue` (+54 -8)
📝 `components/app/StreamContainer.vue` (+5 -4)
</details>
### 📄 Description
## progress skipping backwards after open the main app while playing
I have been tracking "play in stream mode, progress skipping backwards" issue for some time.
According to my test, there are 2 conditions.
### 1.
The first one is pressing the system backButton, the log shows "App destroyed", in this condition, only player is running, progress can not sync to server.
```
D/Capacitor: App paused
D/Capacitor: App stopped
D/Capacitor: App destroyed
```
### 2.
Another one is more subtle, maybe caused by my os I think. My os is MIUI12.5 (Android 11). When the screen locked and play audiobooks in stream mode for a period of time, it seems that the app will be hibernated by the os.
According to the log, the app can sync `CurrentTime` to server at the beginning. But the `playInterval` will stop after about 10 minutes.
```
D/Capacitor: App paused
D/Capacitor: App stopped
D/Capacitor: Saving instance state!
D/PlayerService: EVENT IS PLAYING CHANGED
V/Capacitor/MyNativeAudio: Notifying listeners for event onPlayingUpdate
D/PlayerService: GET SUPORTED ACITONS
D/PlayerService: Notification Posted 10 - Start Foreground | Notification(channel=audiobookshelf_channel shortcut=null contentView=null vibrate=null sound=null defaults=0x0 flags=0xa color=0x00000000 category=transport actions=3 vis=PUBLIC)
D/AudioTrack: getTimestamp_l(3551): device stall time corrected using current time 446958880756319
D/AudioTrack: getTimestamp_l(3551): stale timestamp time corrected, currentTimeNanos: 446953808877988 < limitNs: 446958782885798 < mStartNs: 446958862885798
W/AudioTrack: getTimestamp_l(3551): retrograde timestamp time corrected, 446958782885798 < 446959084843455
D/BufferPoolAccessor2.0: bufferpool2 0xb4000078dd006428 : 4(32768 size) total buffers - 4(32768 size) used buffers - 0/5 (recycle/alloc) - 25/16321 (fetch/transfer)
V/Capacitor/Plugin: To native (Capacitor plugin): callbackId: 65265582, pluginId: MyNativeAudio, methodName: getCurrentTime
V/Capacitor: callback: 65265582, pluginId: MyNativeAudio, methodName: getCurrentTime, methodData: {}
D/MyNativeAudio: Get Current Time 233569
V/Capacitor/Plugin: To native (Capacitor plugin): callbackId: 65265583, pluginId: MyNativeAudio, methodName: getCurrentTime
V/Capacitor: callback: 65265583, pluginId: MyNativeAudio, methodName: getCurrentTime, methodData: {}
D/MyNativeAudio: Get Current Time 234571
V/Capacitor/Plugin: To native (Capacitor plugin): callbackId: 65265584, pluginId: MyNativeAudio, methodName: getCurrentTime
V/Capacitor: callback: 65265584, pluginId: MyNativeAudio, methodName: getCurrentTime, methodData: {}
D/MyNativeAudio: Get Current Time 235572
D/CCodecBufferChannel: [c2.android.mp3.decoder#87] DEBUG: elapsed: n=4 [in=0 pipeline=0 out=0 smoothness=4]
D/PipelineWatcher: DEBUG: elapsed 0 / 4
...
V/Capacitor/Plugin: To native (Capacitor plugin): callbackId: 65265874, pluginId: MyNativeAudio, methodName: getCurrentTime
V/Capacitor: callback: 65265874, pluginId: MyNativeAudio, methodName: getCurrentTime, methodData: {}
D/MyNativeAudio: Get Current Time 525525
D/BufferPoolAccessor2.0: bufferpool2 0xb4000078dd006428 : 4(32768 size) total buffers - 4(32768 size) used buffers - 0/5 (recycle/alloc) - 28/38763 (fetch/transfer)
D/PlayerService: EVENT_IS_LOADING_CHANGED : true
D/CCodecBufferChannel: [c2.android.mp3.decoder#87] DEBUG: elapsed: n=4 [in=0 pipeline=0 out=0 smoothness=4]
D/PipelineWatcher: DEBUG: elapsed 0 / 4
D/PlayerService: EVENT_IS_LOADING_CHANGED : false
V/Capacitor/Plugin: To native (Capacitor plugin): callbackId: 65265875, pluginId: MyNativeAudio, methodName: getCurrentTime
V/Capacitor: callback: 65265875, pluginId: MyNativeAudio, methodName: getCurrentTime, methodData: {}
D/MyNativeAudio: Get Current Time 526526
D/CCodecBufferChannel: [c2.android.mp3.decoder#87] DEBUG: elapsed: n=4 [in=0 pipeline=0 out=0 smoothness=4]
D/PipelineWatcher: DEBUG: elapsed 0 / 4
D/BufferPoolAccessor2.0: bufferpool2 0xb4000078dd006428 : 4(32768 size) total buffers - 4(32768 size) used buffers - 0/5 (recycle/alloc) - 28/39165 (fetch/transfer)
D/PlayerService: EVENT_IS_LOADING_CHANGED : true
D/PlayerService: EVENT_IS_LOADING_CHANGED : false
D/CCodecBufferChannel: [c2.android.mp3.decoder#87] DEBUG: elapsed: n=4 [in=0 pipeline=0 out=0 smoothness=4]
D/PipelineWatcher: DEBUG: elapsed 0 / 4
D/BufferPoolAccessor2.0: bufferpool2 0xb4000078dd006428 : 4(32768 size) total buffers - 4(32768 size) used buffers - 0/5 (recycle/alloc) - 28/39567 (fetch/transfer)
D/CCodecBufferChannel: [c2.android.mp3.decoder#87] DEBUG: elapsed: n=4 [in=0 pipeline=0 out=0 smoothness=4]
D/PipelineWatcher: DEBUG: elapsed 0 / 4
D/PlayerService: EVENT_IS_LOADING_CHANGED : true
D/PlayerService: EVENT_IS_LOADING_CHANGED : false
D/CCodecBufferChannel: [c2.android.mp3.decoder#87] DEBUG: elapsed: n=4 [in=0 pipeline=0 out=0 smoothness=4]
D/PipelineWatcher: DEBUG: elapsed 0 / 4
D/BufferPoolAccessor2.0: bufferpool2 0xb4000078dd006428 : 4(32768 size) total buffers - 4(32768 size) used buffers - 0/5 (recycle/alloc) - 28/39967 (fetch/transfer)
D/CCodecBufferChannel: [c2.android.mp3.decoder#87] DEBUG: elapsed: n=4 [in=0 pipeline=0 out=0 smoothness=4]
D/PipelineWatcher: DEBUG: elapsed 0 / 4
D/PlayerService: EVENT_IS_LOADING_CHANGED : true
D/PlayerService: EVENT_IS_LOADING_CHANGED : false
```
> Of course, we can the listening for the backButton and disable the default behaviour in the 1st condition, but I think it is not necessary to.
My methods is when the app runs again, read status and data from the player, and restore these data to the app after some processing. Such as do not initPlayer if the audiobook is the same one and the player is in playing.
I have been testing this code for a while, it worked fine.
## other improvements
### fix bug: player init cause stream retranscoding
The init progress is call `mPlayer.setMediaSource()` and `prepare()` first, when the state turns to `READY`, then call `seekTo()` to jump to the startTime. That will call the server for the file `output-0.ts`.
### add auto seekback
I mentioned this in #12, when playing the paused audiobook again, seekback a bit of time can help user recall where they were last stopped.
There are 2 conditions too:
One is the player is still running, and no audiobook switch. The `seekback` is handled by the player which record the pauseTime when paused and calc `seekback` time when start to play.
Another one is switch audiobook or restart the app (player). Becase there is no data for the player to calc, so there need help from the server. We need the `lastUpdate time` of the audiobook, use it as the last paused time. The `seekback` is handled in the app, before player init.
And there is another problem, the `seekback` may cause stream retranscoding in the same way. So the server should transcode a little more befroe the `clientCurrentTime` at the beginning.
> I will open a pull request to the server code at the same time.
#### P.S.
> The rules of `seekback` for now :
> - `totalPauseTime < 3s`, `seekback = 0`
> - `3s <= totalPauseTime < 1m`, `seekback = totalPauseTime / 6`
> - `1m <= totalPauseTime < 5m`, `seekback = 15s`
> - `5m <= totalPauseTime < 30m`, `seekback = 20s`
> - `30m <= totalPauseTime < 1h`, `seekback = 25s`
> - `1h <= totalPauseTime`, `seekback = 29.5s`
>
> We can discuss whether there is a more suitable solution.
---
<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/18
Author: @svdztn
Created: 10/26/2021
Status: ✅ Merged
Merged: 10/26/2021
Merged by: @advplyr
Base:
master← Head:stream-sync📝 Commits (7)
44a782brestore from App “stop" & "destroyed", get data from player, avoid progress loss1a86621native plugin: add getStreamSyncData()be02219native plugin: change setMediaSource() to the api with startPositionMs, avoid call output-0.ts (will cause server retranscoding)81316c7add auto seekback9a684aaMerge branch 'advplyr:master' into stream-synca08b09fdel debug log2ba41fefix min pause time to 3000 ms📊 Changes
4 files changed (+120 additions, -15 deletions)
View changed files
📝
android/app/src/main/java/com/audiobookshelf/app/MyNativeAudio.kt(+20 -0)📝
android/app/src/main/java/com/audiobookshelf/app/PlayerNotificationService.kt(+41 -3)📝
components/AudioPlayerMini.vue(+54 -8)📝
components/app/StreamContainer.vue(+5 -4)📄 Description
progress skipping backwards after open the main app while playing
I have been tracking "play in stream mode, progress skipping backwards" issue for some time.
According to my test, there are 2 conditions.
1.
The first one is pressing the system backButton, the log shows "App destroyed", in this condition, only player is running, progress can not sync to server.
2.
Another one is more subtle, maybe caused by my os I think. My os is MIUI12.5 (Android 11). When the screen locked and play audiobooks in stream mode for a period of time, it seems that the app will be hibernated by the os.
According to the log, the app can sync
CurrentTimeto server at the beginning. But theplayIntervalwill stop after about 10 minutes.My methods is when the app runs again, read status and data from the player, and restore these data to the app after some processing. Such as do not initPlayer if the audiobook is the same one and the player is in playing.
I have been testing this code for a while, it worked fine.
other improvements
fix bug: player init cause stream retranscoding
The init progress is call
mPlayer.setMediaSource()andprepare()first, when the state turns toREADY, then callseekTo()to jump to the startTime. That will call the server for the fileoutput-0.ts.add auto seekback
I mentioned this in #12, when playing the paused audiobook again, seekback a bit of time can help user recall where they were last stopped.
There are 2 conditions too:
One is the player is still running, and no audiobook switch. The
seekbackis handled by the player which record the pauseTime when paused and calcseekbacktime when start to play.Another one is switch audiobook or restart the app (player). Becase there is no data for the player to calc, so there need help from the server. We need the
lastUpdate timeof the audiobook, use it as the last paused time. Theseekbackis handled in the app, before player init.And there is another problem, the
seekbackmay cause stream retranscoding in the same way. So the server should transcode a little more befroe theclientCurrentTimeat the beginning.P.S.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.