Sonntag, 17. Oktober 2010

Webcam Chat

Auf Anfrage eines Lesers habe ich mich kürzlich der Realisierung eines etwas aufwendigeren Projekts gewidmet, der Entwicklung eines in C# implementierten Webcam Chats.
Diesen möchte ich in diesem Post vorstellen, zum Verständnis sind einige Vorkenntnisse hilfreich:
- Den Code zur Einbindung einer Webcam habe ich mit Erlaubnis vom net-blog übernommen.
- Die Verbindung der Partner wird über TCP / IP hergestellt, hierzu gibt es eine Einführung auf diesem Blog (hier).
- Viele möchten sich sicherlich über das Internet mit Freunden vernetzen, wie die Verbindung darüber läuft und insbesondere welche IPs zu verwenden sind, findet ihr hier (und auch noch allgemeine Infos zur Vernetzung im LAN).
- Wie in Bild "gestreamt" werden kann wird in diesem Post erklärt.
- Und schließlich gibt's hier allgemeine Infos zum Fehler "Allgemeiner Fehler in GDI+", welcher sporadisch bei Grafikanwendungen auftritt.

Hier die Oberfläche des Programms:


In der linken PictureBox wird das Bild der eigenen Kamera angezeigt, in der rechten das des Chat Partners.
Der Chat Partner muss natürlich auch das gleiche Programm laufen haben.

Zur Funktionsweise:
Beim Klick auf den Button "Verbinden" werden 2 Threads gestartet, einer davon dient zum Senden des eigenen Bildes und der andere zum Empfangen des Bildes des anderen.
Der Senden - Thread läuft auf dem unter "eigener Port" angegebenen Port, der Empfangs - Thread über den unter "Partner Port".
Zum Verbinden müssen also logischerweise beide Partner die IP - Adresse des jeweiligen Partners eingeben sowie passende Ports, also Partner A den Port x unter "eigener Port" und Port y unter "Partner Port", Partner B muss diese Daten andersherum eingeben.
Im Senden - Thread wird ein Server erstellt, auf welchen sich der Client aus dem Empfangs - Thread des Clients verbindet.
In jeder Instanz des Programms gibt es also 2 Server - Client Verbindungen, die jeweils über einen Netzwerkstream kommunizieren.
In dem Senden - Thread wird in einer Endlosschleife versucht, das Bild der eigenen PictureBox über die Methode WriteImage() zu senden.
In dieser wird zuerst das Bild über einen temporären Stream in ein byte - Array geschrieben. Dann wird die Größe dieses Arrays in einen 20-stelligen String geschrieben, wobei die restlichen Stellen mit dem Buchstaben "x" aufgefüllt werden.
Die Größe und der eigentliche Inhalt des Bildes werden dann über den Netzwerkstream gesendet.
In dem Empfangs - Thread wird in einer Endlosschleife versucht, diesen Stream über die Methode ReadImage() auszulesen.
Als erstes werden hier in jedem Zyklus die ersten 20 Bytes ausgelesen, welches die Größe des Bildes sein sollten.
Kann der erhaltene String in eine sinnvolle Zahl g konvertiert werden, werden die nächsten g Bytes aus dem Netzwerkstream gelesen und daraus das Bild reproduziert.
Können die 20 Bytes nicht konvertiert werden, gab es einen Übertragungsfehler. Damit Server und Client sich wieder synchronisieren, muss der Stream gelöscht werden. Hierzu werden einfach so lange Bytes aus dem Stream herausgelesen, bis dieser leer ist.
Allgemein stellte sich die Realisierung der Datenübertragung als ziemlich schwer heraus, Server und Client wurden immer wieder asynchron und es traten viele Übertragungsfehler aus.
In der hier veröffentlichten Version werden bei Erfolg beim Senden und Empfangen eines Bildes die jeweiligen Bilder in einer Variablen gespeichert. Tritt an einer Stelle ein Fehler auf, wird das gespeicherte Bild wiederverwendet.
So, das sollte als Ablaufbeschreibung reichen, wie gesagt, die einzelnen Programmteile sollten bei Verständnis der oben erwähnten Themen leicht verständlich sein.
Ich weiß, diese Version hier ist nur ein erster Anfang, sie soll lediglich zu Demozwecken zeigen, wie ein solcher Webcam - Chat realisiert werden kann und kann beliebig erweitert werden.
Für Hinweise und Verbesserungsvorschläge bin ich aber immer dankbar.
Viel Spaß mit dem Programm!

Ein Setup, mit der sich der Webcam Chat installieren lässt, ist über diesen Link erreichbar.
Das komplette Projekt inklusive Quelldateien gibt es hier.
Und nun der Quellcode, zuerst der Inhalt der Datei Form1.cs und dann auch der Inhalt der Datei Form1.Designer.cs, kopiert ihr auch letztere in euer Projekt, habt ihr genau die gleiche Oberfläche wie ich.

Form1.cs:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

// für Webcam
using AForge.Video;
using AForge.Video.DirectShow;

// für Netzwerk
using System.IO;
using System.Net.Sockets;
using System.Net;

using System.Threading;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        #region Webcam

        //Unser Webcam Objekt
        VideoCaptureDevice videoSource;

        void InitWebCam(int nr)
        {
            //Auflistung aller Webcam/Videogeräte
            FilterInfoCollection videosources = new FilterInfoCollection(FilterCategory.VideoInputDevice);

            //Überprüfen, ob mindestens eine Webcam gefunden wurde
            if (videosources != null)
            {
                //Die Webcam "nr" an unser Webcam Objekt binden
                videoSource = new VideoCaptureDevice(videosources[nr].MonikerString);

                try
                {
                    //Überprüfen ob die Webcam Technische-Eigenschaften mitliefert
                    if (videoSource.VideoCapabilities.Length > 0)
                    {
                        string lowestSolution = "10000;0";
                        //Das Profil mit der niedrigsten Auflösung suchen
                        for (int i = 0; i < videoSource.VideoCapabilities.Length; i++)
                        {
                            if (videoSource.VideoCapabilities[i].FrameSize.Width < Convert.ToInt32(lowestSolution.Split(';')[0]))
                                lowestSolution = videoSource.VideoCapabilities[i].FrameSize.Width.ToString() + ";" + i.ToString();
                        }
                        //Dem Webcam Objekt die niedrigstmögliche Auflösung übergeben
                        videoSource.DesiredFrameSize = videoSource.VideoCapabilities[Convert.ToInt32(lowestSolution.Split(';')[1])].FrameSize;
                    }
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.ToString());
                }

                //Dem Webcam Objekt den NewFrame Eventhandler zuweisen.
                //Dieser schlägt bei jedem eingehenden Bild der Webcam an
                videoSource.NewFrame += new AForge.Video.NewFrameEventHandler(videoSource_NewFrame);

                //Die Webcam aktivieren
                videoSource.Start();
            }
        }

        void videoSource_NewFrame(object sender, AForge.Video.NewFrameEventArgs eventArgs)
        {
            //Jedes ankommende Bild von der Webcam der Picturebox zuweisen
            pictureBoxVideoSelf.BackgroundImage = (Image)eventArgs.Frame.Clone();
        }

        #endregion

        Image LastImageSent = null; // zuletzt korrekt gesendetes Bild
        Image LastImageReceived = null; // zuletzt korrekt empfangenes Bild

        Thread Sender; // Thread zum Senden von Bildern
        Thread Receiver; // Thread zum Empfangen von Bildern

        bool Closing = false; // true wenn Formular beendet werden soll
        String ClosingString = "FORM#CLOSING"; // Nachricht, die bei Beendigung geschickt wird
        byte[] ClosingBytes; // Byte - Darstellung der Nachricht
        ASCIIEncoding ByteConverter = new ASCIIEncoding(); // Objekt zur Konvertierung von Strings in byte - Arrays und umgekehrt

        private void button1_Click(object sender, EventArgs e)
        {
            // Thread zum Senden des eigenen Bildes starten
            Sender = new Thread(new ParameterizedThreadStart(this.Send));
            Sender.Start(int.Parse(textBox4.Text));

            // Thread zum Empfangen des Partnerbildes starten
            Receiver = new Thread(new ParameterizedThreadStart(Receive));
            Receiver.Start(textBox2.Text + "-" + textBox1.Text);

            ClosingBytes = ByteConverter.GetBytes(ClosingString);
        }

        private void Send(object port)
        {
            InitWebCam(int.Parse(textBox3.Text)); // Webcam starten

            TcpListener Server = new TcpListener(int.Parse(port.ToString()));
            Server.Start();

            TcpClient Client = Server.AcceptTcpClient();

            NetworkStream ClientStream = Client.GetStream();

            while (true)
            {
                if (Closing)
                    break; // Beendigung
                try
                {
                    // probieren, das aktuelle Bild an den Partner zu senden, dieses dann als Backupbild speichern
                    WriteImage((Image)pictureBoxVideoSelf.BackgroundImage.Clone(), ClientStream);
                    LastImageSent = (Image)pictureBoxVideoSelf.BackgroundImage.Clone();
                    Thread.Sleep(100);
                }
                catch
                {   // konnte das aktuelle Bild nicht gesendet werden, das Backupbild senden
                    WriteImage(LastImageSent, ClientStream);
                }
            }

            try
            {
                ClientStream.Write(ClosingBytes, 0, ClosingBytes.Length);
            }
            catch { };
        }

        private void Receive(object portip)
        {
            // portip hat die Form "port-ip"
            string[] Parameter = portip.ToString().Split('-');
            System.Net.IPAddress IP = System.Net.IPAddress.Parse(Parameter[1]);

            TcpClient Exchange = new TcpClient();
            NetworkStream ExchangeStream = null;

            Image TempImage;

            // alle 3 Sekunden versuchen eine Verbindung herzustellen
            while (true)
            {
                try
                {
                    Exchange.Connect(IP, int.Parse(Parameter[0]));
                    ExchangeStream = Exchange.GetStream();
                    break;
                }
                catch
                {
                    Thread.Sleep(3000);
                }
            }

            while (true)
            {
                if (Closing)
                    break; // Beendigung

                try
                {
                    // versuchen, das empfangene Bild zu lesen darzustellen
                    // bei Erfolg
                    TempImage = ReadImage(ExchangeStream);
                    if (TempImage == null)
                        throw new Exception();

                    pictureBoxVideoPartner.BackgroundImage = TempImage;
                    LastImageReceived = (Image)pictureBoxVideoPartner.BackgroundImage.Clone();
                    Thread.Sleep(100);
                }
                catch
                {
                    try
                    {   // bei Fehler das Backupbild darstellen
                        pictureBoxVideoPartner.BackgroundImage = LastImageReceived;
                    }
                    catch { }
                }
            }
        }

        private void WriteImage(Image image, NetworkStream stream)
        {
            ASCIIEncoding Encoder = new ASCIIEncoding();
            MemoryStream TempStream = new MemoryStream();
            byte[] Buffer;

            try
            {  
                // das übergebene Bild in den aktuellen Stream schreiben
                image.Save(TempStream, System.Drawing.Imaging.ImageFormat.Gif);
            }
            catch
            {
            }

            Buffer = TempStream.ToArray();

            // die Größe des Bildes als 20-stelligen String darstellen, mit "x" auffüllen
            string ImageSize = Buffer.Length.ToString();
            while (ImageSize.Length < 20)
                ImageSize += "x";

            // die Größe plus die Daten des Bildes in ein Array schreiben
            byte[] FittedImageSize = Encoder.GetBytes(ImageSize);
            byte[] ImagePlusSize = new byte[FittedImageSize.Length + Buffer.Length];
            Array.Copy(FittedImageSize, ImagePlusSize, FittedImageSize.Length);
            Array.Copy(Buffer, 0, ImagePlusSize, FittedImageSize.Length, Buffer.Length);

            try
            {
                // das zusammengefasste Array schreiben
                stream.Write(ImagePlusSize, 0, ImagePlusSize.Length);
                stream.Flush();
            }
            catch
            {
                // kann der Stream nicht mehr beschrieben werden, hat der Partner beendet
                Closing = true;
            }
        }

        private Image ReadImage(NetworkStream stream)
        {
            Image Result;
            int BytesRead;

            // die ersten 20 Bytes des Streams einlesen, denn in diesen ist die Größe kodiert
            byte[] ImageSize = new byte[20];
            BytesRead = stream.Read(ImageSize, 0, 20);

            /* konnten nur 12 Bytes gelesen werden und haben diese den Inhalt des
            Closing Strings, so soll beendet werden */
            if (BytesRead == 12)
            {
                if (ByteConverter.GetString(ImageSize, 0, 12) == "FORM#CLOSING")
                {
                    Closing = true;
                    return null;
                }
            }

            byte[] ErrorBuffer = new byte[100000000];

            ASCIIEncoding Decoder = new ASCIIEncoding();
            string ImageSizeString = Decoder.GetString(ImageSize).Replace("x", "");

            int TestSize;

            if (!int.TryParse(ImageSizeString, out TestSize))
            {
                stream.Read(ErrorBuffer, 0, ErrorBuffer.Length);
                return null;
            }

            byte[] ImageFile = new byte[int.Parse(ImageSizeString)];

            stream.Read(ImageFile, 0, ImageFile.Length);

            MemoryStream temps = new MemoryStream();

            try
            {
                temps.Write(ImageFile, 0, ImageFile.Length);
                Result = Image.FromStream(temps);
                return Result;
            }
            catch
            {
                return null;
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            //Webcam beim Schließen des Programms wieder freigeben
            if (videoSource != null && videoSource.IsRunning)
            {
                videoSource.SignalToStop();
                videoSource = null;
            }

            Closing = true;

            Thread.Sleep(3000);

            if (Sender != null && Sender.IsAlive)
                Sender.Abort();

            if (Receiver != null && Receiver.IsAlive)
                Receiver.Abort();
        }
    }
}


Form1.Designer.cs:

namespace WindowsFormsApplication1
{
    partial class Form1
    {
        /// <summary>
       /// Erforderliche Designervariable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
       /// Verwendete Ressourcen bereinigen.
        /// </summary>
        /// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Vom Windows Form-Designer generierter Code

        /// <summary>
       /// Erforderliche Methode für die Designerunterstützung.
       /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
        /// </summary>
        private void InitializeComponent()
        {
            this.pictureBoxVideoSelf = new System.Windows.Forms.PictureBox();
            this.button1 = new System.Windows.Forms.Button();
            this.pictureBoxVideoPartner = new System.Windows.Forms.PictureBox();
            this.label1 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.label3 = new System.Windows.Forms.Label();
            this.label4 = new System.Windows.Forms.Label();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.textBox2 = new System.Windows.Forms.TextBox();
            this.textBox3 = new System.Windows.Forms.TextBox();
            this.textBox4 = new System.Windows.Forms.TextBox();
            this.label5 = new System.Windows.Forms.Label();
            ((System.ComponentModel.ISupportInitialize)(this.pictureBoxVideoSelf)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.pictureBoxVideoPartner)).BeginInit();
            this.SuspendLayout();
            //
            // pictureBoxVideoSelf
            //
            this.pictureBoxVideoSelf.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
            this.pictureBoxVideoSelf.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.pictureBoxVideoSelf.Location = new System.Drawing.Point(47, 26);
            this.pictureBoxVideoSelf.Name = "pictureBoxVideoSelf";
            this.pictureBoxVideoSelf.Size = new System.Drawing.Size(331, 210);
            this.pictureBoxVideoSelf.TabIndex = 0;
            this.pictureBoxVideoSelf.TabStop = false;
            //
            // button1
            //
            this.button1.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.button1.Location = new System.Drawing.Point(326, 263);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(154, 46);
            this.button1.TabIndex = 1;
            this.button1.Text = "Verbinden";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            //
            // pictureBoxVideoPartner
            //
            this.pictureBoxVideoPartner.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
            this.pictureBoxVideoPartner.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.pictureBoxVideoPartner.Location = new System.Drawing.Point(398, 26);
            this.pictureBoxVideoPartner.Name = "pictureBoxVideoPartner";
            this.pictureBoxVideoPartner.Size = new System.Drawing.Size(319, 210);
            this.pictureBoxVideoPartner.TabIndex = 3;
            this.pictureBoxVideoPartner.TabStop = false;
            //
            // label1
            //
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(25, 281);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(0, 13);
            this.label1.TabIndex = 4;
            //
            // label2
            //
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(47, 249);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(54, 13);
            this.label2.TabIndex = 5;
            this.label2.Text = "Partner IP";
            //
            // label3
            //
            this.label3.AutoSize = true;
            this.label3.Location = new System.Drawing.Point(47, 273);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(63, 13);
            this.label3.TabIndex = 6;
            this.label3.Text = "Partner Port";
            //
            // label4
            //
            this.label4.AutoSize = true;
            this.label4.Location = new System.Drawing.Point(47, 321);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(73, 13);
            this.label4.TabIndex = 7;
            this.label4.Text = "Webcam - Nr.";
            //
            // textBox1
            //
            this.textBox1.Location = new System.Drawing.Point(128, 249);
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(158, 20);
            this.textBox1.TabIndex = 8;
            //
            // textBox2
            //
            this.textBox2.Location = new System.Drawing.Point(128, 273);
            this.textBox2.Name = "textBox2";
            this.textBox2.Size = new System.Drawing.Size(158, 20);
            this.textBox2.TabIndex = 9;
            //
            // textBox3
            //
            this.textBox3.Location = new System.Drawing.Point(128, 321);
            this.textBox3.Name = "textBox3";
            this.textBox3.Size = new System.Drawing.Size(158, 20);
            this.textBox3.TabIndex = 10;
            this.textBox3.Text = "0";
            //
            // textBox4
            //
            this.textBox4.Location = new System.Drawing.Point(128, 297);
            this.textBox4.Name = "textBox4";
            this.textBox4.Size = new System.Drawing.Size(158, 20);
            this.textBox4.TabIndex = 10;
            //
            // label5
            //
            this.label5.AutoSize = true;
            this.label5.Location = new System.Drawing.Point(47, 297);
            this.label5.Name = "label5";
            this.label5.Size = new System.Drawing.Size(64, 13);
            this.label5.TabIndex = 11;
            this.label5.Text = "eigener Port";
            //
            // Form1
            //
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(758, 370);
            this.Controls.Add(this.textBox4);
            this.Controls.Add(this.label5);
            this.Controls.Add(this.textBox3);
            this.Controls.Add(this.textBox2);
            this.Controls.Add(this.textBox1);
            this.Controls.Add(this.label4);
            this.Controls.Add(this.label3);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.pictureBoxVideoPartner);
            this.Controls.Add(this.button1);
            this.Controls.Add(this.pictureBoxVideoSelf);
            this.Name = "Form1";
            this.Text = "C# Webcam Chat";
            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
            ((System.ComponentModel.ISupportInitialize)(this.pictureBoxVideoSelf)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.pictureBoxVideoPartner)).EndInit();
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.PictureBox pictureBoxVideoSelf;
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.PictureBox pictureBoxVideoPartner;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.Label label3;
        private System.Windows.Forms.Label label4;
        private System.Windows.Forms.TextBox textBox1;
        private System.Windows.Forms.TextBox textBox2;
        private System.Windows.Forms.TextBox textBox3;
        private System.Windows.Forms.TextBox textBox4;
        private System.Windows.Forms.Label label5;
    }
}

Kommentare:

  1. Hallo Oliver.. vielen Dank ersteinmal für die tolle Anwendung

    Nur wenn ich auf den Button Verbinden klicke, bekomme ich eine Fehlermeldung im Quellcode angezeigt.

    Unzwar an der Stelle
    // Webcam "nr" an das Webcam obejkt binden
    videoSource = new VideoCaptureDevice(videosources[nr].MonikerString);

    ArgumentOutOfRangeException wurde nicht behandelt... Der Index lad außerhalb des bereiches. Er muss nicht negativ und kleiner als die Auflistung sein.

    Eine Rückantwort wäre Klasse!

    AntwortenLöschen
  2. Hallo Roland,
    da du einen ArgumentOutOfRange Fehler erhälst, heißt das, du willst auf ein Element aus dem Array videosources mit einem ungültigen Index zugreifen, z.B. wenn das Array 2 Webcams speichert und du 3 als nr übergibst.
    Pro angeschlossene Webcam am Computer gibt es einen Eintrag in diesem Array. Also entweder übergibst du einen ungültigen Wert für nr, oder die Webcam(s) wird / werden nicht erkannt. Du kannst ja mal im Debug Modus den Inhalt von videosources einlesen und prüfen, ob darin alle gewünschten Webcams vorhanden sind.

    AntwortenLöschen
  3. Habe den Code überflogen. Wie sieht das mit einer Verbindung über das Internet aus? ISt Portforwarding im Router nötig?

    AntwortenLöschen
  4. Das Programm verhält sich wie ein "normales" Programm, welches über TCP / IP mit anderen Rechnern kommuniziert und hat damit die gleichen Eigenschaften. Ob Portforwarding nötig ist hängt also vom Router ab und der Netzwerkarchitektur ab.
    Falls die Verbindung nicht klappt klappt, kann es daran liegen, dass Portforwarding nötig ist.
    Wie das funktioniert und mehr allgemeine Infos zu TCP / IP gibt's im Post: http://csharp-tricks.blogspot.com/2010/10/wahl-der-ip-adressen-zur-kommunikation.html

    AntwortenLöschen
  5. Hallo Oliver, der Download-Link funktioniert bei mir nicht, kannst du mir die kompletten dateien als Email-Anhang schicken?

    AntwortenLöschen
  6. Hey, klar kann ich machen, ich habe auf deinem Profil allerdings keine Email Adresse gefunden.
    Schick mir doch mal eine bitte.
    Grüße

    AntwortenLöschen
  7. hallo Oliver,
    danke für das Beispiel
    Ich wollte mal fragen, ob
    es möglich wäre eine Sprachübertragung
    ins Bsp. zu integrieren
    danke
    Grüße Karl

    AntwortenLöschen
  8. Hallo Karl,

    das ist sicherlich möglich und klingt auch sehr interessant, leider habe ich im Moment nicht die Zeit dazu.
    Du kriegst es bestimmt aber auch selber hin: Das Prinzip ist ja das gleiche wie beim Senden der Bilder, nur eben müssen Audiodaten übertragen werden und falls es dafür keine passende Klasse gibt die Daten binär übertragen.

    Viele Grüße
    Oliver

    AntwortenLöschen
  9. Hallo,
    ich muss sagen, dass mir das Tutorial sehr weitergeholfen hat
    Allerdings habe ich immer das Problem, das anscheinend immer nur eine Server-Client Verbindung hergestellt wird.
    Woran kann das liegen?
    z.B. wird bei diesem Programm nur an einem PC das Bild des anderen angezeigt. Der andere PC zeigt nur das eigen Bild.

    Grüße Henning

    AntwortenLöschen
  10. Hallo Oliver,
    Ich befinde mich im Praktikum und habe die aufgabe ein Programm zu schreiben mit dem maschienen in anderen werken via webcam überwacht werden können.
    Dein Programm hat mir sehr geholfen aber es ist etwas unpraktisch mit den ips ist es möglich ein server programm und mehrere clients zu erstellen die automatisch beim start des Programms auf den server connecten ?kannst du mir da weiterhelfen brauche echt dringend hilfe.

    AntwortenLöschen
  11. Hallo Robin,
    Ich bin auch gerade dabei so etwas zu schreiben. Also du brauchst mal 2 Programme. Der Server, welcher das Bild raus schickt und den Client, der das Bild empfängt. Alle dafür relevanten Code-Teile findest oben im Beispiel. Problem gelöst :D

    AntwortenLöschen
  12. also bei mir funktioniert nur der Teil, in dem ich mich selbst sehen kann. Allerdings sehe ich da nicht nur ein Bild von mir sondern mehrere....
    Das Bild wird so oft in die Picturebox geschmissen bis diese voll ist...was kann man da machen, dass das bild nur einmal und in voller Größe angezeigt wird ?

    AntwortenLöschen
  13. Hallo Oliver,
    vielen Dank für die tolle Software!
    Es läuft auf allen Rechnern gut, außer auf meinen Acer Iconia Tablett, mit der internen Kamera sehe ich kein Bild. Stecke ich die USB Kamera, läuft alles ohne Probleme.
    Hast Du evt. eine Ahnung wo ich suchen müsst?

    AntwortenLöschen