Optimale Parameter für FFMPEG, um die Dateigröße beizubehalten

Optimale Parameter für FFMPEG, um die Dateigröße beizubehalten

Die Idee ist also: Ich möchte jedes einzelne Video, das ich auf einem 1-Terabyte-Laufwerk habe, in ein Format konvertieren, das mein Chromecast abspielen kann (https://developers.google.com/cast/docs/media) und ich werde meinen nicht mehr ganz so neuen PC gerne ein paar Tage (Wochen?) lang laufen lassen, um das zu tun. Großartig, FFMPEG ist die Rettung.

ein wenig Hintergrund: Ich bin ein Android-/Java-Entwickler (sehr aktiv bei StackOverflow) und ich weiß, dass ich irgendwann nur noch ein paar Batch-Skripte oder eine schnelle Java-Befehlszeile codieren muss (weil ich mit Java besser zurechtkomme), um die Arbeit zu erledigen, aber ich bin mir noch nicht sicher, welche Argumente ich in meiner FFMPEG-Befehlszeile verwenden soll.

Meine Anforderungen sind also: - Videocodec: H.264 High Profile Level 5 - Audiocodec: einer von HE-AAC, LC-AAC, MP3 (ehrlich gesagt kenne ich den Unterschied nicht, vielleicht ist AAC besser?), alles gleich lassen - ich möchte auf jeden Fall die langsame oder langsamere Version verwenden (für bessere Qualität) - ich möchte auf jeden Fall 2-Pass mit variabler Bitrate verwenden (für bessere Qualität)

Ich habe in den Tutorials und Handbüchern nachgelesen, wie das alles funktioniert. Jetzt kommt der Teil, bei dem ich mir nicht ganz sicher bin, wie ich ihn hinbekomme:

Ich möchte, dass die endgültige Dateigröße ungefähr der Originalgröße entspricht. Das liegt daran, dass das Laufwerk zu etwa 80 % voll ist und ich es nicht durch einfaches Konvertieren füllen möchte. Im Skript werde ich die Datei neu kodieren und das Original löschen, damit alles ohne Probleme weiterläuft.

wie komme ich also von der Dateigröße zur Video-Bitrate und Audio-Bitrate, um sie in das Skript einzufügen?

PS: Ich benutze die Handbremse genauso gerne, wenn jemand weiß, wie das geht.

danke im voraus für die hilfe.

Antwort1

Der benötigte ffmpeg-Befehl sieht etwa so aus:

ffmpeg -i input.foo -c:v libx264 -profile:v high -level 5 -preset slow -b:v $videobitrate -an -pass 1 output.bar;
ffmpeg -y -i input.foo -c:v libx264 -profile:v high -level 5 -preset slow -b:v $videobitrate -b:a $audiobitrate -pass 2 output.bar

libx264 ist der h264-Encoder, und alle Optionen werden von ffmpeg an ihn übergeben, sie sind ziemlich selbsterklärend. Der erste Durchgang benötigt kein Audio, daher das -an. Sie können die Ausgabe nach /dev/null weiterleiten, wenn Sie möchten, aber egal. Ich verwende im zweiten Durchgang einfach den Schalter -y, damit die temporäre Datei ohne Nachfrage überschrieben wird. Der Audiocodec ist standardmäßig aac, Sie müssen ihn also nicht angeben.

ffprobekann Ihnen helfen, den Wert von $videobitrate und $audiobitrate zu ermitteln (ich gehe von einer POSIX-Umgebung aus, sonst wären es %videobitrate% und %audiobitrate%). Sie müssen etwas Sed-, Awk- oder Perl-Voodoo anwenden, um die Werte in eine Form zu bringen, die Sie verwenden können. Hier ist die Ausgabe von ffprobe auf einer zufälligen MP4 auf meinem Rechner:

ffprobe version 2.1.3 Copyright (c) 2007-2013 the FFmpeg developers
  built on Feb 12 2014 22:10:38 with Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/2.1.3 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-nonfree --enable-hardcoded-tables --enable-avresample --enable-vda --cc=clang --host-cflags= --host-ldflags= --enable-libx264 --enable-libfaac --enable-libmp3lame --enable-libxvid --enable-libfreetype --enable-libtheora --enable-libvorbis --enable-libvpx --enable-librtmp --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libvo-aacenc --enable-libass --enable-ffplay --enable-libspeex --enable-libschroedinger --enable-libfdk-aac --enable-openssl --enable-libopus --enable-frei0r --enable-libcaca --enable-libopenjpeg --extra-cflags='-I/usr/local/Cellar/openjpeg/1.5.1/include/openjpeg-1.5 '
  libavutil      52. 48.101 / 52. 48.101
  libavcodec     55. 39.101 / 55. 39.101
  libavformat    55. 19.104 / 55. 19.104
  libavdevice    55.  5.100 / 55.  5.100
  libavfilter     3. 90.100 /  3. 90.100
  libavresample   1.  1.  0 /  1.  1.  0
  libswscale      2.  5.101 /  2.  5.101
  libswresample   0. 17.104 /  0. 17.104
  libpostproc    52.  3.100 / 52.  3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'loop.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf55.19.104
  Duration: 00:00:19.56, start: 0.000000, bitrate: 201 kb/s
    Stream #0:0(eng): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 400x226 [SAR 226:225 DAR 16:9], 129 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 75 kb/s (default)
    Metadata:
      handler_name    : SoundHandler

ärgerlicherweise gibt ffprobe alles auf stderr aus, also müssen Sie es auf stdout umleiten. Ich werde Ihnen nicht sagen, wie man Eier lutscht, Ihr Sed-Fu ist vielleicht besser als meines, aber fürDiejenigen, die zu spät kamen, um die Bitrate für das ganze Zeug im obigen Beispiel zu erhalten, könnten Sie etwas wie Folgendes tun:

videobitrate=$(ffprobe input.foo 2>&1|grep bitrate |sed "s/.*bitrate: \([0-9]*\) \([km]*\).*/\1\2/")

und für den Ton:

audiobitrate=$(ffprobe input.foo 2>&1|grep Audio|sed "s/.* \([0-9]*\) \([km]*\)b\/s.*/\1\2/")

Ich bin mir nicht sicher, warum die Bitrate des Audios angegeben wurde, die des Videos jedoch nicht. Das könnte daran liegen, dass ich normalerweise mit einem konstanten Ratenfaktor komprimiere (konstante Qualität statt konstanter Bitrate). Sie müssen die ffprobe-Ausgabe Ihrer Filme überprüfen. Von dort aus liegt es an Ihnen, diese in die benötigten Variablen umzuwandeln. Beachten Sie, dass ffmpeg Zahlen wie 100k oder 3m analysiert.

verwandte Informationen