2016-05-12 12 views
0

Ich habe einen Dienst, der große Menge von Videos mit unterschiedlichen Formaten transcodieren muss. Der Service laicht fünf Fäden, ein für ein einzelnes Video und jeder Thread läuft ffmpeg mit dem folgenden Befehl:ffmpeg hängt, wenn in einer Umgebung mit mehreren Threads

ffmpeg -i %%FILEPATH%% -vf scale=X:Y -ab 128k -c:a aac -movflags faststart -strict -2 -ar 22050 -r 24 -c:v libx264 -crf 25 -y %%OUTPUT.MP4%%

wo X und Y die basierend gewünschten Abmessungen auf der Ausrichtung der Original-Datei im Grunde seines entweder 640:trunc(ow*a/2)*2 für Landschaft oder trunc(oh*a/2)*2:640 für Porträt.

Das ist mein ffmpeg Info:

ffmpeg version 2.4.3-1ubuntu1~trusty6 Copyright (c) 2000-2014 the FFmpeg developers 
    built on Nov 22 2014 17:07:19 with gcc 4.8 (Ubuntu 4.8.2-19ubuntu1) 
    configuration: --prefix=/usr --extra-version='1ubuntu1~trusty6' --build-suffix=-ffmpeg --toolchain=hardened --extra-cflags= --extra-cxxflags= --libdir=/usr/lib/x86_64-linux-gnu --shlibdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --enable-shared --disable-stripping --enable-avresample --enable-avisynth --enable-fontconfig --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-librtmp --enable-libschroedinger --enable-libshine --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-opengl --enable-x11grab --enable-libxvid --enable-libx265 --enable-libdc1394 --enable-libiec61883 --enable-libzvbi --enable-libzmq --enable-frei0r --enable-libx264 --enable-libsoxr --enable-openal --enable-libopencv 
    libavutil  54. 7.100/54. 7.100 
    libavcodec  56. 1.100/56. 1.100 
    libavformat 56. 4.101/56. 4.101 
    libavdevice 56. 0.100/56. 0.100 
    libavfilter  5. 1.100/5. 1.100 
    libavresample 2. 1. 0/2. 1. 0 
    libswscale  3. 0.100/3. 0.100 
    libswresample 1. 1.100/1. 1.100 
    libpostproc 53. 0.100/53. 0.100 
Hyper fast Audio and Video encoder 
usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}... 

Der Service ist in Java geschrieben und läuft auf Ubuntu Server 14.04 und die Maschine ist ein 64-Bit-Octa-Core-Server.

Dies ist der Code-Block, die ffmpeg ausführt:

try 
{ 
    ProcessBuilder procBuilder = null; 


    String sArgs = String.format("ffmpeg -i %s -vf scale=%s:%s -ab 128k -c:a aac -movflags faststart -strict -2 -ar 22050 -r 24 -c:v libx264 -crf 25 -y %s", 
       originalPath, 
       outWidth, 
       outHeight, 
       targetPath 
     ); 

    } 

    String[] arrArgs = sArgs.split("\\s+"); 
    procBuilder = new ProcessBuilder(Arrays.asList(arrArgs)); 
    procBuilder.redirectErrorStream(true); 
    procBuilder.redirectOutput(); 


    Process process = procBuilder.start(); 

    try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) 
    { 
     String line = null; 
     while ((line = reader.readLine()) != null) 
     { 
      System.out.println(line); 
     } 
     errorCode = process.waitFor(); 
    } 
} 
catch(Throwable ex) 
{ 
} 

I fünf Threads sind derzeit Laichen und jeder Thread läuft eine einzelne Instanz ffmpeg eine einzelne Videodatei Targeting. Dies funktioniert die meiste Zeit gut, aber ab und zu fangen Threads an zu hängen. Ich bemerkte von oben, dass ffmpeg für einige Dateien unbegrenzt hängt, wobei einer der Threads 100% der Kern-CPU verwendet und kein Fortschritt gemacht wird. Es ist mit verschiedenen Dateitypen passiert, wie ich es auf mkv, avi, wmv und mp4 Dateien bemerkt habe.

Ich bin nicht sicher, was bewirkt, dass ffmpeg hängen bleibt, es passiert nicht gleich zu Beginn des Transcodierungsprozesses, ffmpeg fängt an, die Datei zu konvertieren, aber irgendwo in der Mitte bleibt es hängen.

Jetzt ist dies kein Problem mit den Dateien, als wenn ich den gleichen Befehl auf die gleiche Datei manuell versuchen, läuft es gut. Und es scheint nur dann zu passieren, wenn mehrere Instanzen von ffmpeg zur gleichen Zeit laufen, als ich meinen Dienst geändert habe, um nur einen einzigen Thread auszuführen, und er läuft seit fast einem Monat ohne Probleme.

Gibt es eine Option, die ich verwenden muss, um zu ermöglichen, dass mehrere Instanzen von ffmpeg gleichzeitig ausgeführt werden? Ist es etwas in der Befehlszeile, die ich derzeit verwende, die das verursacht?

+0

Sie haben also 8 Kerne (echte Kerne)? Wie misst du wieder? Können Sie die Festplattenaktivität für jede Zieldatei überwachen? Beachten Sie, dass ffmpeg viel in stderr schreibt, so dass Sie den Fehlerstream in den Ausgabestrom umleiten müssen, sonst werden Sie eine Menge Informationen verpassen. – UmNyobe

+0

@UmNyobe Ja, ich habe auch versucht, stderr umzuleiten, aber ffmpeg schreibt keine Ausgabe. Das erste Mal, als ich bemerkte, dass mein Dienst aufhörte, Dateien zur Verarbeitung zu ziehen. Ich habe das Ausgabeverzeichnis überprüft, in dem ich meine transcodierten Dateien gespeichert habe, und habe festgestellt, dass keine Dateien geändert werden. Auch von oben sah ich, dass ich 5 Prozesse von ffmpeg ausgeführt habe. Jeder Prozess hat etwa 20 Threads hervorgebracht und nur einer davon verwendete 100% der CPU.Ich ließ es für etwa eine Stunde laufen und kam zurück und es war immer noch das gleiche, Ausgabedatei Größen blieben gleich und die gleichen genauen Threads war mit 100% CPU –

+0

@UmNyobe nur um zu klären, wenn ich sagte 'ein einziger Thread' ich bedeutete, dass jeder ffmpeg-Prozess einen einzelnen Thread hatte, der bei 100% lief CPU –

Antwort

1

libx264 verwendet standardmäßig eine Anzahl von Threads, die 1,5 * logischen Kernen entsprechen (für rahmenbasiertes Multithreading). Multiplizieren Sie dies mit fünf Instanzen und Sie erhalten viele Threads, und dies ist nur für die Codierung des Videostreams.

Sie können versuchen, die Anzahl der verwendeten Threads für jede Instanz zu reduzieren, indem Sie die Option -x264opts threads=n einstellen.

+0

Und Was würde das erreichen? –

+0

Diese Threads sind CPU-intensiv. Die Standardeinstellungen funktionieren möglicherweise für einen einzelnen Befehl, aber da Sie mehrere Instanzen ausführen, erzeugen Sie eine hohe CPU-Anforderung. Durch das Reduzieren der einzelnen Anzahl von Threads können Sie möglicherweise mehrere Instanzen ausführen und dieses Deadlock vermeiden. Leistungsmäßig müssen Sie Benchmarks durchführen, um zu sehen, was passiert, da zu viele Threads nur auf die CPU warten. – aergistal

+0

Thread-Konfiguration basierend auf Nr. von CPU-Kernen http://stackoverflow.com/questions/13834692/threads-configuration-based-on-no-of-cpu-cores – aergistal

Verwandte Themen