Does Rotating Your Phone Restart HLS Playback? Diagnose Resize, Fullscreen, and Player Remounts
Separate a normal phone-orientation layout change from a true HLS reload, then preserve safe playback state when a player really must be rebuilt.
If an HLS video pauses, jumps, or starts loading again when a phone turns sideways, rotation itself is not enough to identify the cause. A responsive layout may only have changed dimensions; the application may have replaced its video element; fullscreen entry may have triggered a separate state change; or the page may have actually reloaded the source.
First determine which event occurred. Keep the same authorized stream, player version, browser, playback position, and network while comparing portrait and landscape. Do not infer a mobile-browser defect from one rotation or restore a saved timestamp blindly on a live stream.
Verification method — September 28, 2026: We reviewed the current MDN documentation for the Screen Orientation API, viewport orientation media queries, HTMLMediaElement.currentTime, play(), and fullscreen. We also ran a deterministic Node.js fixture for synthetic resize, remount, and recovery-state cases. This is documentation review plus fixture logic only: no physical phone, browser-specific HLS engine, or real stream was tested. The fixture is scripts/test-hls-orientation-fixture.cjs.
Separate a layout change from a player restart
These signals point to different layers:
| Observation | What it can mean | What to inspect next |
|---|---|---|
| Player dimensions change but media time continues | Responsive layout or video sizing | CSS/layout and resize handling |
A change event fires on screen.orientation | The browser reports an orientation change | Check whether your handler also changes player state |
| The video element or player instance ID changes | The framework or application remounted the player | Component keys, conditional rendering, route state |
| A new manifest request starts and media time returns near zero | Source reload or new player setup | src assignment, player load() calls, effect dependencies |
| Playback pauses with no new manifest request | Pause policy, visibility handling, browser behavior, or user action | Capture paused, visibility, fullscreen, and media events |
The CSS orientation media feature describes the viewport shape; it is not proof that a particular physical device sensor event caused playback to restart. Prefer the Screen Orientation API's change event over the deprecated orientationchange event when JavaScript genuinely needs an orientation notification. Usually the video does not need to be recreated just to resize its container.
Instrument the player before changing code
For a short, authorized test, record a timestamped sequence of:
screen.orientation.typeand viewport width/height, where supported.- A stable application player-instance ID and whether the actual
<video>node identity changed. currentSrcor a redacted source identifier,currentTime,paused,readyState, andnetworkState.resize,visibilitychange,fullscreenchange,pause,playing,waiting,emptied,loadstart, andloadedmetadataevents.- Whether a new manifest or media request began. Store only a redacted hostname/path class; never log signed query strings, cookies, or authorization headers.
Take one snapshot just before rotation and another after the layout stabilizes. If the video node and source remain the same and no new loading sequence starts, investigate layout or buffering before blaming a player reload. If the node changed, find the render branch that replaced it. If the source was assigned again, find the code path that did so.
Test rotation, fullscreen, and reload separately
Use a small matrix rather than rotating repeatedly and guessing:
| Test | Change only | Evidence to compare |
|---|---|---|
| Portrait to landscape while playing | Viewport/device orientation | Node identity, media time, new requests, pause state |
| Landscape to portrait while paused | Orientation with paused intent | Whether the player unexpectedly starts or seeks |
| Enter and exit fullscreen without rotating | Fullscreen state | Fullscreen promise/event and source continuity |
| Resize a desktop browser viewport | Layout dimensions | Whether application logic reacts differently from mobile |
| Explicitly reload the page | Document lifecycle | Expected new player instance and fresh source request |
Do not treat an emulator or desktop viewport as a physical-device test. If the issue is limited to a phone/browser combination you cannot access, label that platform as documentation-reviewed or untested and ask for browser version, OS version, device class, and a redacted event trace.
Keep the media element stable where possible
Let CSS resize the player shell while preserving the same media element and HLS instance. Avoid putting orientation-dependent values into a framework key or conditional branch that forces the player component to unmount. Also avoid recreating the player in a resize handler unless a documented engine constraint requires it.
If a genuine teardown is unavoidable, capture only the state that can safely be restored: source identity, whether playback was paused, selected audio/quality preferences if supported, and the last observed media time. Reattach the source, wait for metadata/seekable ranges, then validate the target before seeking. currentTime is a seek position, not a durable identity for live content: a live DVR window can move or expire while the player is being rebuilt. Clamp a live target to a currently available seekable range or return to the live edge according to the product's intended behavior.
Call play() only when the prior state and product behavior justify resuming. Its promise can reject, so handle the rejection and leave a usable play control. Fullscreen entry is also asynchronous and can be denied; update UI state from the actual fullscreen event rather than assuming a request succeeded.
Common mistakes
- Rebuilding the player on every
resize: rotation and browser chrome changes can generate layout events without requiring source reload. - Using a changing component key: a key tied to width/orientation can deliberately replace the video subtree.
- Listening only for an old orientation event: use the modern Screen Orientation API where available, and retain a graceful fallback if orientation data is not needed.
- Seeking to a saved live timestamp unconditionally: the live window may no longer contain that time.
- Calling
play()without handling its promise: user-gesture or browser policy can prevent automatic resumption. - Assuming fullscreen caused rotation: test fullscreen entry/exit independently from orientation changes.
- Sharing full request logs: query parameters and headers may contain credentials; redact before sharing.
A concise bug report
Report the device and OS, browser/version, player/engine version, stream type (VOD or live/DVR), starting playback state, and exact test sequence. Include whether the video node or player instance changed, whether a manifest request restarted, and whether currentTime, paused, or seekable ranges changed. Redact stream URLs, keys, tokens, cookies, and private hostnames. State clearly if the behavior was documentation-reviewed rather than reproduced on the named device.
For related checks, see the mobile HLS playback guide, HLS playback after backgrounding or locking the screen, and autoplay troubleshooting.
Primary references
- MDN: ScreenOrientation
changeevent - MDN: Managing screen orientation
- MDN:
HTMLMediaElement.currentTime - MDN:
HTMLMediaElement.play() - MDN:
Element.requestFullscreen() - MDN: deprecated
orientationchangeevent
The useful distinction is not “portrait versus landscape,” but “layout changed versus player/source lifecycle changed.” Capture that boundary first; only then decide whether any playback-state recovery is needed.