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

如何使用React Native Expo-AV Video实现长按跳转不同时间点播放功能

疑问澄清

这类长按预览效果基本不会用GIF实现:提前生成GIF会额外占用存储和带宽,清晰度、帧率上限低,还要适配不同时长视频的生成规则,平台级应用普遍采用直接从原视频抽取时间片实时播放的方案实现。

Expo-AV 实现方案

依赖安装

如果项目未引入对应依赖先执行安装:

npx expo install expo-av react-native-gesture-handler

非Expo管理的纯React Native项目需要额外完成原生依赖的链接配置。

核心实现逻辑

通过Expo-AV提供的视频定位、播放控制API,结合长按手势检测、时序队列控制完成功能,示例代码如下:

import { Video } from 'expo-av';
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import { useState, useRef } from 'react';
import { View } from 'react-native';

// 计算4个采样时间点,默认取视频10%/35%/60%/85%位置,避开开头黑屏/片尾无效内容
const getSamplePoints = (durationMs) => {
  const step = durationMs * 0.25;
  return [0.1 * durationMs, 0.1 * durationMs + step, 0.1 * durationMs + 2*step, 0.1 * durationMs + 3*step]
    .map(point => Math.min(point, durationMs - 1000)); // 避免最后一个采样点播放时长不足1秒
}

const VideoPreviewItem = ({ videoUri, posterUri }) => {
  const videoRef = useRef(null);
  const [isPreviewing, setIsPreviewing] = useState(false);
  const samplePointsRef = useRef([]);
  const totalDurationRef = useRef(0);

  // 视频加载完成后获取总时长,预计算采样点
  const onVideoLoad = async (data) => {
    totalDurationRef.current = data.durationMillis;
    samplePointsRef.current = getSamplePoints(data.durationMillis);
  };

  // 执行预览播放队列
  const runPreviewPlay = async () => {
    if (isPreviewing || !videoRef.current) return;
    setIsPreviewing(true);
    
    for (const timePoint of samplePointsRef.current) {
      if (!isPreviewing) break; // 长按中断则直接终止队列
      // 跳转到采样时间点
      await videoRef.current.setPositionAsync(timePoint);
      // 播放1秒后暂停
      await videoRef.current.playAsync();
      await new Promise(resolve => setTimeout(resolve, 1000));
      await videoRef.current.pauseAsync();
    }
    setIsPreviewing(false);
  };

  // 长按手势配置
  const longPressGesture = Gesture.LongPress()
    .minDuration(200) // 长按触发阈值可自行调整
    .onStart(() => {
      runPreviewPlay();
    })
    .onEnd(() => {
      // 松开后立即停止预览,切回封面
      setIsPreviewing(false);
      videoRef.current?.pauseAsync();
      videoRef.current?.setPositionAsync(0);
    });

  return (
    <GestureDetector gesture={longPressGesture}>
      <View>
        <Video
          ref={videoRef}
          source={{ uri: videoUri }}
          style={{ width: 300, height: 200 }}
          usePoster
          posterSource={{ uri: posterUri }}
          onLoad={onVideoLoad}
          shouldPlay={false}
          isLooping={false}
        />
      </View>
    </GestureDetector>
  );
};

export default VideoPreviewItem;

可选优化项

  • 列表渲染阶段可以预加载视频元数据,避免长按后才获取时长产生的延迟
  • 可根据业务场景调整采样点规则,比如跳过检测到的黑帧、静帧区间
  • 预览播放时隐藏进度条、音量控件等非必要UI元素,只保留画面输出

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 11:45:04