jbilcke-hf HF staff commited on
Commit
9b37b82
1 Parent(s): d4e8cf1

add a delay to not load all videos at once

Browse files
src/app/interface/video-card/index.tsx CHANGED
@@ -1,6 +1,6 @@
1
  "use client"
2
 
3
- import { useRef, useState } from "react"
4
  import dynamic from "next/dynamic"
5
  import Link from "next/link"
6
  import { RiCheckboxCircleFill } from "react-icons/ri"
@@ -22,11 +22,13 @@ export function VideoCard({
22
  className = "",
23
  layout = "normal",
24
  onSelect,
 
25
  }: {
26
  video: VideoInfo
27
  className?: string
28
  layout?: "normal" | "compact"
29
  onSelect?: (video: VideoInfo) => void
 
30
  }) {
31
  const ref = useRef<HTMLVideoElement>(null)
32
  const [duration, setDuration] = useState(0)
@@ -36,6 +38,7 @@ export function VideoCard({
36
  `https://huggingface.co/datasets/jbilcke-hf/ai-tube-index/resolve/main/videos/${video.id}.webp`
37
  )
38
  const [videoThumbnailReady, setVideoThumbnailReady] = useState(false)
 
39
 
40
  const isCompact = layout === "compact"
41
 
@@ -67,6 +70,12 @@ export function VideoCard({
67
  }
68
  }
69
 
 
 
 
 
 
 
70
  return (
71
  <Link href={`/watch?v=${video.id}`}>
72
  <div
@@ -89,28 +98,37 @@ export function VideoCard({
89
  isCompact ? `w-42 h-[94px]` : `aspect-video`
90
  )}
91
  >
92
- <div className="relative w-full">
93
- <video
 
 
 
94
  ref={ref}
95
  src={video.assetUrl}
96
  className={cn(
97
  `w-full h-full`,
 
98
  duration > 0 ? `opacity-100`: 'opacity-0',
99
  `transition-all duration-500`,
100
  )}
101
  onLoadedMetadata={handleLoad}
102
  muted
103
- />
104
  <img
105
  src={videoThumbnail}
106
  className={cn(
107
  `absolute`,
108
- `rounded-lg`,
 
 
109
  videoThumbnailReady ? `opacity-100`: 'opacity-0',
110
  `hover:opacity-0 w-full h-full top-0 z-30`,
111
  //`pointer-events-none`,
112
- `transition-all duration-500 hover:delay-200 ease-in-out`,
113
  )}
 
 
 
114
  onLoad={() => {
115
  setVideoThumbnailReady(true)
116
  }}
@@ -122,7 +140,8 @@ export function VideoCard({
122
  </div>
123
 
124
  <div className={cn(
125
- ``,
 
126
  `w-full flex flex-row items-end justify-end`
127
  )}>
128
  <div className={cn(
 
1
  "use client"
2
 
3
+ import { useEffect, useRef, useState } from "react"
4
  import dynamic from "next/dynamic"
5
  import Link from "next/link"
6
  import { RiCheckboxCircleFill } from "react-icons/ri"
 
22
  className = "",
23
  layout = "normal",
24
  onSelect,
25
+ index
26
  }: {
27
  video: VideoInfo
28
  className?: string
29
  layout?: "normal" | "compact"
30
  onSelect?: (video: VideoInfo) => void
31
+ index: number
32
  }) {
33
  const ref = useRef<HTMLVideoElement>(null)
34
  const [duration, setDuration] = useState(0)
 
38
  `https://huggingface.co/datasets/jbilcke-hf/ai-tube-index/resolve/main/videos/${video.id}.webp`
39
  )
40
  const [videoThumbnailReady, setVideoThumbnailReady] = useState(false)
41
+ const [shouldLoadVideo, setShouldLoadVideo] = useState(false)
42
 
43
  const isCompact = layout === "compact"
44
 
 
70
  }
71
  }
72
 
73
+ useEffect(() => {
74
+ setTimeout(() => {
75
+ setShouldLoadVideo(true)
76
+ }, index * 500)
77
+ }, [index])
78
+
79
  return (
80
  <Link href={`/watch?v=${video.id}`}>
81
  <div
 
98
  isCompact ? `w-42 h-[94px]` : `aspect-video`
99
  )}
100
  >
101
+ <div className={cn(
102
+ `relative w-full`,
103
+ isCompact ? `w-42 h-[94px]` : `aspect-video`
104
+ )}>
105
+ {videoThumbnailReady && shouldLoadVideo ? <video
106
  ref={ref}
107
  src={video.assetUrl}
108
  className={cn(
109
  `w-full h-full`,
110
+ `aspect-video`,
111
  duration > 0 ? `opacity-100`: 'opacity-0',
112
  `transition-all duration-500`,
113
  )}
114
  onLoadedMetadata={handleLoad}
115
  muted
116
+ /> : null}
117
  <img
118
  src={videoThumbnail}
119
  className={cn(
120
  `absolute`,
121
+ `aspect-video`,
122
+ // `aspect-video object-cover`,
123
+ `rounded-lg overflow-hidden`,
124
  videoThumbnailReady ? `opacity-100`: 'opacity-0',
125
  `hover:opacity-0 w-full h-full top-0 z-30`,
126
  //`pointer-events-none`,
127
+ `transition-all duration-500 hover:delay-300 ease-in-out`,
128
  )}
129
+ onMouseEnter={() => {
130
+ setShouldLoadVideo(true)
131
+ }}
132
  onLoad={() => {
133
  setVideoThumbnailReady(true)
134
  }}
 
140
  </div>
141
 
142
  <div className={cn(
143
+ // `aspect-video`,
144
+ `z-40`,
145
  `w-full flex flex-row items-end justify-end`
146
  )}>
147
  <div className={cn(
src/app/interface/video-list/index.tsx CHANGED
@@ -36,13 +36,14 @@ export function VideoList({
36
  className,
37
  )}
38
  >
39
- {videos.map((video) => (
40
  <VideoCard
41
  key={video.id}
42
  video={video}
43
  className="w-full"
44
  layout={layout === "vertical" ? "compact" : "normal"}
45
  onSelect={onSelect}
 
46
  />
47
  ))}
48
  </div>
 
36
  className,
37
  )}
38
  >
39
+ {videos.map((video, i) => (
40
  <VideoCard
41
  key={video.id}
42
  video={video}
43
  className="w-full"
44
  layout={layout === "vertical" ? "compact" : "normal"}
45
  onSelect={onSelect}
46
+ index={i}
47
  />
48
  ))}
49
  </div>