从上传的视频流生成缩略图?

时间:2014-05-09 13:41:01

标签: c# video azure ffmpeg

我正在构建一个页面供人们使用C#,.NET MVC和Azure上传视频文件。这些文件存储在Azure blob存储中。我想在上传期间生成缩略图。但我发现从视频生成缩略图的唯一解决方案是使用ffmpeg包装器,这些只能在文件系统上的实际文件上运行,而不是流。有没有办法从流中捕获静止?该视频仅作为blob或流提供,我实际上无法存储用于制作缩略图的本地副本。任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:2)

您可以使用VideoConverter FFMpeg wrapper实现目标(获取缩略图) - 它使用stdin / stdout管道支持实时流转换。一般的想法是将流转换为原始视频(实际上是位图帧流)并使用适当的帧作为缩略图。

请注意,这仅适用于“可流式”视频格式(例如,MP4无法作为实时流处理)。

答案 1 :(得分:1)

回答我自己的问题,因为我根据Kashif Imran撰写的这篇文章创建了一个有效的解决方案 http://www.codeproject.com/Tips/496864/Getting-Thumbnail-from-Video-using-MediaPlayer-Cla

以下代码每800毫秒会生成一个新缩略图。

    public static IEnumerable<ThumbnailData> GenerateThumbnails(string mediaFile, int amount, System.Drawing.Size? imagesize)
    {
        System.Drawing.Size size = imagesize ?? new System.Drawing.Size(120, 80);
        MediaPlayer player = new MediaPlayer { Volume = 0, ScrubbingEnabled = true };

        player.Open(new Uri(mediaFile));
        player.Pause();
        //We need to give MediaPlayer some time to load. 
        System.Threading.Thread.Sleep(800);
        var totalduration = player.NaturalDuration;
        if (!totalduration.HasTimeSpan)
        {
            yield break;
        }
        double avglen = totalduration.TimeSpan.TotalMilliseconds / (amount + 1d);
        for (int frameId = 0; frameId < amount; frameId++)
        {
            var timespan = avglen * (frameId + 1);
            var offset = TimeSpan.FromMilliseconds(timespan);
            player.Position = offset;
            player.Play();
            player.Pause();

            System.Threading.Thread.Sleep(400);

            RenderTargetBitmap rtb = new RenderTargetBitmap(size.Width, size.Height, 96, 96, PixelFormats.Pbgra32);
            DrawingVisual dv = new DrawingVisual();
            using (DrawingContext dc = dv.RenderOpen())
            {
                dc.DrawVideo(player, new Rect(0, 0, size.Width, size.Height));
            }
            rtb.Render(dv);
            Duration duration = player.NaturalDuration;

            BitmapFrame frame = BitmapFrame.Create(rtb).GetCurrentValueAsFrozen() as BitmapFrame;
            BitmapEncoder encoder = new JpegBitmapEncoder();
            encoder.Frames.Add(frame as BitmapFrame);
            MemoryStream memoryStream = new MemoryStream();
            encoder.Save(memoryStream);
            //Here we have the thumbnail in the MemoryStream!
            memoryStream.Seek(0, SeekOrigin.Begin);
            var thumbnail = new Bitmap(memoryStream);

            yield return new ThumbnailData { Offset = offset, Image = thumbnail };
        }

        player.Close();
    }

答案 2 :(得分:0)

您可以使用HTML5,读取本地文件,生成缩略图并将其上传到服务器,请查看本文http://www.html5rocks.com/en/tutorials/file/dndfiles/。生成缩略图的javascript必须使用ffmpeg在本地或服务器上完成。

相关位将是文件切片功能

<style>
  #byte_content {
    margin: 5px 0;
    max-height: 100px;
    overflow-y: auto;
    overflow-x: hidden;
  }
  #byte_range { margin-top: 5px; }
</style>

<input type="file" id="files" name="file" /> Read bytes: 
<span class="readBytesButtons">
  <button data-startbyte="0" data-endbyte="4">1-5</button>
  <button data-startbyte="5" data-endbyte="14">6-15</button>
  <button data-startbyte="6" data-endbyte="7">7-8</button>
  <button>entire file</button>
</span>
<div id="byte_range"></div>
<div id="byte_content"></div>

<script>
function readBlob(opt_startByte, opt_stopByte) {
    var files = document.getElementById('files').files;
    if (!files.length) {
      alert('Please select a file!');
      return;
    }

    var file = files[0];
    var start = parseInt(opt_startByte) || 0;
    var stop = parseInt(opt_stopByte) || file.size - 1;

    var reader = new FileReader();

    // If we use onloadend, we need to check the readyState.
    reader.onloadend = function(evt) {
        if (evt.target.readyState == FileReader.DONE) { // DONE == 2
            document.getElementById('byte_content').textContent = evt.target.result;
        document.getElementById('byte_range').textContent = 
            ['Read bytes: ', start + 1, ' - ', stop + 1,
             ' of ', file.size, ' byte file'].join('');
        }
    };

    **var blob = file.slice(start, stop + 1);
    reader.readAsBinaryString(blob);**
}

document.querySelector('.readBytesButtons').addEventListener('click', function(evt) {
    if (evt.target.tagName.toLowerCase() == 'button') {
        var startByte = evt.target.getAttribute('data-startbyte');
        var endByte = evt.target.getAttribute('data-endbyte');
        readBlob(startByte, endByte);
    }
}, false);
</script>

另一种方法是使用HTML5 canvas元素播放视频并生成缩略图,如Create thumbnail from video without ffmpeg in PHP

所述