You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用FFMpegCore从视频MemoryStream/byte[]截取快照无需存储物理文件

问题根因

你遇到的错误由三个核心配置问题导致:

  • ffmpeg读取管道流时默认的探测大小和分析时长不足,无法正确解析h264流的编码参数,错误日志也明确提示了需要调整analyzeduration和probesize参数
  • 输出配置冲突:你指定了视频编码为png,但强制输出格式为rawvideo,两种格式不兼容导致输出流解析失败
  • 管道流本身不支持随机seek,你在输入参数中添加的Seek(captureTime)配置无法生效,ffmpeg读取管道时无法直接跳转到指定时间点

修复后的完整代码

首先修改BuildSnapshotArguments方法,补充流探测配置,调整seek逻辑:

private static (FFMpegArguments, Action<FFMpegArgumentOptions> outputOptions) BuildSnapshotArguments(
    IPipeSource input,
    IMediaAnalysis source,
    Size? size = null,
    TimeSpan? captureTime = null,
    int? streamIndex = null,
    int inputFileIndex = 0)
{
    captureTime ??= TimeSpan.FromSeconds(source.Duration.TotalSeconds / 3);
    size = PrepareSnapshotSize(source, size);
    streamIndex ??= source.PrimaryVideoStream?.Index
                    ?? source.VideoStreams.FirstOrDefault()?.Index
                    ?? 0;

    return (FFMpegArguments
        .FromPipeInput(input, options => options
             // 增加流探测大小和分析时长,确保ffmpeg能正确识别编码参数
             .WithProbeSize(100_000_000) // 100MB探测大小,可根据实际视频大小调整
             .WithAnalyzeDuration(TimeSpan.FromSeconds(10))), // 最长10秒分析时长
        options => options
            // 管道不支持输入侧seek,改为输出侧跳转到指定时间点
            .Seek(captureTime)
            .SelectStream((int)streamIndex, inputFileIndex)
            .WithVideoCodec(VideoCodec.Png)
            .WithFrameOutputCount(1)
            .Resize(size));
}

然后修改SnapshotAsync方法的输出配置,修正格式冲突:

public static async Task<Bitmap> SnapshotAsync(Stream input, IMediaAnalysis source, Size? size = null, TimeSpan? captureTime = null, int? streamIndex = null, int inputFileIndex = 0)
{
    input.Seek(0, SeekOrigin.Begin);
    var streamPipeSource = new FFMpegCore.Pipes.StreamPipeSource(input)
    {
        // 可选:调整块大小适配大体积视频
        BlockSize = 4096 * 1024
    };
    var (arguments, outputOptions) = BuildSnapshotArguments(streamPipeSource, source, size, captureTime, streamIndex, inputFileIndex);
    using var ms = new MemoryStream();

    await arguments
        // 输出格式改为image2匹配png编码,不要用rawvideo
        .OutputToPipe(new StreamPipeSink(ms), options => outputOptions(options
            .ForceFormat("image2")))
        .ProcessAsynchronously().ConfigureAwait(false);

    ms.Position = 0;
    return new Bitmap(ms);
}

调用说明

你现有的调用逻辑不需要修改,直接传入MemoryStream即可正常截取快照,不需要将视频写入物理磁盘。如果处理超大体积视频,可以适当上调WithProbeSize的参数值。

内容的提问来源于stack exchange,提问作者Akash Kadia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 23:57:04