Livestream speichern?!!?

1342

Grünschnabel
Hallo zusammen,

ich habe ein Programm, welches einen Livestream einer WLAN kamera anzeigt.

Nun würde ich diesen Livestream gerne speichern. Momentan speichert es mir zwar was ab, aber ich kann es mit keinem PLayer wiedergeben.
Wärend der Aufnahme wächst die Datei und unser Programm bleibt hängen.
Wir vermuten das in die Datei nur 0en geschrieben werden und wegen dem können wir die Datei nicht abspielen.

Hier ist der code zur Aufnahme:
Code:
public class iListener implements ItemListener // Interne Klasse iListener
    {            
        
        private AbstractButton button; // Privates Attribut        
        
        // Wird aufgerufen wenn sich bei "Record" was ändert
        public void itemStateChanged(ItemEvent e) 
        {    
            button = (AbstractButton)e.getItem(); // Gibt das auslösende Objekt zurück
                            
            if(button.isSelected()) // Wenn "Record" gesetzt ist
            {   
                try // Versuche
                {
                    
                Date dt = new Date(); // Datum erzeugen
                SimpleDateFormat dtformat = new SimpleDateFormat("dd.MM.yyyy 'at' HH.mm.ss");// Datumsformat festlegen
                URL url = new URL("http://"+Daten[0]+"/videostream.cgi?&user=admin&pwd=1342&resolution=32");
                URLConnection conn = url.openConnection();
                BufferedInputStream stream = new BufferedInputStream(conn.getInputStream());
                
                FileOutputStream fos = new FileOutputStream(Daten[3] + "\\"+ dtformat.format(dt) +".mjpg"); 
                char  buffer[] = new char[0xffff];
                int   nbytes ;
 
                while( (nbytes=stream.read()) != 3) { 
                    fos.write(nbytes);

                }                 

                  }
           
            
                catch(IOException e1) // Wird ausgeführt wenn ein Fehler stattgefunden hat
                {
                      e1.printStackTrace();
                }
                                        
            }                
        }}

Ich suche schon seit Tagen im Netz, finde aber keine passende Lösung.

Hat jemand von Euch ne Ahnung? Ich bin am Verzweifeln......

Gruß 1342
 
Hi,

bei deinem Codebeispiel fallen mir mehrere Sachen auf, hier erstmal eine "verbesserte" Lösung von mir.

Java:
public class iListener implements ItemListener {
        private AbstractButton button;
        
        public void itemStateChanged(ItemEvent e)  {
		/*
		 * Streams ausserhalb deklarieren um diese auf jeden Fall auch zu schließen
		 * (auch bei Exception)
		 */
		BufferedInputStream stream = null;
		FileOutputStream fos = null;
		
		try {
			Date dt = new Date();
			SimpleDateFormat dtformat = new SimpleDateFormat("dd.MM.yyyy 'at' HH.mm.ss");// Datumsformat festlegen
			URL url = new URL("http://" + Daten[0] + "/videostream.cgi?&user=admin&pwd=1342&resolution=32");
			URLConnection conn = url.openConnection();
			stream = new BufferedInputStream(conn.getInputStream());
			
			fos = new FileOutputStream(Daten[3] + "\\"+ dtformat.format(dt) +".mjpg");
			
			// Die ausgelesenen Daten liegen als byte vor, nicht als char
			byte  buffer[] = new byte[256];
			int   nbytes ;
			
			/*
			 * Hier wird nicht immer nur ein byte gelesen, sondern gleich
			 * maximal 256. Bringt bessere Performance.
			 */
			while((nbytes=stream.read(buffer, 0, 256)) != -1) { 
				fos.write(buffer, 0, nbytes);
			}
			
			/*
			 * Buffer leeren, Speicher freigeben
			 */
			buffer = null;
		} catch(IOException e1) {
			e1.printStackTrace();
		} finally {
			/*
			 * Die Streams schließen, egal ob Exception kommt oder nicht
			 */
			if(fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			
			if(stream != null) {
				try {
					stream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
        }
}

So, jetzt mal zu meinen Änderungen / Anpassungen.
Als erstes definiere ich die Streams ausserhalb des try-catch-Blocks um diese auf jeden Fall schließen zu lassen. Bei dir wurde zum Beispiel der Inputstream nicht geschlossen, falls beim Öffnen des Dateistreams eine Exception geworfen wurde.

Des weiteren sollte das Array mit den empfangenen Daten ein byte[] sein, da die Daten ja auch so geliefert werden (siehe hier). char und byte sind zwar grundsätzlich beide 8 Bit groß, jedoch eines davon unsigned. Dadurch dass du hier die byte hernimmst sparst du dem Programm höchstwahrscheinlich ein paar Casts.

Dann wird jetzt nicht nur ein byte nach dem nächsten gelesen, sondern gleich versucht 256 Bytes zu lesen. Dies hat einen ungemeinen Performancevorteil, da die read()- und write()- Methoden nicht sooft aufgerufen werden müssen.

Als letzte Änderung habe ich noch den finally-Teil erstellt, welcher die Streams immer schließt.

Gruß
BK
 
Zuletzt bearbeitet:
Hallo Bratkartoffel,

vielen danke für deinen Verbesserungsvorschlag, ich hab das gerade mit meinem Programm getestet.
Wir haben einen kleinen Teilerfolg die Datei wird noch immer langsam großer und wenn ich sie mit dem VLC Player abspiele seh ich 100ms lang das erste Bild vom dem Stream aber danach kommt nichts, ich vermute das es nur 1 Bild abspeichert, weil wenn ich in Details der Datei gehe wird dort nichts angegeben.

Siehe Bild:
testtt.jpg

Ich danke dir! Das ist schonmal ein Vorteil :).

mfg 1342
 
Hallo,

eventuell muss der FileOutputStream des öfteren geflusht werden, je nachdem wieviel Daten halt da reinkommen.
Pack mal in die while()-Schleife noch ein "fos.flush()" rein und versuchs nochmal.

// Edit: Die gespeicherte Datei kannst du dir leicht mit einem Hex-Editor (HxD zum Beispiel anschauen.

Gruß
BK
 
Zuletzt bearbeitet:
Also ich hab jetzt in der While schleife noch das flush eingefügt aber das Programm bleibt noch immer hängen und die Datei ist noch immer gleich, ich hab mal den Hex Editor runtergeladen und geschaut was in die Datei geschrieben wird.
Es werden also keine 0en in die Datei geschrieben:

aaa.jpg

hmm langsam wird es komisch....

Ich hab gerade mal eine Statisik von zwei Dateien gemacht, die obere Statistik ist von einer Datei mit der gleichen Kamera aber mit dem Programm gespeichert das mit der Kamera mitgeliefert wurde.
Unbenanntaa.jpg
 
Zuletzt bearbeitet:
Also betätige ich den Button zum Video Aufnehmen kann ich nichts mehr in meinem Programm Steuern es hängt sich dann auf, dann muss ich es mit dem Task Manager beenden damit ich es wieder neustarten kann.
Ich vermute das die while() schleife dann nicht verlassen wird?!

Programma.jpg
 
Hallo,

das liegt wohl eher daran, dass die Schleife zum Aufnehmen der Daten (zum Speichern der Daten) nicht in einem extra Thread ausgelagert ist und somit das gesammte Programm blockiert bis alle Daten empfangen wurden, bzw. bis die Gegenstelle die Verbindung beendet.

Schöner Schrank übrigens ;)

Gruß
BK
 
Das Programm hängt sich nicht auf. Aber der Thread ist in der while-Schleife mit dem aufzeichnen beschäftigt und kann sich nicht um die Benutzeroberfläche kümmern. Also musst du die Aufnahme in einen neuen Thread auslagern.
 
Zurück