ybabts
ybabts2y ago

HTTP 206 + HTML5 video streaming with Fresh

how do I implement an endpoint to stream a video to a HTML video player using HTTP 206 in Fresh? Here's what I have so far however it doesn't seem to be working.
import { HandlerContext } from "$fresh/server.ts";
import { Err, isErr, Ok } from "eav/mod.ts";

const video = await Deno.readFile("./static/assets/hero.mp4");

const chunkSize = 1024 * 1024 * 10;

export async function handler(
req: Request,
ctx: HandlerContext,
): Promise<Response> {
if (req.headers.has("range")) {
const range = Ok(parseRange(req.headers.get("range")!)) ??
{ start: 0, end: NaN };
if (range.start === 0 && isNaN(range.end)) {
return new Response(video.slice(0, chunkSize), {
status: 206,
headers: {
"Content-Type": "video/mp4",
"Content-Length": chunkSize.toString(),
"Content-Range": `bytes 0-100/${video.length}`,
"Accept-Ranges": "bytes",
},
});
}
const end = isNaN(range.end) ? range.start + chunkSize : range.end;
return new Response(video.slice(range.start, end), {
status: 206,
headers: {
"Content-Type": "video/mp4",
"Content-Length": chunkSize.toString(),
"Content-Range": `bytes ${range.start}-${end}/${video.length}`,
"Accept-Ranges": "bytes",
},
});
}
return new Response(null, {
status: 404,
});
}

function parseRange(range: string) {
if (!range.includes("bytes=")) {
return new Err("invalid range");
}
const [_, rangeStr] = range.split("=");
const [start, end] = rangeStr.split("-");
return { start: parseInt(start), end: parseInt(end) };
}
import { HandlerContext } from "$fresh/server.ts";
import { Err, isErr, Ok } from "eav/mod.ts";

const video = await Deno.readFile("./static/assets/hero.mp4");

const chunkSize = 1024 * 1024 * 10;

export async function handler(
req: Request,
ctx: HandlerContext,
): Promise<Response> {
if (req.headers.has("range")) {
const range = Ok(parseRange(req.headers.get("range")!)) ??
{ start: 0, end: NaN };
if (range.start === 0 && isNaN(range.end)) {
return new Response(video.slice(0, chunkSize), {
status: 206,
headers: {
"Content-Type": "video/mp4",
"Content-Length": chunkSize.toString(),
"Content-Range": `bytes 0-100/${video.length}`,
"Accept-Ranges": "bytes",
},
});
}
const end = isNaN(range.end) ? range.start + chunkSize : range.end;
return new Response(video.slice(range.start, end), {
status: 206,
headers: {
"Content-Type": "video/mp4",
"Content-Length": chunkSize.toString(),
"Content-Range": `bytes ${range.start}-${end}/${video.length}`,
"Accept-Ranges": "bytes",
},
});
}
return new Response(null, {
status: 404,
});
}

function parseRange(range: string) {
if (!range.includes("bytes=")) {
return new Err("invalid range");
}
const [_, rangeStr] = range.split("=");
const [start, end] = rangeStr.split("-");
return { start: parseInt(start), end: parseInt(end) };
}
I would bash my head against this some more but I'm going to sleep so I figure if someone knows it'll be useful. I plan on making a middleware to automatically stream any content that is over a certain size.
0 Replies
No replies yetBe the first to reply to this messageJoin