蘑菇短视频横屏切换时播放进度新手快问快答:从0到1怎么设置

概述 很多短视频产品在用户从竖屏切换到横屏观看(或反向切回)时,会因为播放器被销毁或重新加载而丢失当前播放位置,用户体验大打折扣。要把“横竖屏切换时保持播放进度”这件事从0做到1,核心思路很简单:在切换过程中保存并恢复播放时间;更好的策略是直接保留同一个播放器实例,避免重新加载。下面给出面向初学者的实战步骤、示例代码和注意事项,覆盖网页与原生两种常见场景。
先说两种常见实现策略(按优先级)
- 推荐(更省流量、体验最好):不销毁 video 元素/播放器实例,仅改变样式或全屏状态,播放器一直存在,进度自然保持。
- 备用(当必须重建播放器或切换页面时):在切换前保存 currentTime,重建后在 metadata 加载完成后 seek 到该时间。
网页(HTML5/JS)实现步骤(从0到1) 1)准备播放器与切换触发点
- 使用
- 横竖切换可通过全屏 API、CSS 类切换或监听屏幕方向事件实现。
2)优先方案:保持同一 video 元素
- 不要把 video 元素从 DOM 中移除,只对容器做样式变换(宽高、transform、position)。
- 切换为横屏时进入横屏样式/全屏;切回竖屏时恢复样式。
- 这个做法能保证 currentTime、缓冲、播放状态完全保留。
3)备用方案:保存并恢复播放时间
- 在切换前读取 video.currentTime 并保存(内存、sessionStorage 或传入新页面的 URL 参数)。
- 重建播放器后,等待 loadedmetadata 或 canplay 事件,再设置 video.currentTime = savedTime;如果媒体是 HLS/流式分段,等待 canplay 或 canplaythrough 以保证可 seek。
- 需要处理 autoplay 限制:浏览器通常要求用户手势或 muted 才能自动播放。
示例:保持同一元素(简单思路)
- HTML: 一个固定的 video 元素放在页面里,切换只是改样式或调用 requestFullscreen。
- JavaScript 思路:不需要处理 currentTime,直接切换样式/全屏。
示例:如果必须重建播放器(保存/恢复 currentTime)
-
保存进度: var savedKey = 'moguvideo' + videoId; function saveProgress() { try { sessionStorage.setItem(savedKey, video.currentTime.toString()); } catch(e){} } window.addEventListener('beforeunload', saveProgress); // 在切换 UI 之前也调用 saveProgress()
-
恢复进度(重建后): var saved = parseFloat(sessionStorage.getItem(savedKey) || '0'); video.addEventListener('loadedmetadata', function() { if (saved > 0 && saved < video.duration) { video.currentTime = saved; } // 如果希望自动播放,确保满足 autoplay 限制(可能需要 muted) video.play().catch(function(){ /* 允许用户点击播放 */ }); });
移动端(原生 Android/iOS)关键点
-
Android + ExoPlayer
-
在 onConfigurationChanged(或 Activity/Fragment 生命周期)保存播放器的位置: long pos = player.getCurrentPosition();
-
不销毁 player 实例,是最稳妥的:把 PlayerView 从一个 container 移到另一个,或调整布局以实现横竖切换。
-
若必须重建,重建后调用 player.seekTo(pos) 并在准备好后 player.setPlayWhenReady(true)。
-
iOS + AVPlayer
-
监听 UIDevice.orientationDidChangeNotification 或在 UIViewController 的旋转回调中处理。
-
保持同一个 AVPlayer 和 AVPlayerLayer,改变层的 frame 即可保持进度。
-
若重建 AVPlayer,保存 CMTime current = player.currentTime(); 重建后使用 [player seekToTime:current completionHandler:…].
常见问题与解决方案
- 恢复时跳到错误时间或黑屏:确认在 loadedmetadata 或 player.ready 之后再 seek;对于 HLS 等流媒体,可能需要等待 canplay 或 waitForBuffer。
- 自动播放被浏览器阻止:可用 muted + play() 作为临时策略,或提示用户点击继续播放。
- 不同分辨率导致时间轴差异:同一媒体文件在横竖两个源(不同 URL)时要确保两端的时间轴一致;若不同 URL,只能通过服务器或映射表把时间戳转化到目标流。
- 多视频列表场景:每个视频用唯一 id 存储进度(sessionStorage/localStorage;若要跨设备同步可上报后端)。
调试与测试清单(发布前跑一遍)
- 切换横竖屏(快速切、多次切)是否丢失进度或报错
- 在弱网环境下切换,是否卡住、自动重缓冲时间是否可接受
- 不同机型/浏览器(iOS Safari、Android Chrome)下播放/暂停/seek 行为
- 后退/前进、页面重载时进度是否按预期保存
- 全屏进入/退出、旋转时 UI 元素(进度条、播放按钮)位置是否正确
体验优化建议(小技巧)
- 尽量避免在切换时重新加载视频文件;保留播放器实例是最佳体验。
- 切换时可短暂显示自动提示(“已继续播放 xx:xx”)让用户知道进度已恢复。
- 若是短视频 feed(上下滑切换视频),把每个视频的最后进度保存在内存并同步到 sessionStorage,能在短时间内快速恢复。
从0到1的最短路径(实战路线)
- 先实现“同一 video 元素”,通过 CSS/全屏 API 实现横竖切换(这一步通常能解决绝大多数问题)。
- 如果业务限制导致必须销毁播放器,加入“保存 currentTime → 重新创建 → 在 loadedmetadata 后 seek”流程,并用 sessionStorage/内存做临时缓存。
- 在关键平台(iOS/Android/Web)逐条测试,处理 autoplay、缓冲和边缘情况。
结语 把横竖切换时播放进度做对,更多是工程实践而不是复杂算法:核心是“别丢掉播放器状态;确实要丢就先保存时间再恢复”。按照上面的两条策略,从不销毁播放器到保存/恢复 currentTime,你可以一步步把体验从0拉到1。需要的话我可以根据你用的具体技术栈(纯网页、React/Vue、ExoPlayer、AVPlayer 或 video.js/hls.js)给出更贴合的代码示例。想要哪个栈的实例?
