Laden...

Video aufzeichnen und speichern mit USB-Cam

Erstellt von Richard95 vor 7 Jahren Letzter Beitrag vor 7 Jahren 2.794 Views
R
Richard95 Themenstarter:in
10 Beiträge seit 2016
vor 7 Jahren
Video aufzeichnen und speichern mit USB-Cam

Hallo,

ich versuche seit geraumer Zeit mit einer am PC angeschlossenen USB-Cam ein avi-Video von 20sec aufzuzeichnen und zu speichern. Habe mir das Ganze überlegt mit einem Timer von 20sec zu machen. Ich nutze die Libaries von AForgeNET. Leider haut das Ganze bisher nicht hin. Vielleicht kann mir jemand auf die Sprünge helfen wo der Fehler/die Fehler liegen.

private void buttonStart_Click(object sender, EventArgs e)
        {
            VideoCaptureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
            captureDevice = new VideoCaptureDeviceForm();

            if (captureDevice.ShowDialog(this) == DialogResult.OK)
            {

                VideoCaptureDevice videoSource = captureDevice.VideoDevice;
                FinalVideo = captureDevice.VideoDevice;

                FinalVideo.NewFrame += new NewFrameEventHandler(FinalVideo_NewFrame);
                FinalVideo.Start();
            }

            stopVideo = false;
            duration = 20;


            while (video == null)
            { }
            video.Save("U:\\a.avi");

            int h = captureDevice.VideoDevice.VideoResolution.FrameSize.Height;
            int w = captureDevice.VideoDevice.VideoResolution.FrameSize.Width;
            AVIwriter.Open("U:\\a.avi", w, h);

            timer1.Enabled = true;
            timer1.Start();

            //while (stopVideo == false)
            //{ }

        }
        void FinalVideo_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {
            if (stopVideo==true)
            {
                video = (Bitmap)eventArgs.Frame.Clone();
                AVIwriter.Quality = 0;
                AVIwriter.AddFrame(video); //addd new frame to pend video file
            }
            else
            {
                video = (Bitmap)eventArgs.Frame.Clone();
            }
        }


       
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (FinalVideo == null)
            { return; }
            if (FinalVideo.IsRunning)
            {
                this.FinalVideo.Stop();
                this.AVIwriter.Close();
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            duration--;

            textBox1.Text = duration.ToString();

            if (duration ==0)
            {
                timer1.Stop();
                stopVideo = true;

                if (FinalVideo == null)
                { return; }

                if (FinalVideo.IsRunning)
                {
                    this.FinalVideo.Stop();
                    this.AVIwriter.Close();
                }
            }
        }

Guten Abend,
Richard

16.842 Beiträge seit 2008
vor 7 Jahren

Willkommen im Forum.

"Funktioniert nicht" ist keine ausreichende Beschreibung. [Hinweis] Wie poste ich richtig?
Bitte erklär, was genau nicht funktioniert und wo Du aktuell nicht weiter kommst.

R
Richard95 Themenstarter:in
10 Beiträge seit 2016
vor 7 Jahren

Hallo,

habe mir jetzt die Spielregeln durchgelesen 😉 und versuche das Problem konkreter zu beschreiben:

Der Timer läuft wie er soll runter von 20 auf 0. Sprich das Video sollte dann auch 20sec lang sein (Interval ist auf 1000ms). Allerdings ist mein Video 10sec lang. Was noch fataler ist: Das Video ist ein Standbild. Habe also eine Videodatei auf der keine Bewegung zu sehen ist. Ich möchte aber ein ganz normales Video. Es scheint so, als ob nur ein einziger Frame gezogen wird und der AVIWriter das defaultmäßig auf 10sec zieht. Ich hoffe ich konnte mein Problem jetzt besser darlegen 😉

Gruß
Richard

Hinweis von Abt vor 7 Jahren

Bitte keine Fullquotes. Auch das steht in [Hinweis] Wie poste ich richtig?

R
228 Beiträge seit 2013
vor 7 Jahren

Was auch immer 'video' ist, für mich sieht das so aus, als würdest du der Variabel immer nur ein Bitmap zuweisen?



  void FinalVideo_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {

            if (stopVideo==true)
            {
                2) Erst wenn du das Video stoppst, wird video (1 Bitmap) dem AVIwriter hinzugefügt
                video = (Bitmap)eventArgs.Frame.Clone();
                AVIwriter.Quality = 0;
                AVIwriter.AddFrame(video); //addd new frame to pend video file
            }
            else
            {
    1)            video wird ein Bitmapt zugewiesen
                video = (Bitmap)eventArgs.Frame.Clone();
            }
        }


R
Richard95 Themenstarter:in
10 Beiträge seit 2016
vor 7 Jahren

Was auch immer 'video' ist, für mich sieht das so aus, als würdest du der Variabel immer nur ein Bitmap zuweisen?

Video ist auch eine Bitmap.

private Bitmap video = null;

So wie ich den AVIWriter verstehe fügt er mehrere Bitmaps zu einem Video zusammen:

AVIwriter.AddFrame(video);

Inzwischen bekomme ich jetzt auch das Video das ich möchte nur die Zeit stimmt nicht überein.

Habe es jetzt mal mit einem Timer von 60sec versucht.

Ergebnis:

Bei 60sec dauert das Video nur 53 sec.

EDIT: Leider ist mir aufgefallen, dass auch die Dauer des Videos auch stark von der eingestellten Auflösung meiner USB-Kamera abhängt. Je größer die Auflösung desto kürzer das Video bei gleicher Zeit.

Ein weiterer negativer Nebeneffekt das Video braucht 1,15GB für 53sec Video. Erscheint mir etwas viel.

Ich poste nochmal meinen aktuellen Code. Ich weis man soll nur Schnipsel einfügen, aber ich denke um die Zusammenhänge zu sehen zwischen Events und Handler ist das nötig. Wie gesagt das Video machen funktioniert. Allerdings mit falschen Zeiten:

using System;
using System.Drawing;
using System.Windows.Forms;
using AForge.Video;
using AForge.Video.DirectShow;
using AForge.Video.VFW;


namespace WindowsFormsApplication13
{
    public partial class Form1 : Form
    {
        private FilterInfoCollection VideoCaptureDevices;
        private VideoCaptureDevice FinalVideo = null;
        private VideoCaptureDeviceForm captureDevice;
        private Bitmap video = null;
        private AVIWriter AVIwriter = new AVIWriter();
        private int duration ;

        private bool stopVideo;
        //private SaveFileDialog saveAvi;
        public Form1()
        {
            InitializeComponent();
        }

        private void butStart_Click(object sender, EventArgs e)
        {
            stopVideo = false;
            duration = 60;


            VideoCaptureDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
            captureDevice = new VideoCaptureDeviceForm();

            if (captureDevice.ShowDialog(this) == DialogResult.OK)
            {
                VideoCaptureDevice videoSource = captureDevice.VideoDevice;
                FinalVideo = captureDevice.VideoDevice;

                FinalVideo.NewFrame += new NewFrameEventHandler(FinalVideo_NewFrame);
                FinalVideo.Start();
                                
            }

            int h = captureDevice.VideoDevice.VideoResolution.FrameSize.Height;
            int w = captureDevice.VideoDevice.VideoResolution.FrameSize.Width;
            AVIwriter.Open("U:\\a.avi", w, h);
            timer1.Enabled = true;
            timer1.Start();
        }

        void FinalVideo_NewFrame(object sender, NewFrameEventArgs eventArgs)
        {
            if (stopVideo==false)
            {
                video = (Bitmap)eventArgs.Frame.Clone();
                AVIwriter.Quality = 0;
                AVIwriter.AddFrame(video); 
            }
            else if (stopVideo==true)
            {
                video = (Bitmap)eventArgs.Frame.Clone();
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (FinalVideo == null)
            { return; }
            if (FinalVideo.IsRunning)
            {
                this.FinalVideo.Stop();
                this.AVIwriter.Close();
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            duration--;

            textBox1.Text = duration.ToString();

            if (duration ==0)
            {
                timer1.Stop();
                stopVideo = true;

                if (FinalVideo == null)
                { return; }

                if (FinalVideo.IsRunning)
                {
                    this.FinalVideo.Stop();
                    this.AVIwriter.Close();
                }
            }
        }
    }
}
Hinweis von Coffeebean vor 7 Jahren

Zum zweiten Mal: Keine Full-Quotes!!! [Hinweis] Wie poste ich richtig?

R
Richard95 Themenstarter:in
10 Beiträge seit 2016
vor 7 Jahren

Hallo nochmal,

das Problem, dass die Videos so groß sind konnte ich lösen. Habe jetzt statt dem AVIWriter den FileWriter verwendet und als VideoCodec MPEG4 gewählt.

Folgendes Problem habe ich leider immer noch:

Kann mir einer sagen, warum mein Video immer eine andere Länge hat, sobald ich die frameRate verändere. Und an welchen Stellschrauben ich drehen muss, damit bei jeder beliebigen Framerate ein gleich langes Video dabei herauskommt.

Gruß,
Richard

3.003 Beiträge seit 2006
vor 7 Jahren

Kann mir einer sagen, warum mein Video immer eine andere Länge hat, sobald ich die frameRate verändere.

Weil ganz offensichtlich eine feste Anzahl Frames gespeichert werden, vermutlich in Abhängigkeit davon, mit welcher framerate die Kamera aufzeichnet.

Kamera mit 25fps für 30 Sekunden => 750 Frames.
Video gespeichert mit 60fps => 12,5 Sekunden Video.

Damit das Ergebnis genauso lang wird wie das Original, muss es mit derselben framerate gespeichert werden, wie es aufgenommen wurde. Liegt auf der Hand. Sonst müsste er sich Frames aus den Fingern saugen.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

R
Richard95 Themenstarter:in
10 Beiträge seit 2016
vor 7 Jahren

Damit das Ergebnis genauso lang wird wie das Original, muss es mit derselben framerate gespeichert werden, wie es aufgenommen wurde. Liegt auf der Hand. Sonst müsste er sich Frames aus den Fingern saugen.

In diese Variablen schreibe ich welche Auflösung und Framerate meine Cam hat. Richtig?
Und anschließend speichere ich das Video mit denselben Eigenschaften ab.

            
int height = FinalVideo.VideoCapabilities[0].FrameSize.Height; //480
int width =  FinalVideo.VideoCapabilities[0].FrameSize.Width; //640
int frameRate = FinalVideo.VideoCapabilities[0].AverageFrameRate; //30
FileWriter.Open("U:\\a.avi", width, height, frameRate, VideoCodec.MPEG4, bitRate);

timer1.Enabled = true;
timer1.Start();

Hängt das nicht auch noch mit meinem Timer zusammen. Also wenn ich den Timer auf 10sec stelle, bekomme ich immer noch kein 10sec Video, sondern ein 7sec Video.

Gruß,
Richard

3.003 Beiträge seit 2006
vor 7 Jahren

An der Stelle kann ich nur raten. Mein Gefühl sagt mir, dass der Einsatz des Timers falsch ist. Nur, weil du der Kamera den Befehl gibst, was aufzunehmen, ist der Zeitpunkt nicht der Zeitpunkt, an dem die Kamera beginnt, etwas aufzunehmen[1]. Du kannst allerdings länger aufnehmen und das Ergebnis schneiden - falls die Kamera nicht von sich aus schon eine Möglichkeit hat, genau x Frames aufzunehmen.

LaTino
[1] Will sagen: es wäre gut möglich, dass die Kamera eine gewisse Anlaufzeit hat.

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)