Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Video Streaming using Entity Framework and HTML5 in MVC5

0.00/5 (No votes)
14 Oct 2016 1  
Convert uploaded video to MP4 and store it in database. Create thumbnail of the uploaded video and Stream the video from Database using HTML5 video tag and Entity Framework.

Introduction

In this Article, I am performing on How to store a video into Database? and How to stream it in MVC5 application?

Background

To perform this, no advance knowledge of ASP.NET MVC is needed. One should have knowledge of converting stream to bytes.

Using the code

Let's start. 

First of all we need to create a database and table. We need to identify, which are the fields to include in the table. Create database VideoStreaming and then create table with following fields.

SrNo, FileName, FileType and Video

Datatypes of the above filed are mentioned below.

USE [VideoStreaming]
GO

/****** Object:  Table [dbo].[VideoSteam]    Script Date: 24-08-2016 19:38:04 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[VideoSteam](
    [SrNo] [int] IDENTITY(1,1) NOT NULL,
    [FileName] [nvarchar](50) NOT NULL,
    [FileType] [nvarchar](20) NOT NULL,
    [Video] [varbinary](max) NOT NULL,
 CONSTRAINT [PK_Video] PRIMARY KEY CLUSTERED 
(
    [SrNo] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

After creating database and table, goto visual studio and Create new MVC5 project with no authentication.  Goto solution exporer. right click on models and then click New Item. and add ADO.Net Entity Data model. After adding Entity model, Add a Class file in same directory and name it VideoVM. This is the View Model we are going to use. Paste below lines in your View Model class file.

 public class VideoVM
    {
        public string Name { get; set; }

        public string ext { get; set; }

        public byte[] video { get; set; }

       public long id { get; set; }
    }

 

now add Home controller by right clicking on controller folder in solution exporer. Add Index view by right clicking on Index action and add view.

Open Index.cshtml page. add following lines in the page.

 

<div class="col-md-12">
        @using (Html.BeginForm("Index", "Home", FormMethod.Post, new { @id = "frmform", @enctype = "multipart/form-data" }))
        {
            <br />
            <table>
                <tr>
                    <td width="50px">Video</td>
                    <td class="text-center">
                        <input type="file" name="file" id="file" />
                    </td>
                    <td>
                        <button type="submit">Submit</button>
                    </td>
                </tr>
            </table>     
        }
    </div>

 

Here, we have created a form with post method. This will post the video file to Index action on Home controller. Here, we need to store the video to database.

Now goto controller and create Index action which is of HttpPost type.

to save a file in database we need to convert it into byte array. Create byte array. Read the file using MemoryStream and write it to byte array. After converting file to byte array we can store it in the database.

If user has uploaded any video rathar than MP4, than we need to convert it to MP4. For that I've used NReco Video convertor.

To add Nreco Video convertor to your project, open Package Manger console and run following command.

 

Install-Package NReco.VideoConverter

[http://www.nrecosite.com/video_converter_net.aspx]

 

After adding NReco reference to site, Refer the below code.

 

[HttpPost]  
public ActionResult Index(HttpPostedFileBase file)
        {
            VideoSteam video = new VideoSteam();

            if (file != null)
            {
                // store uploaded file to temporary folder
                string path = Server.MapPath("~/Upload/TempUpload/" + file.FileName);

                file.SaveAs(path);

                // Create new object of FFMpegConvertor
                var ffMpeg = new FFMpegConverter();
                var tname = Guid.NewGuid();

                // Path for converted videos
                string output = Server.MapPath("~/Upload/TempUpload/" + tname + ".mp4");

                // after conversion, video will be saved in Temporary folder.
                ffMpeg.ConvertMedia(path, output, Format.mp4);

                byte[] buffer = new byte[file.ContentLength];

                using (MemoryStream ms = new MemoryStream())
                {
                  //open converted video file, read it and write it to buffer
                  using (FileStream tempfile = new FileStream(output, FileMode.Open, FileAccess.Read))
                  {
                      buffer = new byte[tempfile.Length];
                      tempfile.Read(buffer, 0, (int)tempfile.Length);
                      ms.Write(buffer, 0, (int)tempfile.Length);
                  }
                }

                string fname = Guid.NewGuid().ToString();
                string ftype = "mp4";
           
                // Store video in database
                using (db = new DBEntities())
                {
                    video.FileName = fname;
                    video.FileType = ftype;
                    video.Video = buffer;

                    db.VideoSteams.Add(video);
                    db.SaveChanges();
                }
            }
            return RedirectToAction("Index","Home");
        }

 

Yea, we have saved the video in database. Now We need to show this video on our page where user can watch it.  
Add following line to Index Action of type HttpGet

 

[httpGet]
public ActionResult Index()
        {
            List<VideoVM> list = new List<VideoVM>(); //List object of View Model class
           
            using (db = new DbEntities())
            {
                //select list from database using linq query
                list = db.VideoSteams.Select(m=>new VideoVM {  
                    ext = m.FileType,
                    Name = m.FileName,
                    id = m.SrNo
                }).ToList();
            }
            return View(list);
        }
        

We have sent a list of type VideoVM to our view, which consist of list of videos saved in database. To show video on view add following line on the top of the cshtml page

 

@model List<VideoStreamingDemo.Models.VideoVM>

now add following lines to cshtml page. To render video on page, Video tag of HTML5 is used. We need to create an action which returns particular video. that action name is VideoStream which we need to give in src prop of Video tag. We need to also specify the video id to fetch particular video.

<div class="col-md-12">
        <ul class="list-inline">
            @foreach (var item in Model)
            {
                <li>
                <video width="100%" height="240" controls poster="@Url.Action("GetThumbnail", "Home", new { id = @item.id })">
                    <source src="@Url.Action("VideoStream","Home", new { id=@item.id})" type="video/@item.ext">
                </video>
                <label>@item.Name</label>
                    <a href="@Url.Action("DeleteVideo","Home", new { id=item.id})">Delete</a>
                </li>
            }
        </ul>
    </div>


Add following lines to controller. Here we need to create a void method. If we do so, we will not be able to call it from view. So EmptyResult method is used. When we returns EmptyResult then it is automatically converted to the type of Void().

 

VideoStream method will return video, where as GetThumnail method will return thumnail image. Thumnail creation reference http://www.joshholmes.com/blog/2009/01/27/returningthumbnailswiththemvcframework/

 [HttpGet]
        public EmptyResult VideoStream(long id = 0)
        {
            using (db = new DbEntities())
            {
                VideoVM vm = new VideoVM();
                vm = db.VideoSteams.Where(m => m.SrNo == id).Select(m => new VideoVM
                {
                    Name=m.FileName,
                    ext = m.FileType,
                    id = m.SrNo,
                    video = m.Video
                }).FirstOrDefault();  //fetch video from database of particular id
             

                HttpContext.Response.AddHeader("Content-Disposition", "attachment; filename="+vm.Name+"."+vm.ext);  //add header to httpcontext > response.
                HttpContext.Response.BinaryWrite(vm.video);  //write bytes to httpcontext response

                return new EmptyResult(); ;
            }

        }
        
     public ActionResult DeleteVideo(long id = 0)
        {
            if (id > 0)
            {
                using (db = new DbEntities())
                {
                    VideoSteam vs = new VideoSteam();
                    vs = db.VideoSteams.Where(m => m.SrNo == id).FirstOrDefault();

                    db.VideoSteams.Remove(vs);
                    db.SaveChanges();
                }
            }
                return RedirectToAction("Index", "Home");
        }


        public ActionResult GetThumbnail(long id)
        {
            using (db = new DBEntities())
            {
                // fetch video from database
                VideoSteam vs = new VideoSteam();
                vs = db.VideoSteams.Where(m => m.SrNo == id).FirstOrDefault();

                Image thumbnail = null;

                var ffMpeg = new NReco.VideoConverter.FFMpegConverter();
                float? frameTime = 07;

                var path = Server.MapPath("~/Upload/TempUpload/" + vs.FileName + "." + vs.FileType);
                
                //thumnail path
                string imageFilePath = Server.MapPath("~/Upload/TempUpload/" + vs.FileName + ".jpg");

                // Get thumnail using NReco.VideoConverter
                ffMpeg.GetVideoThumbnail(path, imageFilePath, frameTime);

                //Open image and read it to thumnail
                using (FileStream imageStream = new FileStream(imageFilePath, FileMode.Open, FileAccess.Read))
                {
                   thumbnail = Image.FromFile(imageFilePath);
                }

                using (MemoryStream ms = new MemoryStream())
                {
                    // Save thumbnail image
                    thumbnail.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);

                    // Add it to Response
                    HttpContext.Response.ContentType = "image/bmp";
                    HttpContext.Response.BinaryWrite(ms.ToArray());
                    HttpContext.Response.End();
                }

            }

            return new EmptyResult();
        }

        

 


reffering http://www.dotnetcurry.com/aspnet-mvc/998/play-videos-aspnet-mvc-custom-action-filter, it is found that to stream video we need to attach the bytes to the response of the page. As seen in above code, we have added header and wrote bytes to the response.

 

We are done. Run the project and Enjoy streaming.

 


Note : as stated in http://www.w3schools.com/tags/tag_video.asp only video of only three formats , MP4, webm and ogg , will be worked with HTML5 video tag. For this reason we have converted uploaded videos to MP4.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here