Jave (InputFormatException)

Christopher25

Bekanntes Mitglied
Hallo Zusammen.

Meine Frage ist folgende. Ich benutze den Wrapper Jave welcher auf dem projekt ffmpeg basiert.
Hier ist die homepage http://www.sauronsoftware.it/projects/jave/manual.php#10
Ich möchte eine "AVI" Datei in eine "MP4" Datei, mit dem video codec H.264 convertieren.
Der Video Encoder ist dort der "libx264" mit dem Tag "H264".

Hier mein Code:
Java:
AudioAttributes audio = new AudioAttributes();
        audio.setCodec("libfaac");
        audio.setBitRate(new Integer(512000));
        audio.setSamplingRate(new Integer(44100));
        audio.setChannels(new Integer(2));
        VideoAttributes video = new VideoAttributes();
        video.setCodec("libx264");
        video.setTag("H264");
        video.setBitRate(new Integer(512000));
        video.setFrameRate(new Integer(30));
        attributes = new EncodingAttributes();
        attributes.setFormat("mp4");
        attributes.setAudioAttributes(audio);
        attributes.setVideoAttributes(video);
        super.convert(source, target);

Ich bekomme dabei aber folgende Fehlermeldung:
it.sauronsoftware.jave.InputFormatException
at it.sauronsoftware.jave.Encoder.parseMultimediaInfo(Encoder.java:659)
at it.sauronsoftware.jave.Encoder.encode(Encoder.java:840)
at converts.ConvertModule.convert(ConvertModule.java:17)
at converts.MP4Module.convert(MP4Module.java:46)
at modules.Test.main(Test.java:16)


Kann mir jemand dabei helfen? Ich weiß nicht wirklich was ich falsch mache. Ich muss unbedingt dieses video ausschließlich mit dem H264 Video Codec haben.
 
K

kneitzel

Gast
Die von Dir verlinkte Doku hast Du gelesen? Die Exception ist dort beschrieben. Das Source file kann nicht decoded werden. Also ist das Format nicht unterstützt oder die Datei ist defekt.
 

Christopher25

Bekanntes Mitglied
Ich hab die gelesen, aber das taucht sowohl mit einer .avi und ebenso mit einer .mkv auf,
welche auf jedenfall unterstützt werden, da sich diese z.b. mit dem mpeg video codec ja auch umsetzen lassen.
 

JStein52

Top Contributor
Was ist das :
Code:
super.convert(source, target);

Dein Beispielcode ist so nicht kompilierbar. Gib mal ein kompilierbares Beispiel ....
 
K

kneitzel

Gast
Also sein Code muss in einer Klassenstruktur stecken, die dann intern irgendwo den Encoder hat. Ich habe das für meine Tests einfach mal wie folgt gemacht:
Code:
public static void main(String[] args) {
    File source= new File("c:\\temp\\input.mp4");
    File target= new File("c:\\temp\\output.mp4");
    AudioAttributes audio = new AudioAttributes();
    audio.setCodec("libfaac");
    audio.setBitRate(new Integer(512000));
    audio.setSamplingRate(new Integer(44100));
    audio.setChannels(new Integer(1));
    VideoAttributes video = new VideoAttributes();
    video.setCodec("libx264");
    video.setTag("H264");
    video.setBitRate(new Integer(512000));
    video.setFrameRate(new Integer(30));
    EncodingAttributes attributes = new EncodingAttributes();
    attributes.setFormat("mp4");
    attributes.setAudioAttributes(audio);
    attributes.setVideoAttributes(video);
    Encoder encoder = new Encoder();
    try {
        encoder.encode(source, target, attributes);
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}
Was ich also geändert habe ist:
- source und target definiert
- den Audio Channel habe ich auf 1 gesetzt - mit 2 gab es bei mir auch die genannte Exception. Aber das kann evtl. auch an meinem Input liegen oder so.
- Die EncodingAttributes sind eine lokale Variable und den Encoder habe ich direkt erzeugt.

Der Code läuft prinzipiell, nur eben sind die angegebenen Parameter zumindest für mein System ungültig: it.sauronsoftware.jave.EncoderException: Error while opening codec for output stream #0.1 - maybe incorrect parameters such as bit_rate, rate, width or height

Konrad
 

JStein52

Top Contributor
Hallo @kneitzel , Ja war mir klar dass da sowas drumrum muss. Aber es könnte ja sein dass genau da sein Fehler drinnen ist und deshalb wollte ich seinen Code und nicht meinen.
 
K

kneitzel

Gast
Ich würde vermuten, dass sein Imput auch nur einen Audio-Channel hat und daher ist sein SetChannels der Auslöser. Aber das ist nur eine Vermutung, da ich über dieses Problem gestolpert bin.
 

Christopher25

Bekanntes Mitglied
Also ich bin immernoch bei diesem fehler, an der bitrate, channel usw. scheint es nicht zu liegen.
Wenn ich daran rumspiele oder gar mal ganz weglasse bleibt der fehler bestehen.

PS:
Java:
        File source = new File("G://Filme/Sheep In The Island 1 [HD].mp4");
        File target = new File("G://Filme/Test.mp4");
      
        ConvertModule module = new MP4Module();
        try {
            module.convert(source, target);
        } catch (Exception e) {
            e.printStackTrace();
        }
Java:
public abstract class ConvertModule {
   protected Encoder encoder = new Encoder();
   protected EncodingAttributes attributes;
   
   public void convert(File source, File target) throws Exception {
     encoder.encode(source, target, attributes, new EncoderProgressListener() {
       @Override
       public void sourceInfo(MultimediaInfo info) {
         Logger.getGlobal().log(Level.INFO, info.getFormat());
         Logger.getGlobal().log(Level.INFO, info.getAudio().getDecoder());
         Logger.getGlobal().log(Level.INFO, info.getVideo().getDecoder());
       }
       
       @Override
       public void progress(int duration) {
         double percent = ((double)100 / 1000) * duration;
         percent = Math.round(percent * 100) / 100.0;  
         System.out.println(percent + " %");
       }
       
       @Override
       public void message(String msg) {}
     });
   }
}
 

Christopher25

Bekanntes Mitglied
Also sein Code muss in einer Klassenstruktur stecken, die dann intern irgendwo den Encoder hat. Ich habe das für meine Tests einfach mal wie folgt gemacht:
Java:
public static void main(String[] args) {
    File source= new File("c:\\temp\\input.mp4");
    File target= new File("c:\\temp\\output.mp4");
    AudioAttributes audio = new AudioAttributes();
    audio.setCodec("libfaac");
    audio.setBitRate(new Integer(512000));
    audio.setSamplingRate(new Integer(44100));
    audio.setChannels(new Integer(1));
    VideoAttributes video = new VideoAttributes();
    video.setCodec("libx264");
    video.setTag("H264");
    video.setBitRate(new Integer(512000));
    video.setFrameRate(new Integer(30));
    EncodingAttributes attributes = new EncodingAttributes();
    attributes.setFormat("mp4");
    attributes.setAudioAttributes(audio);
    attributes.setVideoAttributes(video);
    Encoder encoder = new Encoder();
    try {
        encoder.encode(source, target, attributes);
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}
Was ich also geändert habe ist:
- source und target definiert
- den Audio Channel habe ich auf 1 gesetzt - mit 2 gab es bei mir auch die genannte Exception. Aber das kann evtl. auch an meinem Input liegen oder so.
- Die EncodingAttributes sind eine lokale Variable und den Encoder habe ich direkt erzeugt.

Der Code läuft prinzipiell, nur eben sind die angegebenen Parameter zumindest für mein System ungültig: it.sauronsoftware.jave.EncoderException: Error while opening codec for output stream #0.1 - maybe incorrect parameters such as bit_rate, rate, width or height

Konrad

Das liegt warscheinlich daran, weil libfaac (mp3) mit stereo sound arbeitet (glaub ich zumindest)
bei mir kommt nämlich auch der fehler mit falschen params wenn ich deinen Code übernehme!



PS:
Es liegt wirklich alles nur an dem video codec, wenn ihr nämlich
Java:
    attributes.setVideoAttributes(video);
auskommentiert, funktioniert das ganze wieder.
 
K

kneitzel

Gast
Also ich habe jetzt aus den Augen verloren, was für eine Fehlermeldung du genau bekommst. Du bist doch schon bei falschen Parametern angekommen, also solltest Du die Werte einmal prüfen. Woher kommen die verwendeten Werte?

Ich bin kein Experte für Video-Encoding, daher kann ich da nicht gross weiter helfen. Aber dazu wird es bestimmt auch viele Seiten geben im Netz.
 

Christopher25

Bekanntes Mitglied
Ich habe vieles durchgelesen und auch über ffmpeg.
Ich habe den Wrapper Jave genommen, weil ich, wenn ich ffmpeg mit
git runterlade dort nur lauter .c dateien und andere dateien vorfinde, mit denen ich
nix anzufangen weiß, nichtmal eine .exe oder sowas.

Deshalb frage ich hier ja auch nach, vielleicht weiß jemand ja auch eine alternative.
Ich brauche lediglich ein .mp4 video in H264 Video Format und natürlich das dementsprechende Audio Format am besten MP3 (libfaac encoder).

Ansonsten war meine Fehlermeldung (InputFormatException), welches du aber auch in den Beiträgen zuvor schauen kannst =)
 

Christopher25

Bekanntes Mitglied
So ich habe jetzt einiges ausprobiert und auf diese Seite gestoßen (http://ffmpeg.zeranoe.com/builds/).
Dort habe ich mir einfach mal die 32 Bit Version von ffmpeg runtergeladen.
Mithilfe der Batch Datei kann ich die Befehle eingeben und es funktioniert.
Habe jetzt das ganze so programmiert, dass ich in Java per Runtime aufruf die Exe innerhalb meiner Jar aufrufe und ausführen lasse.
Ich teste es gerade noch ich werde euch dann bescheid sagen wie es ausschaut.
Dementsprechend werde ich natürlich dann auch den Code hier reinstellen, den ich benutzt habe. Vielleicht findet sich ja eine etwas schönere programmierweise bzw Vorschläge zur Verschönerung etc.

PS:
Also den Jave Wrapper habe ich rausgekickt!
 

Christopher25

Bekanntes Mitglied
Mach ich hier irgendetwas falsch?
Immer wenn ich diesen Prozess starte, dann macht der nix. Wenn ich das Programm beenden will über die Eclipse, dann beendet der sich erstmal nicht und wenn ich in dem TaskManager gucke, dann startet der aufeinmal doch die ffmpeg.exe....

hier folgender Code.
Java:
public static void main(String[] args) {
        try {
            File source = new File("G://Filme/Anime/Blood C/c 01 1080p/c 01 1080p/blood.c.01.der.kampf.beginnt.1080p.x265.mkv");
            File target = new File("G://Filme/TEST.mp4");
            String command =
                    Class.class.getResource("/ffmpeg/ffmpeg.exe").getPath().substring(1)+
                    " -i \"" + source.getPath() +
                    "\" -vcodec libx264" +
                    " \"" + target.getPath()+"\"";
          
            Process process = Runtime.getRuntime().exec(command);
            ProcessList.addProcess(new ConvertProcess(source, target, process));
            final int exitStatus = process.waitFor();
            System.out.println("Processed finished with status: " + exitStatus);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Wenn ich das, was in dem command steht in die normale Windows Console eingebe, funktioniert das ganze reibungslos.
Wie kann ich eigentlich das, was in der WindowsConsole steht, auch in meiner Java Console ausgeben lassen, wenn ich den Prozess auch über die WindowsConsole starte? Da steht dann z.b. Wie viele Frames der schon convertiert hat und mit wie viel kb/s....
 

Christopher25

Bekanntes Mitglied
Ich habe herausgefunden dass ich folgenden Befehl aufrufen muss, damit der Prozess startet:
(Quelle: http://www.wsoftware.de/practices/proc-execs.html)

Java:
Process process = Runtime.getRuntime().exec("cmd /c start " + command);

Dieser ruft dann bei mir die Windows Console auf und führt auch ggf. den Prozess durch.
Wenn die Datei schon existiert, muss ich dann nurnoch y oder n drücken.

Warum genau muss eigentlich die Windows Console geöffnet sein? Weiß jemand bescheid?
Geht das ganze nicht ohne Console??
 

Christopher25

Bekanntes Mitglied
Übrigends... wenn ich
Java:
int result = process.waitFor();
mache,
dann geht der sofort weiter im Programm.
Das liegt höchstwarscheinlich daran, dass ich die CMD-Gui Console starte oder?
Kann ich das irgendwie so machen, dass er auch wirklich wartet, bis der Process fertig ist?
 

Christopher25

Bekanntes Mitglied
Wenn ich den Befehl ohne das "cmd /c start " losschicke, öffnet sich die Windows Shell ja nicht.
Jetzt ist mir aber aufgefallen, dass der Process im TaskManager angezeigt wird, aber keine Leistung von der CPU bekommt. Erst wenn ich die Java Anwendung abschieße, bekomm der Prozess vom FFMPEG Leistung zugewiesen und arbeitet.
Wenn ich jedoch die Windows Shell öffnen lasse, arbeitet er direkt, jedoch wartet mein Programm bei dem waitFor(); nicht mehr bis der Prozess zuende gelaufen ist, der soll aber vorher die Datei Konvertieren um diese dann anschließend zu öffnen/abzuspielen (JavaFX).
Wenn ich die Funktion wait(); benutzte von der Process.class dann bleibt das JavaProgramm irgendwie komplett weg und öffnet sich auch später nicht mehr.
Ich habe zwar gelesen, dass man in einem anderen Thread dann ein notifyAll(); anwenden soll, hilft bei mir aber irgendwie nicht wirklich.

Kann mir jemand helfen?


So ich lass die Frage mal stehen, da ich jetzt direkt die Auflösung gebe, die ich in dieser Sekunde herausgefunden und erfolgreich getestet habe^^ (tut mir leid, dass ich hier soviel schreibe und selber lösen konnte).
Aber falls jemand mal den selben Fehler macht wie ich, dann kann ich ihm hiermit helfen.

Der Prozess wartet nicht auf Fertigstellung, weil man ihm das anscheinend sagen muss. Hier ist die der Befehl, der bei mir geholfen hat:

Java:
Process process = Runtime.getRuntime().exec("cmd /c start /wait " + command);

process.waitFor();
 
Zuletzt bearbeitet:

Ähnliche Java Themen

Neue Themen


Oben