【问题标题】:ASP.NET MVC upload video file and convert it from HttpPostedFileBase to image files(frames)ASP.NET MVC 上传视频文件并将其从 HttpPostedFileBase 转换为图像文件(帧)
【发布时间】:2018-03-27 01:39:31
【问题描述】:

我想上传一个视频文件,并在我的 ASP.NET MVC 项目中获取第一帧(或指定的帧)作为缩略图。

控制器:

[HttpPost]
public ActionResult Upload(HttpPostedFileBase file)
{
   // How to get the video file frames(or first frame) here
   // or Microsoft Azure Blob Storage provide the service to do this?
   // (I upload file to Microsoft Azure Blob)
}

【问题讨论】:

标签: asp.net-mvc-5 video-processing azure-blob-storage


【解决方案1】:

根据我的理解,您可以使用包装器VideoFileReader 利用 FFmpeg 库来读取视频文件。以下是官方文档中的示例:

// create instance of video reader
VideoFileReader reader = new VideoFileReader();
// open video file
reader.Open("test.avi");
// check some of its attributes
Console.WriteLine("width:  " + reader.Width);
Console.WriteLine("height: " + reader.Height);
Console.WriteLine("fps:    " + reader.FrameRate);
Console.WriteLine("codec:  " + reader.CodecName);
// read 100 video frames out of it
for(int i = 0; i < 100; i++)
{
    Bitmap videoFrame = reader.ReadVideoFrame();
    // process the frame somehow
    // ...

    // dispose the frame when it is no longer required
    videoFrame.Dispose();
}
reader.Close();

注意:您可能需要将 FFmpeg 二进制文件 (DLL) 复制到您的 Web 应用程序中。对于 AForge.Video.FFMPEG 包,您可以关注here 或类似的issue

回到您的场景,您可能需要将HttpPostedFileBase.InputStream 临时存储到一个临时文件中,然后使用该临时文件来初始化VideoFileReader 实例。

要将文件上传到 Azure Blob 存储,您可以利用 UploadFromFileUploadFromStream 等。详细教程,可以关注here


更新:

我检查了 AForge.Video.FFMPEG,发现它不能再工作了。根据我的测试,您可以安装源自 AForge.NET Framework 并且是处理视频的 Accord.NET Framework 的一部分的 Accord.Video.FFMPEG 包。您只需要更改引用的命名空间,这是我在控制台应用程序上的测试代码:

using Accord.Video.FFMPEG;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleFfmpeg
{
    class Program
    {
        static void Main(string[] args)
        {
            // create instance of video reader
            VideoFileReader reader = new VideoFileReader();
            // open video file
            reader.Open(AppDomain.CurrentDomain.BaseDirectory+ @"Videos\FlickAnimation.avi");
            // check some of its attributes
            Console.WriteLine("width:  " + reader.Width);
            Console.WriteLine("height: " + reader.Height);
            Console.WriteLine("fps:    " + reader.FrameRate);
            Console.WriteLine("codec:  " + reader.CodecName);
            //read video frames
            for (int i = 0; i < reader.FrameCount; i++)
            {
                Bitmap videoFrame = reader.ReadVideoFrame();
                // process the frame somehow
                videoFrame.Save(AppDomain.CurrentDomain.BaseDirectory + $"Videos\\{i}.bmp");
                // dispose the frame when it is no longer required
                videoFrame.Dispose();
            }
            reader.Close();
            Console.ReadLine();
        }
    }
}

结果:

【讨论】:

  • 我将 'externals' 文件夹中的所有 dll 复制到我的项目中,但它仍然显示有关依赖项的错误
  • 我刚刚检查了它,请参阅我关于新解决方案的更新部分。
  • 再次更新更好。 Accord 已经死了而且太老了,你不能在任何 .Net 5+ 项目上使用它。
【解决方案2】:

为了获取快照,我使用了FFmpeg tool

它是一个用于演示的控制台应用程序,同样的逻辑也可以用于 Web。

public class Ffmpeg
{
    Process _ffmpeg;

    private void Exec(string input, string output, string duration)
    {
        _ffmpeg = new Process();

        _ffmpeg.StartInfo.Arguments = $"-ss {duration} -i {input} -vframes 1 {output}";

        // Path of Exe which will be in folder Q:\\ConsoleVideo\\ConsoleVideo\\utils\\ffmpeg.exe
        _ffmpeg.StartInfo.FileName = "Q:\\ConsoleVideo\\ConsoleVideo\\utils\\ffmpeg.exe";
        _ffmpeg.StartInfo.UseShellExecute = false;
        _ffmpeg.StartInfo.RedirectStandardOutput = true;
        _ffmpeg.StartInfo.RedirectStandardError = true;
        _ffmpeg.StartInfo.CreateNoWindow = true;          
        _ffmpeg.Start();
        _ffmpeg.WaitForExit();
        _ffmpeg.Close();
    }

    public void GetThumbnail(string video, string jpg, string duration)
    {
        Exec(video, jpg, duration);  //hh:mm:ss.fff
    }
}


class Program
{
    static void Main(string[] args)
    {
        Ffmpeg f = new Ffmpeg();
        // GetThumbnail ("Video Input Path" , "Image OutPut Path" , "Time Frame of Snapshot" ) [hh:mm:ss.fff]
        f.GetThumbnail("Q:\\ConsoleVideo\\ConsoleVideo\\videos\\Wildlife.wmv", "C:\\Users\\1438\\Downloads\\thumb.jpg", "00:00:25.000");
    }
}

项目结构

保存在utils文件夹中的FFmpeg exe可以从here下载。

【讨论】:

  • 我可以将帧放到 MemoryStream 中,而不是另存为文件吗?我试过 $"-ss {duration} -i {input} -vframes 1 -f {extension} pipe:" 参考:stackoverflow.com/questions/19634749/… 但是输出流 colud 没有使用。
  • @gary 它将根据您传递给它的时间从视频中获取快照,不返回 MemoryStream
  • 所以...,如果我想将快照(缩略图)上传到azure blob存储,我必须先保存到网络服务器,然后读取要上传的文件?
  • @gary 对,您需要存储在服务器上获取缩略图,然后获取缩略图的 base64string 格式并推送到您要存储的位置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-07
  • 1970-01-01
  • 2011-08-31
  • 1970-01-01
  • 2020-04-16
  • 1970-01-01
相关资源
最近更新 更多