diff --git a/server.ts b/server.ts index f75da21..53c0c70 100644 --- a/server.ts +++ b/server.ts @@ -55,8 +55,41 @@ app.get("/podcast_audio/*", async (c) => { const file = Bun.file(audioFilePath); if (await file.exists()) { - const blob = await file.arrayBuffer(); - return c.body(blob, 200, { "Content-Type": "audio/mpeg" }); + const fileSize = file.size; + const range = c.req.header("range"); + + if (range) { + // Handle range requests for streaming + const parts = range.replace(/bytes=/, "").split("-"); + const start = parseInt(parts[0] || "0", 10); + const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1; + + if (start >= fileSize) { + return c.text("Requested range not satisfiable", 416, { + "Content-Range": `bytes */${fileSize}`, + }); + } + + const chunkSize = (end - start) + 1; + const stream = file.stream(); + + return c.body(stream, 206, { + "Content-Type": "audio/mpeg", + "Content-Range": `bytes ${start}-${end}/${fileSize}`, + "Accept-Ranges": "bytes", + "Content-Length": chunkSize.toString(), + "Cache-Control": "public, max-age=31536000", + }); + } else { + // Serve entire file with streaming support + const stream = file.stream(); + return c.body(stream, 200, { + "Content-Type": "audio/mpeg", + "Content-Length": fileSize.toString(), + "Accept-Ranges": "bytes", + "Cache-Control": "public, max-age=31536000", + }); + } } return c.notFound(); } catch (error) {