简体   繁体   English

如何使用 C# 和 .NET 核心制作转码视频文件流

[英]How can I make a Transcoded Video Filestream using C# and .NET Core

Overview概述

I'm currently working on a media streaming server using ASP.net Core REST Server.我目前正在使用 ASP.net Core REST 服务器开发媒体流服务器。 I'm currently using .net 5.0 and ASP.net Core MVC我目前正在使用 .net 5.0 和 ASP.net Core MVC

What I need我需要的

I need to be able to dynamically down-res the original video file.我需要能够动态降低原始视频文件的分辨率。 from 1080p to 720p for example.例如,从1080p720p Also I need to be able to make the media file able to be transcoded to a different encoding based on client capabilities.此外,我需要能够使媒体文件能够根据客户端功能转码为不同的编码。

What I've Tried我试过的

I've been looking for a library that can manage this feat, but I can't seem to find one.我一直在寻找可以管理这一壮举的图书馆,但我似乎找不到。 I thought FFMpeg would be able to do this.我认为 FFMpeg 能够做到这一点。 I know this is possible because applications like plex and emby seem to manage this.我知道这是可能的,因为像 plex 和 emby 这样的应用程序似乎可以管理这个。

What I've Done我做了什么

[HttpGet("/api/streaming/video")]
public IActionResult GetFile()
{
    string path = "C:\Path\To\Video\FILE.mp4";
    System.IO.FileStream stream = new(path, System.IO.FileMode.Open, System.IO.FileAccess.Read);
    Microsoft.AspNetCore.Mvc.FileStreamResult file = File(stream, "video/mp4", true);
    return file;
}

Framework Tried框架尝试

  • Xabe.FFmpeg Xabe.FFmpeg
  • FFMpegSharp FFMpegSharp

Given that you need this to work cross platform, as @Andy said the best solution is ffmpeg.鉴于您需要它来跨平台工作,正如@Andy 所说,最好的解决方案是 ffmpeg。 You have two choices:你有两个选择:

  1. Invoke the ffmpeg command line utility from your web process;从 web 进程调用 ffmpeg 命令行实用程序; or或者
  2. Compile the libav library suite (which underlies ffmpeg) to each native platform your code might be run on - Windows, Linux, etc. - make a native DLL wrapper, and use P/Invoke in your ASP.NET project to access it. Compile the libav library suite (which underlies ffmpeg) to each native platform your code might be run on - Windows, Linux, etc. - make a native DLL wrapper, and use P/Invoke in your ASP.NET project to access it.

Command Line Utility命令行实用程序

The command line utility is very easy to use and well documented.命令行实用程序非常易于使用并且有据可查。 Documentation is here .文档在这里 Your basic approach would be to include ffmpeg.exe in your web project (make sure you have a version for each platform), and use Process.Start to invoke it, using the command line arguments to point it to your video file and configure the output.您的基本方法是在您的 web 项目中包含 ffmpeg.exe(确保每个平台都有一个版本),并使用Process.Start调用它,使用命令行 arguments 将其配置为指向您的视频文件output。 Once the output is finished, you can serve it by returning with File like in your example. output 完成后,您可以像示例中一样通过返回File来提供它。 There are also some open source .NET wrappers like this one that could save you some of the work.还有一些像这样的开源 .NET 包装器可以为您节省一些工作。 Unfortunately the command line utility doesn't offer much (any) control once started, or a programmatic way of determining progress.不幸的是,命令行实用程序一旦启动就不能提供太多(任何)控制,也不能提供确定进度的编程方式。 However, these issues should not be a problem if you follow my recommendation at the end.但是,如果您最后遵循我的建议,这些问题应该不是问题。

Libav利巴夫

If you do need or want total control, however - including frame by frame transcoding, progress reporting, etc. - then you would need to use libav.但是,如果您确实需要或想要完全控制 - 包括逐帧转码、进度报告等 - 那么您将需要使用 libav。 Before going further, note that you need to use at least some C/C++ to use libav.在继续之前,请注意您至少需要使用一些 C/C++ 才能使用 libav。 That means your server code is going to have to run with full trust, and you WILL be susceptible to the security risks of running native code.这意味着您的服务器代码必须在完全信任的情况下运行,并且您将容易受到运行本机代码的安全风险的影响。 (Though the same would be true if you used ffmpeg.exe, but at least in that case you don't run the risk of introducing NEW security risks through your own code). (虽然如果您使用 ffmpeg.exe 也是如此,但至少在这种情况下,您不会冒通过自己的代码引入新安全风险的风险)。

Also know that you can't just find nice clean, always up-to-date downloadable binaries for every platform (at least one reason for which is fear of patent lawsuits).还要知道,您不能只为每个平台找到干净、始终最新的可下载二进制文件(至少有一个原因是担心专利诉讼)。 Instead you have to build it yourself for every platform your code might run on.相反,您必须为您的代码可能运行的每个平台自己构建它。 Find your platform(s) on here and then follow the instructions to the letter .此处找到您的平台,然后按照信中的说明进行操作。 If you make a single deviation no matter how small, you won't be able to build it, and you will pull your hair out figuring out why.如果你做出一个偏差,无论多么小,你都无法建造它,你会拔出头发找出原因。

Once you have the builds, then your next major task is to expose the APIs you need to your C# code.一旦你有了构建,你的下一个主要任务就是向你的 C# 代码公开你需要的 API。 The documentation for the libav APIs is not a model of clarity. libav API 的文档不是清晰的 model。 They more or less assume you will look at the code for the ffmpeg command line utility to figure out how to use libav, and that's what you should do.他们或多或少假设您将查看 ffmpeg 命令行实用程序的代码以了解如何使用 libav,这就是您应该做的。 But if you invest the time (days if not weeks) to construct the builds and learn the APIs, you will become a Master of Media.但是,如果您投入时间(几天甚至几周)来构建构建并学习 API,您将成为媒体大师。 There is virtually nothing imaginable that you can't do using libav.几乎没有什么是您无法使用 libav 完成的。

Now you're finally ready to integrate this into your app.现在您终于可以将其集成到您的应用程序中了。 Again you can take two approaches.同样,您可以采取两种方法。 If you're quite comfortable with C/C++, you should make a new C/C++ DLL project, link the libav DLLs to it, and do most of the heavy lifting there and just export couple of entrypoint functions that you can invoke from C#.如果你对 C/C++ 非常熟悉,你应该创建一个新的 C/C++ DLL 项目,将 libav DLL 链接到它,并在那里完成大部分繁重的工作,然后导出几个可以从 C# 调用的入口点函数. Alternatively, you can P/Invoke directly to the libav DLLs, but you will need to do a ton of scaffolding of data structures and functions in C#.或者,您可以直接 P/Invoke 到 libav DLL,但您将需要在 C# 中对数据结构和函数进行大量搭建。 Unless you're extremely comfortable with marshalling, I would not attempt this.除非您对编组非常满意,否则我不会尝试这样做。

In fact, I'm going to recommend going the command line utility route, because -事实上,我会推荐使用命令行实用程序路线,因为 -

You Shouldn't Try to Transcode On The Fly Anyway无论如何,您都不应该尝试即时转码

With all that out of the way, let's talk about your actual gameplan.综上所述,让我们谈谈你的实际游戏计划。 You said you need to "dynamically" convert the video based on what the client wants/can receive.您说您需要根据客户想要/可以接收的内容“动态”转换视频。 No one does this.没有人这样做。 What they do do is create multiple versions of the videos in advance and save each one on the server eg, a 1080p, 720p, 480p, and maybe even 240p version.他们所做的是提前创建多个版本的视频并将每个版本保存在服务器上,例如 1080p、720p、480p 甚至 240p 版本。 Then, the client application monitors the connection quality and, also considering the user's preference, directs the media player to the desired version.然后,客户端应用程序监控连接质量,并考虑用户的偏好,将媒体播放器定向到所需的版本。 The server always serves the version requested and doesn't convert on the fly.服务器始终提供请求的版本,并且不会即时转换。 Unless you're talking about streaming live events - and if so then that's beyond the scope of my expertise - this is what you should do.除非您在谈论流媒体直播活动 - 如果是这样,那么这超出了我的专业知识 scope - 这就是您应该做的。

So, what I would advise is use the ffmpeg utility to create different versions of the videos in advance - as part of an import or upload process for example.因此,我建议使用 ffmpeg 实用程序提前创建不同版本的视频 - 例如,作为导入或上传过程的一部分。 Track the videos in a database including what versions are available for each.跟踪数据库中的视频,包括每个可用的版本。 Give the client a way to obtain this information.为客户提供获取此信息的方法。 Then when it comes time to serve the videos, you just serve the one the client requests in a query parameter.然后,当需要提供视频时,您只需在查询参数中提供客户端请求的视频。 Put the logic for determining the desired version on the client - either connection speed and/or user preference.将确定所需版本的逻辑放在客户端上 - 连接速度和/或用户偏好。

And Don't Forget to Support Content-Range Requests并且不要忘记支持内容范围请求

Finally, you probably don't want to just use File to serve the media unless the users are just going to download the files for offline viewing.最后,您可能不想只使用File来提供媒体服务,除非用户只是要下载文件以供离线查看。 Assuming people are going to play videos in a browser, you need your API to accept content-range request headers.假设人们要在浏览器中播放视频,您需要您的 API 接受content-range请求标头。 Here's a pretty good example of how to do that. 这是一个很好的例子来说明如何做到这一点。 Provided you implement it correctly, web browser media players will be able to play, seek, etc., transparently.如果您正确实施,web 浏览器媒体播放器将能够透明地播放、搜索等。 If for whatever reason the format needs to change, just redirect the URL of the media player to the appropriate version, keep the position the same, and resume playing, and the user will barely notice a skip.如果出于某种原因需要更改格式,只需将媒体播放器的 URL 重定向到适当的版本,保持 position 相同,然后继续播放,用户几乎不会注意到跳过。

Hope at least some of this helps!希望至少有一些帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我可以使用C#中的文件流将类的obj发送到文件吗? - Can I send an obj of a class to a file using filestream in C#? 如何在 C# 中将整数写入 FileStream? - How can I write a Integer to a FileStream in C#? 如何在C#中的FileStream中插入字节 - How I can insert bytes in a FileStream in C# 我如何打开外部 memory 文件,因为 FileStream 是 c# - How can I open External memory file as FileStream is c# .NET核心是否支持SqlFileStream或使用C#从SQL Server中获取文件流的任何其他方法? - .NET core support for SqlFileStream or any alternative way to get a filestream out of SQL Server using C#? 如何将 C# 类作为字符串 UserInput,并使其可用于 ASP.NET Core 运行时? - How can I take a C# Class, as a string UserInput, and make it available to the ASP.NET Core runtime? C#.NET中FileStream的替代品 - Alternative to FileStream in C# .NET C#.net核心如何使用npgsql检索所有行 - C# .net core how can I retrieve all rows using npgsql C#如何使用Filestream读取目录中的所有jpeg文件,以便文件不被锁定? - C# How can I read all jpeg files in a directory using a Filestream so the files aren't locked? 如何通过仅使用.NET Core SDK直接调用C#编译器来编译.NET Standard 2.0类库? - How can I compile a .NET Standard 2.0 class library by directly invoking the C# complier using only the .NET Core SDK?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM