从ffmpeg stdout管道的单个流中获取多个图像 [英] getting mulitple images from a single stream piped from ffmpeg stdout

查看:131
本文介绍了从ffmpeg stdout管道的单个流中获取多个图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开始一个过程,用ffmpeg从视频文件中检索几帧,

I start a process to retrieve a few frames from a video file with ffmpeg,

ffmpeg -i "<videofile>.mp4" -frames:v 10 -f image2pipe pipe:1

并将图像管道到stdout -

and pipe the images to stdout -

var cmd = Process.Start(p);
var stream = cmd.StandardOutput.BaseStream;
var img = Image.FromStream(stream);

以这种方式获取第一张照片,但是如何获得所有图像?

Getting the first image this way works, but how do I get all of them?

推荐答案

OK这是gobspackingly容易,有点尴尬我在这里问。我会发布答案,以防其他人有所帮助。

OK this was gobspackingly easy, kind of embarrassed I asked here. I'll post the answer in case it will help anyone else.

每次有新图像时,流中的前几个字节将被重复。我猜想前8个会做,瞧瞧。

The first few bytes in the stream will be repeated every time there is a new image. I guessed the first 8 would do and voila.

    static IEnumerable<Image> GetThumbnails(Stream stream)
    {
        byte[] allImages;
        using (var ms = new MemoryStream())
        {
            stream.CopyTo(ms);
            allImages = ms.ToArray();
        }
        var bof = allImages.Take(8).ToArray(); //??
        var prevOffset = -1;
        foreach (var offset in GetBytePatternPositions(allImages, bof))
        {
            if (prevOffset > -1)
                yield return GetImageAt(allImages, prevOffset, offset);
            prevOffset = offset;
        }
        if (prevOffset > -1)
            yield return GetImageAt(allImages, prevOffset, allImages.Length);
    }

    static Image GetImageAt(byte[] data, int start, int end)
    {
        using (var ms = new MemoryStream(end - start))
        {
            ms.Write(data, start, end - start);
            return Image.FromStream(ms);
        }
    }

    static IEnumerable<int> GetBytePatternPositions(byte[] data, byte[] pattern)
    {
        var dataLen = data.Length;
        var patternLen = pattern.Length - 1;
        int scanData = 0;
        int scanPattern = 0;
        while (scanData < dataLen)
        {
            if (pattern[0] == data[scanData])
            {
                scanPattern = 1;
                scanData++;
                while (pattern[scanPattern] == data[scanData])
                {
                    if (scanPattern == patternLen)
                    {
                        yield return scanData - patternLen;
                        break;
                    }
                    scanPattern++;
                    scanData++;
                }
            }
            scanData++;
        }
    }

这篇关于从ffmpeg stdout管道的单个流中获取多个图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆