如何在SharpAvi中保存录制视频

时间:2017-05-19 14:22:28

标签: c#

我想录制屏幕视频,然后保存为Mp4,Webm或任何视频格式。 我使用SharpAvi录制视频,下面的代码是录制视频,但我停止后无法保存,请帮助这是我的代码。

 namespace RecordScreenvideo
 {
// Used to Configure the Recorder
public class RecorderParams
{
    public RecorderParams(string filename, int FrameRate, FourCC Encoder, int Quality)
    {
        FileName = filename;
        FramesPerSecond = FrameRate;
        Codec = Encoder;
        this.Quality = Quality;

        Height = (int)SystemParameters.PrimaryScreenHeight;
        Width = (int)SystemParameters.PrimaryScreenWidth;
    }

    string FileName;
    public int FramesPerSecond, Quality;
    FourCC Codec;

    public int Height { get; private set; }
    public int Width { get; private set; }

    public AviWriter CreateAviWriter()
    {
        return new AviWriter(FileName)
        {
            FramesPerSecond = FramesPerSecond,
            EmitIndex1 = true,
        };
    }

    public IAviVideoStream CreateVideoStream(AviWriter writer)
    {
        // Select encoder type based on FOURCC of codec
        if (Codec == KnownFourCCs.Codecs.Uncompressed) return writer.AddUncompressedVideoStream(Width, Height);
        else if (Codec == KnownFourCCs.Codecs.MotionJpeg) return writer.AddMotionJpegVideoStream(Width, Height, Quality);
        else
        {
            return writer.AddMpeg4VideoStream(Width, Height, (double)writer.FramesPerSecond,
                // It seems that all tested MPEG-4 VfW codecs ignore the quality affecting parameters passed through VfW API
                // They only respect the settings from their own configuration dialogs, and Mpeg4VideoEncoder currently has no support for this
                quality: Quality,
                codec: Codec,
                // Most of VfW codecs expect single-threaded use, so we wrap this encoder to special wrapper
                // Thus all calls to the encoder (including its instantiation) will be invoked on a single thread although encoding (and writing) is performed asynchronously
                forceSingleThreadedAccess: true);
        }
    }
}
public class Recorder : IDisposable
{
    #region Fields
    AviWriter writer;
    RecorderParams Params;
    IAviVideoStream videoStream;
    Thread screenThread;
    ManualResetEvent stopThread = new ManualResetEvent(false);
    #endregion

    public Recorder(RecorderParams Params)
    {
        this.Params = Params;

        // Create AVI writer and specify FPS
        writer = Params.CreateAviWriter();

        // Create video stream
        videoStream = Params.CreateVideoStream(writer);
        // Set only name. Other properties were when creating stream, 
        // either explicitly by arguments or implicitly by the encoder used
        videoStream.Name = "Captura";

        screenThread = new Thread(RecordScreen)
        {
            Name = typeof(Recorder).Name + ".RecordScreen",
            IsBackground = true
        };

        screenThread.Start();
    }

    public void Dispose()
    {
        stopThread.Set();
        screenThread.Join();

        // Close writer: the remaining data is written to a file and file is closed
        writer.Close();

        stopThread.Dispose();
    }

    void RecordScreen()
    {
        var frameInterval = TimeSpan.FromSeconds(1 / (double)writer.FramesPerSecond);
        var buffer = new byte[Params.Width * Params.Height * 4];
        Task videoWriteTask = null;
        var timeTillNextFrame = TimeSpan.Zero;

        while (!stopThread.WaitOne(timeTillNextFrame))
        {
            var timestamp = DateTime.Now;

            Screenshot(buffer);

            // Wait for the previous frame is written
            videoWriteTask?.Wait();

            // Start asynchronous (encoding and) writing of the new frame
            videoWriteTask = videoStream.WriteFrameAsync(true, buffer, 0, buffer.Length);

            timeTillNextFrame = timestamp + frameInterval - DateTime.Now;
            if (timeTillNextFrame < TimeSpan.Zero)
                timeTillNextFrame = TimeSpan.Zero;
        }

        // Wait for the last frame is written
        videoWriteTask?.Wait();
    }

    public void Screenshot(byte[] Buffer)
    {
        using (var BMP = new Bitmap(Params.Width, Params.Height))
        {
            using (var g = Graphics.FromImage(BMP))
            {
                g.CopyFromScreen(Point.Empty, Point.Empty, new Size(Params.Width, Params.Height), CopyPixelOperation.SourceCopy);

                g.Flush();

                var bits = BMP.LockBits(new Rectangle(0, 0, Params.Width, Params.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);
                Marshal.Copy(bits.Scan0, Buffer, 0, Buffer.Length);
                BMP.UnlockBits(bits);
            }
        }
    }
}
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        FourCC selectedCodec = KnownFourCCs.Codecs.MotionJpeg;


        RecorderParams recparams = new RecorderParams("recordvideo",49,selectedCodec,100);

        Recorder record = new Recorder(recparams);


    }
}

}

2 个答案:

答案 0 :(得分:0)

您只需要调用dispose方法 因此,在您开始录制后,您需要硬编码您想要录制的时间或按下任意键后进行录制,这里是一个主要的示例,当您按任意键时它将开始录制然后它将停止录制后你按任意键。

[DllImport ("__Internal")]
private static extern string _GetLookupStatus ();

答案 1 :(得分:0)

将输出保存为mp4或任何格式非常简单,因为您可以看到方法`接收文件名作为第一个参数

 RecorderParams recparams = new RecorderParams("recordvideo",49,selectedCodec,100);`

所以你需要将输出文件路径作为

传递
   RecorderParams recparams = new RecorderParams("D:\\recordvideo.mp4",49,selectedCodec,100);`