Skip to content

Add stutter detection watchdog with auto-buffer increase#62

Merged
TheJoeFin merged 16 commits intomainfrom
copilot/create-stutter-detection-watchdog
Jan 24, 2026
Merged

Add stutter detection watchdog with auto-buffer increase#62
TheJoeFin merged 16 commits intomainfrom
copilot/create-stutter-detection-watchdog

Conversation

Copy link
Contributor

Copilot AI commented Jan 19, 2026

  • Extend StreamWatchdogService to track stutter/recovery patterns over time
  • Add new event StutterDetected to notify when excessive stuttering is detected
  • Add new event BufferLevelChanged to notify UI when buffer level changes
  • Add new settings to StreamWatchdogService for auto-buffer increase feature
  • Add settings storage for auto-buffer configuration
  • Update PlayerViewModel with properties for auto-buffer settings
  • Update SettingsViewModel with properties for auto-buffer settings
  • Update SettingsPage.xaml with UI for enabling auto-buffer feature
  • Implement buffer level tracking that persists between sessions
  • Use MediaPlaybackSession.GetBufferedRanges to monitor buffered content
  • Add PlayWithBufferAsync method for buffer-aware playback
  • Update recovery logic to use buffered ranges for smooth streaming
  • Always apply buffer settings on every Play() call, not just during stutter recovery
  • Use Pause/Play approach for buffering: Play() -> Pause() -> wait buffer time -> check GetBufferedRanges -> Play()
  • Run code review and address feedback
  • Run CodeQL security check (no issues found)
Original prompt

This section details on the original issue you should resolve

<issue_title>Create a stutter detection watchdog that automatically increases the buffer if the station stutters too much</issue_title>
<issue_description>This will also kick in if the station is struggling to connect to stations</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

- Add recovery attempt tracking with timestamp queue in StreamWatchdogService
- Detect stutter when 3+ recovery attempts occur within 2 minutes
- Auto-increase buffer level (0-3) when stutter is detected
- Add BufferLevelChanged event for UI updates
- Add settings persistence for auto-buffer configuration
- Update PlayerViewModel to expose buffer settings
- Update SettingsViewModel with auto-buffer properties
- Add Settings UI for auto-buffer toggle and buffer level slider
- Use consistent GetToggleText helper for toggle state display

Co-authored-by: TheJoeFin <7809853+TheJoeFin@users.noreply.github.com>
Copilot AI changed the title [WIP] Add stutter detection watchdog with buffer increase Add stutter detection watchdog with auto-buffer increase Jan 19, 2026
Copilot AI requested a review from TheJoeFin January 19, 2026 15:44
@TheJoeFin
Copy link
Owner

@copilot use MediaPlaybackSession.GetBufferedRanges Method on the RadioPlayerService.cs _player MediaPlayer so when trying to play the stream the new buffered amount is applied to be able to smoothly stream the audio without stutter

- Add TotalBufferedDuration property using GetBufferedRanges()
- Add GetBufferedRanges() method to expose buffered time ranges
- Add RequiredBufferDuration and HasSufficientBuffer properties
- Add PlayWithBufferAsync() method that waits for sufficient buffer
- Add LogBufferedRanges() helper for debugging buffer state
- Update AttemptRecoveryAsync to use buffer-aware playback
- Calculate dynamic timeout based on required buffer duration

Co-authored-by: TheJoeFin <7809853+TheJoeFin@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 19, 2026

@copilot use MediaPlaybackSession.GetBufferedRanges Method on the RadioPlayerService.cs _player MediaPlayer so when trying to play the stream the new buffered amount is applied to be able to smoothly ...

Implemented in 51b83f0. Added MediaPlaybackSession.GetBufferedRanges() support in RadioPlayerService:

  • TotalBufferedDuration property calculates total buffered content from all time ranges
  • GetBufferedRanges() method exposes the raw buffered ranges
  • RequiredBufferDuration and HasSufficientBuffer properties for buffer level checking
  • PlayWithBufferAsync() method waits for sufficient buffer before playback starts smoothly

The recovery logic in StreamWatchdogService.AttemptRecoveryAsync now uses PlayWithBufferAsync() to ensure adequate buffering based on the buffer level setting before audio begins.

@TheJoeFin
Copy link
Owner

@copilot the RadioPlayerService should always apply the buffering settings when playing, not just when a stutter is detected. The stutter detection is used to increase the buffer amount, but every time the audio is playing, it should use the buffer settings

…ecovery

- Modified Play() to always use buffer-aware playback via PlayWithBufferInternalAsync()
- Added PlayWithBufferInternalAsync() private method for async buffered playback
- Added cancellation token support to WaitForSufficientBufferAsync()
- Buffer settings using GetBufferedRanges are now applied every time playback starts
- Fixed null handling consistency across methods

Co-authored-by: TheJoeFin <7809853+TheJoeFin@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 19, 2026

@copilot the RadioPlayerService should always apply the buffering settings when playing, not just when a stutter is detected. The stutter detection is used to increase the buffer amount, but every tim...

Implemented in 4b668ce. The RadioPlayerService.Play() method now always applies buffer settings:

  • Play() now calls PlayWithBufferInternalAsync() which uses GetBufferedRanges to monitor buffering
  • Every time playback starts, the buffer level settings are applied and the stream waits for sufficient buffer before audio begins
  • The stutter detection still increases buffer amount when needed, but the buffer is now always applied during normal playback as well

@TheJoeFin
Copy link
Owner

@copilot the playback still happens instantly which tells me that no buffering is happening. Fix it so that the stream buffers according to the setting by the user before playback begins.

Copy link
Contributor Author

Copilot AI commented Jan 19, 2026

@TheJoeFin Unfortunately I hit an unexpected error while processing your comment. I've automatically reported this to GitHub.

You can ask me to try again later by mentioning me in a new comment.

If you want to contact GitHub about this error, please mention the following identifier so they can better serve you: e468b6c3-1d0a-4c84-a8fd-302798f7ac43

Sorry for the inconvenience!

- Modified PlayWithBufferInternalAsync() to mute player (volume=0) while buffering
- Audio remains silent during buffer accumulation using GetBufferedRanges
- Once sufficient buffer is achieved, volume is restored and audio becomes audible
- Modified PlayWithBufferAsync() with same muting behavior for watchdog recovery
- Volume is always restored in finally block for all exit paths

Co-authored-by: TheJoeFin <7809853+TheJoeFin@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 19, 2026

@copilot the playback still happens instantly which tells me that no buffering is happening. Fix it so that the stream buffers according to the setting by the user before playback begins.

Fixed in 5dbc77e. The stream is now muted (volume=0) while buffering, so audio doesn't play until the buffer is full:

  1. When Play() is called and buffer level > 0, the player volume is set to 0
  2. The stream starts buffering using GetBufferedRanges to monitor progress
  3. Once sufficient buffer is achieved, volume is restored and audio becomes audible
  4. If buffer level is 0 (Default), playback starts immediately without muting

@TheJoeFin
Copy link
Owner

@copilot update the code to use mediaPlayer.Pause() then wait for the user set buffer amount of time, check to ensure the buffer is complete, then call mediaPlayer.Play()

- Call _player.Play() to initiate buffering
- Add 100ms delay to ensure play command is processed
- Call _player.Pause() to stop audio while buffering
- Wait for user-set buffer time using Task.Delay(RequiredBufferDuration)
- Check buffer is complete using GetBufferedRanges
- Call _player.Play() to resume playback
- Applied same approach to PlayWithBufferAsync and retry handlers

Co-authored-by: TheJoeFin <7809853+TheJoeFin@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 19, 2026

@copilot update the code to use mediaPlayer.Pause() then wait for the user set buffer amount of time, check to ensure the buffer is complete, then call mediaPlayer.Play()

Implemented in 23b8fdf. Changed buffering approach to use Pause/Play:

  1. _player.Play() - initiates buffering
  2. 100ms delay - ensures play command is processed
  3. _player.Pause() - stops audio while buffering
  4. Task.Delay(RequiredBufferDuration) - waits for user-set buffer time
  5. Check buffer complete via GetBufferedRanges
  6. _player.Play() - resumes playback

Applied to both PlayWithBufferInternalAsync() and PlayWithBufferAsync() methods.

Updated slider to allow 0.5 increments and hid the buffer level description text for a cleaner UI.
Ensures the ListView's selected item stays in sync with the ViewModel's SelectedStation property for consistent UI and data state.
Enable double-based buffer levels and linear delay interpolation for finer granularity in stream buffering.
Improves buffering indicator accuracy and UI responsiveness during custom buffer delays by tracking manual buffering state and ensuring it is reset on pause, error, or cancellation. Also allows finer buffer slider control.
Improves clarity and consistency by updating labels and tooltips to explicitly reference "songs" in favorite-related UI elements.
Updated XAML to use ScrollView, enabled marquee for Now Playing, and added required package reference. No logic changes.
Updated the application version in Package.appxmanifest.
Enhanced About page with star rating, direct review, and contact developer options for improved user feedback experience.
Improves code readability, null-safety, and consistency across RadioPlayerService and AboutViewModel. No functional changes.
Updated version in Package.appxmanifest.
@TheJoeFin TheJoeFin marked this pull request as ready for review January 24, 2026 23:44
@TheJoeFin TheJoeFin merged commit 86f7815 into main Jan 24, 2026
1 check failed
@TheJoeFin TheJoeFin deleted the copilot/create-stutter-detection-watchdog branch February 26, 2026 03:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create a stutter detection watchdog that automatically increases the buffer if the station stutters too much

2 participants