You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中react-video回退时分段播放逻辑异常问题

解决React视频播放器回退逻辑缺失问题

当前正向切换组件(如从步骤2到3)功能正常,但回退时(如从步骤3到2),未实现先播放至前一个组件的endTime,再跳转到当前组件的startTime并播放至其idleTime的预期逻辑,而是直接跳转到当前组件的startTime开始播放。

问题原因

负责回退逻辑的useEffect仅执行了直接跳转和播放操作,完全跳过了"播放前组件剩余部分至endTime"的步骤:

useEffect(() => {
    if (prevComponent > currentComponent) {
        playerRef.current.seek(startTime);
        playerRef.current.play();
    }
}, [currentComponent]);

解决方案

通过添加过渡状态跟踪,分阶段执行回退流程:

修改后的VideoPlayer组件代码

import { useState, useRef, useEffect } from 'react';
import { Player, ControlBar } from 'react-video';

const VideoPlayer = ({ frames, currentComponent, prevComponent, startTime, endTime, idleTime }) => {
    const [currentTime, setCurrentTime] = useState(startTime);
    const playerRef = useRef(null);
    // 新增状态:标记是否处于回退过渡阶段,以及过渡目标时间(前组件的endTime)
    const [backTransition, setBackTransition] = useState({
        isActive: false,
        targetEndTime: 0
    });

    useEffect(() => {
        // 正常播放到idleTime暂停的逻辑保留
        if (currentTime >= idleTime && !backTransition.isActive) {
            playerRef.current.pause();
        }

        // 处理回退过渡:到达前组件的endTime后,跳转至当前组件start并播放
        if (backTransition.isActive && currentTime >= backTransition.targetEndTime) {
            playerRef.current.pause();
            playerRef.current.seek(startTime);
            playerRef.current.play();
            // 结束过渡状态
            setBackTransition({ isActive: false, targetEndTime: 0 });
        }
    }, [currentTime, idleTime, backTransition, startTime]);

    // 正向切换逻辑保留
    useEffect(() => {
        if (prevComponent && prevComponent < currentComponent) {
            const prevEndTime = frames.find(item => item.id === prevComponent).end;
            if (currentTime <= prevEndTime) {
                playerRef.current.play();
                if (prevEndTime - currentTime <= 0.3) {
                    playerRef.current.pause();
                    playerRef.current.seek(startTime);
                    playerRef.current.play();
                }
            }
        }
    }, [currentTime, currentComponent, prevComponent, frames, startTime]);

    // 修改回退逻辑:启动过渡,先播放至前组件的endTime
    useEffect(() => {
        if (prevComponent && prevComponent > currentComponent) {
            const prevFrame = frames.find(item => item.id === prevComponent);
            const prevEndTime = prevFrame.end;

            // 如果当前时间已经超过前组件的endTime,直接跳转
            if (currentTime >= prevEndTime) {
                playerRef.current.seek(startTime);
                playerRef.current.play();
                return;
            }

            // 启动回退过渡:先播放到前组件的endTime
            setBackTransition({ isActive: true, targetEndTime: prevEndTime });
            playerRef.current.play();
        }
    }, [currentComponent, prevComponent, frames, currentTime, startTime]);

    return (
        <Player
            ref={playerRef}
            autoPlay
            startTime={0}
            muted={true}
            onTimeUpdate={(e) => {
                setCurrentTime(parseFloat(e.target.currentTime));
            }}
        >
            <source src="./video.mp4" style={{ height: '100vh' }} />
            <ControlBar autoHide={false} disableCompletely={true} disableDefaultControls={true} />
        </Player>
    );
};

export default VideoPlayer;

关键逻辑说明

  • backTransition状态:用于标记是否处于回退过渡流程中,同时存储需要播放到的前组件endTime,避免和正常播放逻辑冲突。
  • 回退触发逻辑:检测到回退操作时,先判断当前时间是否已超过前组件的endTime,若未超过则启动过渡,播放至该时间点;若已超过则直接跳转至当前组件的startTime。
  • 过渡阶段处理:在currentTime的监听逻辑中,当到达过渡目标时间时,自动跳转至当前组件的startTime并开始播放,同时结束过渡状态,恢复正常播放逻辑。

内容的提问来源于stack exchange,提问作者user22883124

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 16:43:27