Bagus β ini cara yang benar: pelan tapi jadi.
Kita bikin kamu langsung lihat hasil hari ini, bukan kebanyakan teori.
π― TARGET HARI INI
π Website jalan di browser (lokal dulu)
π Bisa nampilin thumbnail
π Bisa klik β play video
Jangan mikir R2 / Hono dulu. Fokus ini dulu.
β‘ STEP 1 β Buat Folder Project
Di PC kamu:
video-site
Isi foldernya:
video-site/
index.html
style.css
app.js
data.json
β‘ STEP 2 β Copy File INI (WAJIB EXACT)
π§Ύ data.json (paling penting)
[
{
"title": "Sample Video",
"type": "mp4",
"src": "https://www.w3schools.com/html/mov_bbb.mp4",
"thumb": "https://peach.blender.org/wp-content/uploads/title_anouncement.jpg"
}
]
π Ini pakai video online dulu biar gak ribet
π index.html
<!DOCTYPE html>
<html>
<head>
<title>Video Gallery</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>My Video Gallery</h1>
<div id="gallery"></div>
<div id="playerModal" class="hidden">
<div class="player-content">
<span onclick="closePlayer()">X</span>
<div id="player"></div>
</div>
</div>
<script src="app.js"></script>
</body>
</html>
π¨ style.css
body {
background: #111;
color: white;
font-family: Arial;
}
#gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 10px;
}
.card img {
width: 100%;
border-radius: 8px;
}
βοΈ app.js
const gallery = document.getElementById("gallery");
const modal = document.getElementById("playerModal");
const player = document.getElementById("player");
fetch("data.json")
.then(res => res.json())
.then(data => {
data.forEach(item => {
const div = document.createElement("div");
div.className = "card";
div.innerHTML = `
<img src="${item.thumb}">
<p>${item.title}</p>
`;
div.onclick = () => openPlayer(item);
gallery.appendChild(div);
});
});
function openPlayer(item) {
modal.classList.remove("hidden");
player.innerHTML = `
<video controls autoplay width="100%">
<source src="${item.src}" type="video/mp4">
</video>
`;
}
function closePlayer() {
modal.classList.add("hidden");
player.innerHTML = "";
}
β οΈ STEP 3 β JANGAN DOUBLE CLICK
Kalau kamu buka index.html langsung β biasanya error (fetch JSON diblok)
π Pakai server sederhana:
πΉ Cara paling gampang (Node)
Di folder project:
npx serve
atau kalau belum ada:
npm install -g serve
serve
π STEP 4 β Buka di Browser
Biasanya:
http://localhost:3000
β HASIL YANG HARUS KAMU LIHAT
- Ada thumbnail video
- Ada judul
- Klik β video play
Kalau belum muncul β STOP dan kasih screenshot ke gue
(jangan lanjut dulu)
π¬ Penting banget
Jangan buru-buru ke:
- upload R2 β
- m3u8 β
- iframe β
π Kita pastikan:
βbasic engine jalan duluβ
π NEXT STEP (kalau ini sudah berhasil)
Baru kita lanjut:
π Step berikutnya:
- multi video
- tambah type (image, iframe, m3u8)
- auto generate JSON (ini nanti cocok banget sama workflow kamu π₯)
π Sekarang giliran kamu
Kerjakan Step 1β4 dulu.
Kalau sudah:
π bilang: "sudah jalan"
atau
π kirim errornya
Gue bantu debug sampai hidup β santai aja, kita gas pelan tapi pasti πͺ
Mantap. Berarti fondasi kamu sudah benar β ini penting banget.
Sekarang kita naik step kecil berikutnya, jangan lompat jauh.
π― TARGET STEP 2
π Bisa handle banyak konten
π Bisa beda type: mp4, image, iframe, m3u8
π Player lebih fleksibel (bukan cuma video)
β‘ STEP 2 β Upgrade data.json
Tambahin isi seperti ini:
[
{
"title": "Video MP4",
"type": "mp4",
"src": "https://www.w3schools.com/html/mov_bbb.mp4",
"thumb": "https://peach.blender.org/wp-content/uploads/title_anouncement.jpg"
},
{
"title": "Image Sample",
"type": "image",
"src": "https://picsum.photos/800/500",
"thumb": "https://picsum.photos/300/200"
},
{
"title": "YouTube Embed",
"type": "iframe",
"src": "https://www.youtube.com/embed/dQw4w9WgXcQ",
"thumb": "https://img.youtube.com/vi/dQw4w9WgXcQ/hqdefault.jpg"
},
{
"title": "HLS Stream",
"type": "m3u8",
"src": "https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8",
"thumb": "https://dummyimage.com/300x200/000/fff&text=HLS"
}
]
β‘ STEP 3 β Upgrade app.js
Ganti function openPlayer() jadi ini:
function openPlayer(item) {
modal.classList.remove("hidden");
if (item.type === "mp4") {
player.innerHTML = `
<video controls autoplay width="100%">
<source src="${item.src}" type="video/mp4">
</video>
`;
}
else if (item.type === "image") {
player.innerHTML = `
<img src="${item.src}" style="width:100%">
`;
}
else if (item.type === "iframe") {
player.innerHTML = `
<iframe src="${item.src}" width="100%" height="500" allowfullscreen></iframe>
`;
}
else if (item.type === "m3u8") {
player.innerHTML = `
<video id="hlsPlayer" controls autoplay width="100%"></video>
`;
const video = document.getElementById("hlsPlayer");
if (Hls.isSupported()) {
const hls = new Hls();
hls.loadSource(item.src);
hls.attachMedia(video);
} else {
video.src = item.src;
}
}
}
β‘ STEP 4 β Tambahin HLS.js (WAJIB untuk m3u8)
Di index.html, sebelum app.js:
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
π― HASIL YANG HARUS TERJADI
Sekarang kamu punya:
- π¬ video MP4 β play
- πΌοΈ image β tampil fullscreen
- βΆοΈ iframe β embed jalan
- π‘ m3u8 β streaming jalan
π Ini udah mini YouTube + streaming site versi kamu sendiri
β οΈ Kalau ada error (ini biasanya kejadian)
β m3u8 gak jalan
- biasanya lupa HLS.js
- atau URL stream gak valid
β iframe blank
- beberapa site blok embed (normal)
π¬ Real talk (penting)
Kalau kamu sudah sampai sini:
π kamu sudah punya engine video platform sendiri
Serius.
Tinggal nanti:
- auto generate JSON
- upload system
- UI polish
π Next step (kalau kamu lanjut)
Gue saranin urutan ini (jangan loncat):
- π§ Auto generate
data.jsondari folder/video - π¨ UI upgrade (hover play, grid Netflix style)
- βοΈ Integrasi R2 upload
- π Admin panel (optional)
π Sekarang
Coba dulu step ini.
Kalau sudah:
π bilang: "step 2 done"
Kalau error:
π kirim error / screenshot
Kita lanjut pelan tapi makin dalam π₯