--- a/Sources/AetherEngine/Video/SegmentCache.swift
+++ b/Sources/AetherEngine/Video/SegmentCache.swift
@@ -78,6 +78,14 @@
     /// detect gaps below the producer's write head after eviction erases them from indexRange().
     private var _highestStoredIndex: Int = -1
 
+    // Modified for Teevo (products/apple-media), 20 October 2026: how long the march takes to make
+    // one segment, measured between consecutive new high-water arrivals and smoothed, so
+    // VideoSegmentProvider can tell a forward wait that will be short from one that outlasts a
+    // restart (a 50 MB segment of a big film over a modest line takes seconds to make).
+    // scripts/fetch-aetherengine.mjs applies this change.
+    private var lastMarchArrival: DispatchTime?
+    private var _marchSecondsPerSegment: Double?
+
     /// Audit SEG-4: every stored generation of an index gets its own file name, so a URL names exactly
     /// one set of bytes. A reader dropping a vanished entry, or a prune deleting a doomed one after
     /// unlocking, can then never hit a newer adoption of the same index.
@@ -274,7 +282,10 @@
             if let superseded { supersededFile = superseded }
             entryBytes[index] = data.count
             _totalBytes += data.count
-            if index > _highestStoredIndex { _highestStoredIndex = index }
+            if index > _highestStoredIndex {
+                noteMarchArrival(consecutive: index == _highestStoredIndex + 1)
+                _highestStoredIndex = index
+            }
         }
         let doomed = pruneOutsideWindow()
         if !doomed.isEmpty { residentSetChanged = true }
@@ -324,7 +335,10 @@
             if let superseded { supersededFile = superseded }
             entryBytes[index] = byteCount
             _totalBytes += byteCount
-            if index > _highestStoredIndex { _highestStoredIndex = index }
+            if index > _highestStoredIndex {
+                noteMarchArrival(consecutive: index == _highestStoredIndex + 1)
+                _highestStoredIndex = index
+            }
             // A later epoch produced what an earlier one passed over: a re-anchor moved the
             // boundaries and this index is no longer a hole (#358).
             foldCounts.removeValue(forKey: index)
@@ -702,8 +716,36 @@
         condition.lock()
         defer { condition.unlock() }
         _highestStoredIndex = -1
+        // Modified for Teevo: a restarted march is timed afresh; its speed estimate stands.
+        lastMarchArrival = nil
+    }
+
+    /// Modified for Teevo: seconds the march takes per segment, nil until two consecutive
+    /// segments have arrived. Called with `condition` held.
+    private func noteMarchArrival(consecutive: Bool) {
+        let now = DispatchTime.now()
+        if consecutive, let last = lastMarchArrival {
+            let gap = Double(now.uptimeNanoseconds - last.uptimeNanoseconds) / 1_000_000_000
+            _marchSecondsPerSegment = _marchSecondsPerSegment.map { 0.5 * $0 + 0.5 * gap } ?? gap
+        }
+        lastMarchArrival = now
     }
 
+    /// Modified for Teevo: see `noteMarchArrival`. The segment being made now has taken at least
+    /// as long as it has been since the last one arrived, so that counts too: a march too slow to
+    /// have been timed yet (the first segments of a big film) is seen as slow.
+    var marchSecondsPerSegment: Double? {
+        condition.lock()
+        defer { condition.unlock() }
+        let current = lastMarchArrival.map { Double(DispatchTime.now().uptimeNanoseconds - $0.uptimeNanoseconds) / 1_000_000_000 }
+        switch (_marchSecondsPerSegment, current) {
+        case let (measured?, current?): return max(measured, current)
+        case let (measured?, nil): return measured
+        case let (nil, current?): return current
+        case (nil, nil): return nil
+        }
+    }
+
     var count: Int {
         condition.lock()
         defer { condition.unlock() }
--- a/Sources/AetherEngine/Video/VideoSegmentProvider.swift
+++ b/Sources/AetherEngine/Video/VideoSegmentProvider.swift
@@ -1432,7 +1432,37 @@
         return _mediaFetchCount
     }
     private var _mediaFetchCount: UInt64 = 0
+
+    // Modified for Teevo (products/apple-media), 20 October 2026: the consumer's newest target when
+    // it arrived as a seek's (the engine said one was dispatched, or more than one segment past the
+    // one before), not AVPlayer's sequential prefetch. Guarded by stateLock. scripts/fetch-aetherengine.mjs applies
+    // this change.
+    private var _jumpTarget: Int?
+    /// Modified for Teevo: the engine dispatched a seek, and its target hasn't been asked for yet.
+    private var _seekDispatched = false
+
+    /// Modified for Teevo: called by the session when the engine dispatches a user seek.
+    func noteSeekDispatched() {
+        stateLock.lock(); _seekDispatched = true; stateLock.unlock()
+    }
+    private var jumpTarget: Int? {
+        stateLock.lock(); defer { stateLock.unlock() }; return _jumpTarget
+    }
+
+    /// Modified for Teevo: a forward wait longer than this, at the march's measured speed, is
+    /// worse than a restart, which makes only the one segment asked for.
+    static let forwardWaitBudgetSeconds: Double = 2.5
 
+    /// Modified for Teevo: whether a seek into the forward window should restart the producer
+    /// rather than wait for its march: the request is a jump, at least two segments past the
+    /// march front, and the march, at its measured speed, would take longer than the budget to
+    /// get there. Prefetch (sequential requests) and a march of unknown speed keep waiting.
+    static func forwardWaitOutrunsRestart(index: Int, marchFront: Int, jumpedHere: Bool,
+                                          secondsPerSegment: Double?) -> Bool {
+        guard jumpedHere, let secondsPerSegment, index - marchFront >= 2 else { return false }
+        return Double(index - marchFront) * secondsPerSegment > forwardWaitBudgetSeconds
+    }
+
     /// The index the consumer is currently blocked on, and how often a pump has passed it without
     /// producing a segment (#358). Two folds mean a re-anchor already tried and rebuilt the same gap.
     var consumerTargetFold: (index: Int, folds: Int) {
@@ -1508,6 +1538,16 @@
         stateLock.unlock()
         let previousTarget = cache.targetIndex
         cache.declareTarget(index)
+        // Modified for Teevo: a jump is remembered for the forward-wait decision; a re-request of
+        // the same index keeps it.
+        stateLock.lock()
+        if _seekDispatched || (previousTarget >= 0 && index > previousTarget + 1) {
+            _jumpTarget = index
+        } else if _jumpTarget != index {
+            _jumpTarget = nil
+        }
+        _seekDispatched = false
+        stateLock.unlock()
 
         // AE#418: AVPlayer places this segment at the position the PLAYLIST gives it, read through
         // the axis its timeline already carries (measured with `play --picture-probe`). So a segment
@@ -1666,6 +1706,24 @@
         // for this same index). Bypasses the restart loop's producerCovers veto below, which
         // otherwise reads the dead producer's still-installed base and suppresses the fire.
         var marchProvenDead = false
+        // Modified for Teevo: a seek's target ahead of the march that the march, at its measured
+        // speed, would take longer to reach than a restart (owner: "teevo player UI getting stuck
+        // a lot whilst playing larger files"; +30 s sat seeking 8-15 s on a 40 Mbit/s film over
+        // 100 Mbit/s). It restarts the producer rather than waiting, here or in the restart loop.
+        var slowMarch = false
+        if !isLive, jumpTarget == index {
+            let front = activeMarchFront
+            let perSegment = cache.marchSecondsPerSegment
+            slowMarch = Self.forwardWaitOutrunsRestart(index: index, marchFront: front, jumpedHere: true,
+                                                       secondsPerSegment: perSegment)
+            if slowMarch {
+                EngineLog.emit(
+                    "[HLSVideoEngine] seg\(index): a seek the march would reach after a restart's time (front=\(front), "
+                    + String(format: "%.2f", perSegment ?? 0) + " s per segment); restarting producer",
+                    category: .session
+                )
+            }
+        }
         // AE#169 round 2: true when the fetch takes the VOD forward-window backpressure wait, so a
         // full-timeout miss records (index, front) for the frozen-march escalation above.
         var tookForwardWait = false
@@ -1722,7 +1780,8 @@
                         )
                     }
                 }
-                needsRestart = index > front + Self.forwardWaitWindow || marchProvenDead
+                // Modified for Teevo: or a seek a slow march would take longer to reach (above).
+                needsRestart = index > front + Self.forwardWaitWindow || marchProvenDead || slowMarch
             }
         } else {
             // Empty cache: cold start (producer at lastRestartIndex, hasn't written yet) vs. big scrub
@@ -1759,7 +1818,8 @@
                     // AE#169 round 2: a march proven dead (finished pump / frozen front across a
                     // full wait) must not veto the fire; the still-installed dead producer's base
                     // covering the index is exactly the wedge being escaped.
-                    let producerCovers = !marchProvenDead && activeProducerCovers(index)
+                    // Modified for Teevo: nor may a slow march's cover veto a seek's restart.
+                    let producerCovers = !marchProvenDead && !slowMarch && activeProducerCovers(index)
                     // A request superseded by a NEWER declared target is an orphan of a skip
                     // storm: AVPlayer's newest request is what it actually wants (the same
                     // newest-wins semantics the coalescer applies to immediate restarts).
--- a/Sources/AetherEngine/Video/HLSVideoEngine.swift
+++ b/Sources/AetherEngine/Video/HLSVideoEngine.swift
@@ -4026,6 +4026,11 @@
         restartLock.lock()
         restartCoalescer.clearSupersededAuthoritativePending()
         restartLock.unlock()
+        // Modified for Teevo (products/apple-media), 20 October 2026: the provider is told a seek
+        // is on its way, so the segment AVPlayer asks for next is known as a seek's target even
+        // one segment on from the last (a run of presses). scripts/fetch-aetherengine.mjs
+        // applies this change.
+        provider?.noteSeekDispatched()
     }
 
     func requestRestart(at idx: Int, authoritative: Bool = false) {
