question

AedmaMartin-3923 avatar image
0 Votes"
AedmaMartin-3923 asked AedmaMartin-3923 commented

Serving video file / stream from ASP Net Core 6 Minimal API

Hi, I'm coming from NodeJs background and trying to get into building API's with ASP Net Core. I am experimenting with .Net Core 6 Minimal API as it looks quite familiar and simple to get going. I'm working on a project for streaming videos and I'm currently stuck on trying to figure out how do I serve / stream a video file for frontend?

I was trying different tutortials in

I have this bare minimal setup code for API with a single GET path "/video" mapped. I also made a folder "wwwroot" inside project folder. I placed in there a mp4 video file named "test.mp4". Would it be possible for someone knowledgeable to write a simple example of how to stream this file inside my mapped route ?


 var builder = WebApplication.CreateBuilder(args);
    
 builder.Services.AddEndpointsApiExplorer();
 builder.Services.AddSwaggerGen();
    
 var app = builder.Build();
    
 if (app.Environment.IsDevelopment())
 {
     builder.Logging.AddJsonConsole();
     app.UseSwagger();
     app.UseSwaggerUI();
 }
    
 app.UseHttpsRedirection();
    
 app.MapGet("/video", () =>
 {    
    
    
 });
    
 app.Run();

dotnet-aspnet-core-generaldotnet-aspnet-core-webapi
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

ZhiLv-MSFT avatar image
1 Vote"
ZhiLv-MSFT answered AedmaMartin-3923 commented

Hi @AedmaMartin-3923,

In the Asp.net core Minimal API application, you can use the Results.File to return file to download from your minimal APIs handler, like this:

 app.MapGet("/video", (int id) =>
 {
     var filename = "file_example.mp4";
     //Build the File Path.
     string path = Path.Combine(_hostenvironment.WebRootPath, "files/") + filename;  // the video file is in the wwwroot/files folder
    
     var filestream = System.IO.File.OpenRead(path);
     return Results.File(filestream, contentType: "video/mp4", fileDownloadName: filename, enableRangeProcessing: true); 
 });

Then, in the main view page, use the video tag to display the video:

   <video autoplay controls src="https://localhost:7093/video?id=1"></video>

The result is like this:

172471-image.png


If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

Best regards,
Dillion


image.png (189.1 KiB)
· 4
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hi @ZhiLv-MSFT
I did this solution and faced a problem.
When I open view in one browser video play correctly.
but when I open second browser video failed.

the error is "The process cannot access the file 'video path' because it is being used by another process"
cant be play in multi browser at same time.

1 Vote 1 ·
AedmaMartin-3923 avatar image AedmaMartin-3923 MohammadShafiei-7877 ·

Could anyone update answer how it would work with multiple client's accessing same file ?

0 Votes 0 ·

Hei,

I've modified my app now to use controlled based web API, and I tried to modify this example to work there but I am getting error.
This is in controller

 [HttpGet]
 [Route("PlayVideo")]
 [ProducesResponseType(StatusCodes.Status200OK)]
 [ProducesResponseType(StatusCodes.Status500InternalServerError)]
 public async Task<IResult> PlayVideo()
 {
     try
     {
         var fileName = "sample.mp4";
         string path = Path.Combine(_env.WebRootPath, "files/") + fileName;  // the video file is in the wwwroot/files folder

         var filestream = System.IO.File.OpenRead(path);
         return Results.File(filestream, contentType: "video/mp4", fileDownloadName: fileName, enableRangeProcessing: true);
     }
     catch (Exception ex)
     {
         _logger.LogError(ex, $"Something Went Wrong in the {nameof(PlayVideo)}");
         return Results.BadRequest();
     }

 }

and in frontend I have this

 <video controls src="https://localhost:7227/api/Videos/PlayVideo"></video>

Error I currently get is

System.InvalidOperationException: Timeouts are not supported on this stream.
at System.IO.Stream.get_ReadTimeout() ...

0 Votes 0 ·

I found a piece of code on stackoverflow by which I was able to get it working, I changed controller to this

 [HttpGet]
     [Route("PlayVideo")]
     [ProducesResponseType(StatusCodes.Status200OK)]
     [ProducesResponseType(StatusCodes.Status500InternalServerError)]
     public FileResult PlayVideo()
     {
         var fileName = "sample.mp4";
         string path = Path.Combine(_env.WebRootPath, "files/") + fileName;
         return PhysicalFile(path, contentType: "application/octet-stream", enableRangeProcessing: true);
     }

But since I am very beginner on the this subject I have a couple of questions:
1. Is this a proper solution or could it be better ?
2. Can I, and if so should I and how to make this work with async / await ?
3. If I put [Authorize] with JWT Bearer token on this route, how do I send token in frontend ? I'm using React on frontend if this information is of use.

My goal is to build a simple streaming service.

If these question are drifting away from original topic, I could also make new one.



0 Votes 0 ·