C# 为什么当我尝试使用directshow将视频捕获到mp4文件时,该文件是空的?

C# 为什么当我尝试使用directshow将视频捕获到mp4文件时,该文件是空的?,c#,.net,winforms,directshow,C#,.net,Winforms,Directshow,当我退出程序时,mp4文件会自动删除 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using DirectShowL

当我退出程序时,mp4文件会自动删除

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DirectShowLib;
using DirectShowLib.BDA;
using DirectShowLib.DES;
using DirectShowLib.DMO;
using DirectShowLib.Dvd;
using DirectShowLib.MultimediaStreaming;
using DirectShowLib.SBE;
using System.Runtime.InteropServices;
using System.Management;
using System.IO;
using AForge.Video;
using AForge.Video.DirectShow;
using AForge.Video.FFMPEG;
using AForge.Video.VFW;
using System.Drawing.Imaging;


namespace Youtube_Manager
{

    public partial class Elgato_Video_Capture : Form
    {
        IFileSinkFilter sink;

        IFilterGraph2 graph;
        ICaptureGraphBuilder2 captureGraph;
        Size videoSize;
        string error = "";
        List<Object> devices = new List<Object>();
        IMediaControl mediaControl;

        public Elgato_Video_Capture()
        {
            InitializeComponent();

            if (comboBox1.Items.Count == 0)
            {
                for (int xx = 1; xx <= 8; xx++)
                {
                    comboBox1.Items.Add(xx);
                }
            }

            InitDevice();

        }

        IPin outPin;
        IPin inPin;
        private void InitDevice()
        {
            try
            {
                //Set the video size to use for capture and recording
                videoSize = new Size(827, 505);//1280, 720);

                //Initialize filter graph and capture graph
                graph = (IFilterGraph2)new FilterGraph();
                captureGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
                captureGraph.SetFiltergraph(graph);
                //Create filter for Elgato
                Guid elgatoGuid = new Guid("39F50F4C-99E1-464A-B6F9-D605B4FB5918");
                Type comType = Type.GetTypeFromCLSID(elgatoGuid);
                IBaseFilter  elgatoFilter = (IBaseFilter)Activator.CreateInstance(comType);
                graph.AddFilter(elgatoFilter, "Elgato Video Capture Filter");

                //Create smart tee filter, add to graph, connect Elgato's video out to smart tee in
                IBaseFilter smartTeeFilter = (IBaseFilter)new SmartTee();

                graph.AddFilter(smartTeeFilter, "Smart Tee");
                outPin = GetPin(elgatoFilter, "Video");
                inPin = GetPin(smartTeeFilter, "Input");               

                graph.Connect(outPin, inPin);

                //Create video renderer filter, add it to graph, connect smartTee Preview pin to video renderer's input pin
                IBaseFilter videoRendererFilter = (IBaseFilter)new VideoRenderer();

                graph.AddFilter(videoRendererFilter, "Video Renderer");
                outPin = GetPin(smartTeeFilter, "Capture");

                inPin = GetPin(videoRendererFilter, "Input");
                graph.Connect(outPin, inPin);

                captureGraph.SetOutputFileName(MediaSubType.Avi, @"e:\screenshots\test1.mp4", out smartTeeFilter, out sink);
                sink.SetFileName(@"e:\screenshots\test1.mp4", null);

                //Render stream from video renderer
                captureGraph.RenderStream(PinCategory.Capture, MediaType.Video, videoRendererFilter, null, null);
                //Set the video preview to be the videoFeed panel
                IVideoWindow vw = (IVideoWindow)graph;
                vw.put_Owner(pictureBox1.Handle);
                vw.put_MessageDrain(this.Handle);
                vw.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipSiblings | WindowStyle.ClipChildren);
                vw.SetWindowPosition(0, 0, 827, 505);

                //Start the preview
                mediaControl = graph as IMediaControl;
                mediaControl.Run();

            }
            catch (Exception err)
            {
                error = err.ToString();
            }
        }

         IPin GetPin(IBaseFilter filter, string pinname)
        {
            IEnumPins epins;
            int hr = filter.EnumPins(out epins);
            checkHR(hr, "Can't enumerate pins");
            IntPtr fetched = Marshal.AllocCoTaskMem(4);
            IPin[] pins = new IPin[1];
            while (epins.Next(1, pins, fetched) == 0)
            {
                PinInfo pinfo;
                pins[0].QueryPinInfo(out pinfo);
                bool found = (pinfo.name == pinname);
                DsUtils.FreePinInfo(pinfo);
                if (found)
                    return pins[0];
            }
            checkHR(-1, "Pin not found");
            return null;
        }

        public  void checkHR(int hr, string msg)
        {
            if (hr < 0)
            {
                MessageBox.Show(msg);
                DsError.ThrowExceptionForHR(hr);
            }            
        }
}
我看到了预览,但mp4文件是空的,根本没有将视频保存到该文件中。 我想做的是使用directshow将视频流保存到mp4文件中。 现在我所能得到的就是在一个图片盒里看到视频的预览

  • 您不会捕获到MP4文件,而是捕获到仅具有MP4扩展名的AVI文件!DirectShow没有本机MP4多路复用器。你需要安装一个单独的像

  • 我认为你的连接不正常。使用DirectShowNet,您需要检查返回代码,然后自己抛出异常,如:

    int hr = graph.Connect(outPin, inPin);;
    DsError.ThrowExceptionForHR(hr);
    
  • 您的
    captureGraph.RenderStream
    无效,因为VideoRender筛选器没有输出引脚。请看地图。您可以使用RenderStream更好地构建此图,它甚至可以为您插入SmartTee过滤器


  • 好吧,现在我不想使用mp4多路复用器,但即使没有压缩,也要将其保存到avi文件中。首先,我想能够捕捉视频的权利。对于数字2,我现在看到它抛出异常2147220969,但我不知道这个数字的含义。我想,如果我看到预览视频,那么它似乎是工作。我想我错了。这是错误号:这是您的错误:0x80040217:找不到中间筛选器的组合来建立连接。也就是说,vfw_e_无法连接。您正在尝试连接不可连接的对象。最好是使用GraphiEdit或在代码中创建图形之前。Elgato设备的输出媒体类型是什么?Yopu在MediaType.Video的RenderStream中的意思是什么?我看到:{73646976-0000-0010-8000-00aa00389b71}这是MediaType_视频的GUID。不,我是说你有哪种媒体?它是未压缩格式还是h.264流?
    int hr = graph.Connect(outPin, inPin);;
    DsError.ThrowExceptionForHR(hr);