如何使用 ASP.NET MVC 流式传输视频文件

本文关键字:传输 视频 文件 MVC 何使用 ASP NET | 更新日期: 2023-09-27 18:34:28

我正在开发一个网站,人们可以在其中访问音频和视频文件。我有下载文件的代码,它由以下两种操作方法组成......

public ActionResult GetAudioFile(int id) {
  return GetFile(id, true);
}
public ActionResult GetVideoFile(int id) {
  return GetFile(id, false);
}
private ActionResult GetFile(int id, bool isAudio) {
  // Code to get info about the file, etc omitted for clarity
  string downloadFileName = // full path to audio/video file
  byte[] bytes = GetFileBytes(fileName); // also omitted
  return File(bytes, (isAudio ? "audio/mpeg" : "video/mp4"), downloadFileName + (isAudio ? ".mp3" : ".mp4"));
}

这些都可以正常工作,我可以下载任何一种类型的文件。

我现在想添加两个 Razor 视图,一个用于收听音频文件,另一个用于查看视频。我在音频视图上做了以下操作,它工作正常...

<audio src='@Url.Action("GetAudioFile", "Search", new {ID = @Model.ID})'
               controls preload="auto"></audio>

然后我尝试对视频视图做同样的事情......

<video src='@Url.Action("GetVideoFile", "Search", new {ID = @Model.ID})' 
               controls preload="auto" width="640" height="368"></video>

但是,当我尝试运行它时,这会产生一个System.OutOfMemoryException。每个视频平均约为400-500Mb。

然后,我尝试使用Response.TransmitFile方法,如下所示...

  Response.ContentType = "video/mp4";
  Response.AddHeader("content-disposition", "attachment; filename=myvideo.mp4"));
  Response.TransmitFile(fileName);
  Response.End();
  return null;

。但这行不通。在Chrome中,我可以在控制台中看到消息"资源解释为文档,但使用MIME类型视频/mp4传输",而在FireFox中,我在视频控件中收到相同的消息。

有人知道我该如何解决这个问题吗?理想情况下,我想流式传输文件,以便在第一个字节到达用户后立即开始播放,而不是让他们等到文件完全下载。

我已经尝试了几个Javascript视频播放器,但都取得了任何成功。

更新我想知道问题是否根本不是控制器操作,因为我尝试将 Web 浏览器直接指向视频文件,我得到了看起来像音频播放器的东西,但没有视频窗格,当我单击播放按钮时没有任何反应。不确定这是否有帮助。

如何使用 ASP.NET MVC 流式传输视频文件

MvcControllerFile方法返回一个FileContentResult。后者不流式传输内容。据我所知,MvcController根本不支持流媒体。

您可能想尝试ApiControllerPushStreamContent。后者提供了通过回调方法异步写入输出流的可能性。为此,您需要在解决方案中使用实际流。使用 byte[] 将始终将整个文件内容加载到内存中。

在此处查看详细教程:使用 ASP.NET Web API 异步流式传输视频

从数据库/PC播放视频的可能方法

<div height="240" width="320" controls>
      <video>
             <source src="@Url.Content(Model.VideoTable.VideoPath)" type='video/mp4' />
      </video>
</div>

源属性需要获取 url 而不是字符串,

所以@Url.Content将视频路径转换为 URL

控制器

Imports System.Web.Mvc
Namespace Controllers
    Public Class HomeController
        Inherits Controller
        Function Index() As ActionResult
            Return View()
        End Function
        Sub movie(id As Integer) 'As ActionResult
            Dim fm As String = "D:'Downloads'Rhoma Irama  Riza Umami - Suratan (Official Music Video).mp4"
            If id = 2 Then fm = "D:'Downloads'JERA riza umami   lagu dangdut   YouTube.mp4"
            If id = 3 Then fm = "D:'Downloads'FTV Trans TV CINTANYA ANAK HITS KEKINIAN RIDWAN GHANI.mp4"
            Dim fi As New IO.FileInfo(fm)
            Dim fs As IO.FileStream = IO.File.OpenRead(fm)
            Dim buff_size As Integer = 1048576 '1Mb buffering
            Dim buff(buff_size) As Byte, max_l As Integer = fs.Length - 1
            If Not Request.ServerVariables("HTTP_RANGE") Is Nothing Then
                Dim r() As String = Request.ServerVariables("HTTP_RANGE").Split("=")
                Dim s() As String = r(1).Split("-")
                Dim bs As Integer = 0, be As Integer = 0, l As Integer = 0
                If IsNumeric(s(0)) Then bs = s(0)
                If IsNumeric(s(1)) Then be = s(1)
                If bs >= 0 And bs <= max_l Then
                    Response.StatusCode = 206
                    Response.ContentType = "video/" & fi.Extension
                    Response.AddHeader("Accept-Ranges", "0-" & max_l)
                    Response.AddHeader("Content-Range", "bytes " & bs & "-" & bs + buff_size & "/" & max_l)
                    Response.AddHeader("Content-Length", buff_size)
                    fs.Position = bs
                    l = fs.Read(buff, 0, buff.Length)
                    If l > 0 Then Response.OutputStream.Write(buff, 0, buff.Length)
                End If
            End If
        End Sub
    End Class
End Namespace

视图(我使用剃刀(

<body>
    <button onclick="video1.src='@Url.Action("movie", "home", New With {.id = 1})'">1</button>
    <button onclick="video1.src='@Url.Action("movie", "home", New With {.id = 2})'">2</button>
    <button onclick="video1.src='@Url.Action("movie", "home", New With {.id = 3})'">3</button>
    <video controls autoplay="autoplay" id="video1" width="920">
        <source src="@Url.Action("movie", "home", New With {.id = 1})" type="video/mp4">
        Your browser does not support HTML5 video.
    </video>  
</body>