Skip to content

Commit 0073ab0

Browse files
committed
fix(mediaplayer): stop the seek bar bouncing to the pre-seek position on short seeks
The scrubber holds the handle at the seek target while the (asynchronous) networking seek applies, releasing once the reported position "lands". The landed test was "within 4s of the target", which can't distinguish a not-yet-applied seek from a landed one when the jump is shorter than 4s — so on short seeks it released early and the bar tracked the still-advancing pre-seek playhead for a moment before snapping to the target. Capture the pre-seek position and release only once the reported position is nearer the target than that origin, which disambiguates at any seek distance.
1 parent 0c6a288 commit 0073ab0

1 file changed

Lines changed: 15 additions & 5 deletions

File tree

Basis/Packages/com.basis.mediaplayer/Runtime/UI/BasisMediaPlayerPanelProvider.cs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public class BasisMediaPlayerPanelProvider : BasisMenuActionProvider<BasisMainMe
3535
private float _seekPendingPct;
3636
private bool _drivingSeekSlider; /* our write, not the user's drag */
3737
private double _seekAwaitPosS; /* issued seek target, held until position lands */
38+
private double _seekAwaitFromS; /* pre-seek position, to tell "landed" from "not yet moved" */
3839
private float _seekAwaitUntil = -1f;
3940
private const float SeekDebounceSeconds = 0.35f;
4041
private int _lastPosSec = -1;
@@ -764,16 +765,20 @@ private void RefreshSeekBar()
764765
_seekPendingAt = -1f;
765766
double targetS = Mathf.Clamp(_seekPendingPct, 0f, 100f) / 100.0 * durS;
766767
var target = System.TimeSpan.FromSeconds(targetS);
768+
// Capture where we're seeking FROM before the seek applies — the
769+
// networking path is asynchronous, so the reported position keeps
770+
// reading the pre-seek playhead until it lands.
771+
double fromS = _activePlayer.Position.TotalSeconds;
767772
if (_activeNetworking != null) _ = _activeNetworking.Seek(target);
768773
else
769774
{
770775
try { _activePlayer.Seek(target); }
771776
catch (System.NotSupportedException) { }
772777
}
773-
// The native seek is asynchronous: hold the handle at the target
774-
// until the reported position lands nearby (or give up after a
775-
// refetch-worth of time), instead of tweening back to the old
776-
// playhead and forward again.
778+
// Hold the handle at the target until the reported position lands
779+
// (or give up after a refetch-worth of time), instead of tweening
780+
// back to the old playhead and forward again.
781+
_seekAwaitFromS = fromS;
777782
_seekAwaitPosS = targetS;
778783
_seekAwaitUntil = Time.unscaledTime + 6f;
779784
return;
@@ -782,7 +787,12 @@ private void RefreshSeekBar()
782787
double posS = _activePlayer.Position.TotalSeconds;
783788
if (_seekAwaitUntil > 0f)
784789
{
785-
bool landed = System.Math.Abs(posS - _seekAwaitPosS) < 4.0; /* keyframe granularity */
790+
// Landed once the reported position is nearer the target than the
791+
// pre-seek playhead. A plain "within N seconds of target" test can't
792+
// tell a not-yet-applied seek from a landed one when the jump is
793+
// shorter than N, which released the hold early and bounced the bar
794+
// back to the old position on small seeks.
795+
bool landed = System.Math.Abs(posS - _seekAwaitPosS) <= System.Math.Abs(posS - _seekAwaitFromS);
786796
if (!landed && Time.unscaledTime < _seekAwaitUntil)
787797
{
788798
posS = _seekAwaitPosS;

0 commit comments

Comments
 (0)