fix: Discord RPC time drift with playback speed

close #284
This commit is contained in:
edde746
2026-01-17 18:55:08 +01:00
parent 9071eab3ae
commit 0005d70bde
2 changed files with 25 additions and 4 deletions
+5
View File
@@ -598,6 +598,11 @@ class VideoPlayerScreenState extends State<VideoPlayerScreen> with WidgetsBindin
DiscordRPCService.instance.updatePosition(position);
});
// Listen to playback rate changes for Discord Rich Presence
player!.streams.rate.listen((rate) {
DiscordRPCService.instance.updatePlaybackSpeed(rate);
});
// Start Discord Rich Presence for current media
if (client != null) {
DiscordRPCService.instance.startPlayback(widget.metadata, client);
+20 -4
View File
@@ -47,6 +47,7 @@ class DiscordRPCService {
DateTime? _playbackStartTime;
Duration? _mediaDuration;
Duration? _currentPosition;
double _playbackSpeed = 1.0;
Timer? _reconnectTimer;
DateTime? _lastPresenceUpdate;
StreamSubscription<void>? _readySubscription;
@@ -106,6 +107,7 @@ class DiscordRPCService {
_mediaDuration = metadata.duration != null ? Duration(milliseconds: metadata.duration!) : null;
_currentPosition = Duration.zero;
_cachedThumbnailUrl = null;
_playbackSpeed = 1.0;
if (_isEnabled && _isConnected) {
// Upload thumbnail in background, don't block playback
@@ -133,6 +135,15 @@ class DiscordRPCService {
}
}
/// Update current playback speed (for accurate remaining time calculation)
void updatePlaybackSpeed(double speed) {
if (_playbackSpeed == speed) return;
_playbackSpeed = speed;
if (_isEnabled && _isConnected && _playbackStartTime != null) {
_updatePresence();
}
}
/// Resume playback (restore timestamp)
Future<void> resumePlayback() async {
if (_currentMetadata == null) return;
@@ -161,6 +172,7 @@ class DiscordRPCService {
_currentClient = null;
_playbackStartTime = null;
_cachedThumbnailUrl = null;
_playbackSpeed = 1.0;
if (_isEnabled && _isConnected) {
await clearPresence();
@@ -357,11 +369,15 @@ class DiscordRPCService {
final now = DateTime.now();
final position = _currentPosition ?? Duration.zero;
// Calculate when playback "started" (now minus current position)
final effectiveStart = now.subtract(position);
// Calculate remaining time accounting for playback speed
final remainingDuration = _mediaDuration! - position;
final adjustedRemaining = Duration(microseconds: (remainingDuration.inMicroseconds / _playbackSpeed).round());
// Calculate when playback will "end" (start + total duration)
final effectiveEnd = effectiveStart.add(_mediaDuration!);
// Calculate total adjusted duration for progress bar
final adjustedTotal = Duration(microseconds: (_mediaDuration!.inMicroseconds / _playbackSpeed).round());
final effectiveEnd = now.add(adjustedRemaining);
final effectiveStart = effectiveEnd.subtract(adjustedTotal);
return DiscordTimestamps.range(effectiveStart, effectiveEnd);
}