forked from langfuse/langfuse-docs
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathVideo.tsx
More file actions
119 lines (116 loc) · 3.28 KB
/
Video.tsx
File metadata and controls
119 lines (116 loc) · 3.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import { cn } from "@/lib/utils";
import {
MediaPlayer,
MediaOutlet,
useMediaRemote,
useMediaStore,
} from "@vidstack/react";
import { Play } from "lucide-react";
import { useState, useRef } from "react";
export const CloudflareVideo = ({
videoId,
aspectRatio,
className,
gifStyle = false,
poster,
posterStartTime = 1,
title,
}: {
videoId: string;
aspectRatio?: number;
gifStyle?: boolean;
className?: string;
poster?: string;
posterStartTime?: number;
title?: string;
}) => {
return (
<Video
src={`https://customer-xnej9vqjtgxpafyk.cloudflarestream.com/${videoId}/manifest/video.m3u8`}
poster={
poster ??
`https://customer-xnej9vqjtgxpafyk.cloudflarestream.com/${videoId}/thumbnails/thumbnail.gif?time=${posterStartTime}s`
}
aspectRatio={aspectRatio}
gifStyle={gifStyle}
className={className}
title={title}
/>
);
};
export const Video = ({
src,
poster,
aspectRatio,
className,
gifStyle = false,
title,
}: {
src: string;
poster?: string;
aspectRatio?: number;
gifStyle?: boolean;
className?: string;
title?: string;
}) => {
const [panelDismissed, setPanelDismissed] = useState(false);
const mediaPlayerRef = useRef(null);
const remote = useMediaRemote(mediaPlayerRef);
const { duration } = useMediaStore(mediaPlayerRef);
const durationString = duration
? `${Math.floor(duration / 60)}:${String(
Math.floor(duration % 60)
).padStart(2, "0")} min`
: null;
return (
<MediaPlayer
ref={mediaPlayerRef}
src={src}
controls={!gifStyle && panelDismissed}
autoplay={gifStyle}
muted={gifStyle}
loop={gifStyle}
load={gifStyle ? "eager" : "custom"}
playsinline={gifStyle}
aspectRatio={aspectRatio}
className={cn(
"my-4 overflow-hidden rounded shadow-lg ring-1 ring-slate-700 bg-cover object-cover",
className
)}
>
{gifStyle ? (
// Capture mouse events, they broke scrolling on iOS
<div className="absolute inset-0 z-10" />
) : !panelDismissed ? (
// Overlay with play button and poster image
<div
className="group cursor-pointer absolute inset-0 z-10 flex flex-col justify-center items-center bg-cover"
style={{
backgroundImage: poster ? `url(${poster})` : undefined,
}}
onMouseMove={() => {
remote.startLoading();
}}
onClick={() => {
remote.startLoading();
remote.play();
setPanelDismissed(true);
}}
>
<div className="p-3 md:p-6 rounded-full bg-black/80 group-hover:bg-black/90 group-hover:ring-8 ring-black/20 transition flex">
<Play className="h-6 w-6 text-white" />
</div>
<div className="mt-3 md:mt-6 transition-opacity duration-300">
<span className="flex gap-2 text-xs md:text-sm font-semibold bg-black/80 group-hover:bg-black/90 transition-all text-white py-1 px-3 rounded-full">
{title && <span>{title}</span>}
{durationString && (
<span className="text-white/70">{durationString}</span>
)}
</span>
</div>
</div>
) : null}
<MediaOutlet />
</MediaPlayer>
);
};