VPE SDK를 활용한 다양한 플레이어 UI 데모를 확인하세요.

네이버클라우드
2026.01.30
메인 영상과 추천 영상 목록을 사이드바로 구성한 YouTube 스타일의 플레이어 데모입니다. 채널 정보, 좋아요/공유/저장 버튼 등 UGC 플랫폼에서 자주 사용하는 UI 패턴을 보여줍니다.
<div className="flex flex-col lg:flex-row gap-5">
{/* Main player */}
<div className="flex-1 min-w-0">
<div className="rounded-2xl overflow-hidden">
<VpePlayer
key={`yt-${currentIdx}`}
hls={Hls}
accessKey="YOUR_ACCESS_KEY"
options={{
playlist,
autostart: true,
muted: true,
aspectRatio: "16/9",
controls: true,
}}
layout={youtubeLayout}
/>
</div>
{/* Video info card */}
<div className="p-5 bg-neutral-900 rounded-2xl mt-5 flex justify-between">
<div>
<h2 className="text-white text-lg font-bold">
{playlist[currentIdx].description.title}
</h2>
<div className="flex items-center gap-3 mt-3">
<img
src={playlist[currentIdx].description.profile_image}
alt=""
className="w-10 h-10 rounded-full object-cover"
/>
<div>
<p className="text-white text-sm font-semibold">
{playlist[currentIdx].description.profile_name}
</p>
<p className="text-neutral-500 text-xs">
{playlist[currentIdx].description.created_at}
</p>
</div>
</div>
</div>
{/* Action buttons */}
<div className="flex gap-2">
{["좋아요", "공유", "저장"].map((label) => (
<button
key={label}
type="button"
className="px-4 py-2 bg-neutral-800 hover:bg-neutral-700 text-white text-xs font-semibold rounded-full transition-colors"
>
{label}
</button>
))}
</div>
</div>
</div>
{/* Sidebar: recommended videos */}
<aside className="lg:w-80 shrink-0 bg-neutral-900 overflow-y-auto rounded-2xl max-h-[645px]">
<div className="p-4 border-b border-neutral-800">
<h3 className="text-white font-bold text-sm">추천 영상</h3>
</div>
<div className="p-2 space-y-2">
{playlist.map((v, i) => (
<button
key={i}
type="button"
onClick={() => setCurrentIdx(i)}
className={`w-full flex items-start gap-2.5 p-2 rounded-lg text-left transition-colors cursor-pointer ${
i === currentIdx ? "bg-neutral-800" : "hover:bg-neutral-800/50"
}`}
>
<div className="relative w-40 shrink-0">
<img src={v.poster} alt="" className="w-full rounded-lg aspect-video object-cover" />
{i === currentIdx && (
<span className="absolute inset-0 flex items-center justify-center bg-black/50 rounded-lg text-white text-xs font-bold">
NOW
</span>
)}
</div>
<div className="min-w-0 flex-1 pt-0.5">
<p className={`text-sm font-medium line-clamp-2 ${
i === currentIdx ? "text-blue-400" : "text-neutral-200"
}`}>
{v.description.title}
</p>
<p className="text-xs text-neutral-500 mt-1">{v.description.profile_name}</p>
<p className="text-xs text-neutral-500">{v.description.created_at}</p>
</div>
</button>
))}
</div>
</aside>
</div>