2017-05-19 15 views
0

私はスクリーンビデオを録画し、次にMp4、Webm、または任意のビデオ形式で保存したいと思います。 SharpAviを使用してビデオを録画しています。下のコードは動画を録画していますが、停止後に保存できません。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); 


    } 
} 

}

答えて

0

あなたが最初の引数としてmethod`receivingファイル名を見ることができるので、これはあなたが同じように、あなたの出力ファイルのパスを渡す必要が

MP4または任意のフォーマットとして出力を保存するために
RecorderParams recparams = new RecorderParams("recordvideo",49,selectedCodec,100);` 

非常に簡単です

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

あなたはちょうどあなたがあなたの記録を開始するので、後にDisposeメソッド を呼び出す必要がどちらかあなたが任意のキーを押した後、それを記録したりしたいどのくらいの時間をハードコードする必要があります、ここでは、いずれかのキーを押したときに記録を開始するメインの例を示します。次に、いずれかのキーを押すと記録を停止します。

private void button1_Click(object sender, EventArgs e) 
{ 
    FourCC selectedCodec = KnownFourCCs.Codecs.MotionJpeg; 
    RecorderParams recparams = new RecorderParams("recordvideo",49,selectedCodec,100); 

    Console.WriteLine("Press any key to start recording "); 
    Console.ReadKey(); 
    Recorder record = new Recorder(recparams); 

    Console.WriteLine("Press any key to stop recording "); 
    Console.ReadKey(); 
    record.Dispose(); 

} 
+0

これは出力ファイルをどのように保存するのですか? – DumpsterDiver

+0

これはファイルを保存します。プロジェクトディレクトリに行く場合は、サポートされているコーデックを使用していることを確認してください。 Exmp: 'var rec = new Recorder(new RecorderParams(" recordedvideo "、10、SharpAvi.KnownFourCCs.Codecs.MotionJpeg、100)); ' –

関連する問題