Streaming MP4 Videos on Kestrel
Kestrel is a cross-platform web server for ASP.NET Core that can serve static files, including MP4 videos. However, serving large video files directly can lead to performance issues and may not support features like seeking.
To stream MP4 videos effectively, you can implement range requests, which allow clients to request specific byte ranges of the video file. This is particularly useful for video playback, as it enables seeking and resuming playback without downloading the entire file.
Here's how you can set up Kestrel to stream MP4 videos by adding the following code to your program.cs file.:
app.MapGet("/videos/{*path}", async context =>
{
var path = (string?)context.Request.RouteValues["path"];
var fileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "videos"));
var fileInfo = fileProvider.GetFileInfo(path?.Replace("..", "") ?? "");
context.Response.Headers.Add("Accept-Ranges", "bytes");
Console.WriteLine($"Requesting video: {path}");
if (fileInfo.Exists)
{
var rangeHeader = context.Request.Headers["Range"].ToString();
if (!string.IsNullOrEmpty(rangeHeader))
{
var range = rangeHeader.Replace("bytes=", "").Split('-');
var end = fileInfo.Length-1; // Default to the end of the file
if (range.Length > 1 && long.TryParse(range[1], out long endRange))
{
end = endRange;
}
if (range.Length == 2 && long.TryParse(range[0], out long start))
{
var fileLength = fileInfo.Length;
if (start < 0 || end >"= fileLength || start > end)
{
context.Response.StatusCode = 416; // Range Not Satisfiable
return;
}
context.Response.StatusCode = 206; // Partial Content
context.Response.Headers.Add("Content-Range", $"bytes {start}-{end}/{fileLength}");
context.Response.ContentLength = end - start + 1;
await context.Response.SendFileAsync(fileInfo, start, end - start + 1);
return;
}
}
context.Response.ContentType = "video/mp4";
context.Response.StatusCode = 206; // Partial Content
}
else
{
context.Response.StatusCode = 404;
}
});
In this code:
- We define a route to handle requests for video files.
- We check if the requested video file exists.
- If the "Range" header is present, we parse it to determine the byte range requested by the client.
- We validate the requested range and set the appropriate response headers, including "Content-Range" and "Accept-Ranges".
- Finally, we send the requested byte range of the video file to the client.
This setup allows clients to request specific parts of the video file, enabling features like seeking and resuming playback. Make sure to test your implementation with various video players to ensure compatibility.
Now you can stick videos in a folder at the root called videos and serve files out from it. Be sure to only put videos as it will try to stream out any file located in videos.
Copy Over Your Video Files on Build
To ensure your video files are copied to the output directory during the build process, you can add the following item group to your .csproj file:
<ItemGroup>
<Content Include="videos\**" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
This will copy all files in the "videos" directory to the output directory when you build your project, ensuring that your video files are available for streaming.