From 6bb819a6a0320baf71a7b24d882b642edc038f23 Mon Sep 17 00:00:00 2001 From: Stefan Brand Date: Thu, 23 Feb 2012 08:43:14 +0100 Subject: [PATCH 1/7] Version 1.1.1 Fixed README formating --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index c34cbc8..520d153 100644 --- a/README +++ b/README @@ -6,7 +6,7 @@ PREQUISITES: The following components are needed: * mplayer - * ffmpeg (tested with version 0.10, older versions may or may not work) + * ffmpeg (tested with version 0.10, older versions may or may not work) * python USAGE: From 86eacfa9b5e1796bed58777eb012b8e2d8671d4b Mon Sep 17 00:00:00 2001 From: Stefan Brand Date: Fri, 23 Mar 2012 20:25:16 +0100 Subject: [PATCH 2/7] Version 1.2 Added possibility for CRF-Encoding Default Quality is now CRF at factor 22 Some Encoding Tweaks and default values for the Nokia N9 --- n900-encode.py | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/n900-encode.py b/n900-encode.py index 0f06f4e..3ab601d 100755 --- a/n900-encode.py +++ b/n900-encode.py @@ -4,7 +4,7 @@ # n900-encode.py: Encode almost any Video to an Nokia N900-compatible format (h264,aac,mp4) # Disclaimer: This program is provided without any warranty, USE AT YOUR OWN RISK! # -# Version 1.1 (22.02.2012) +# Version 1.2 (23.03.2012) # # (C) 2010-2012 Stefan Brand # @@ -21,12 +21,12 @@ from time import sleep # Default values, feel free to adjust ########################################################################################### -_basewidth = 800 # Base width for widescreen Video +_basewidth = 854 # Base width for widescreen Video _basewidth43 = 640 # Base width for 4:3 Video _maxheight = 480 # maximum height allowed -_abitrate = 96 # Audio Bitrate in kBit/s -_vbitrate = 500 # Video Bitrate in kBit/s -_threads = 2 # Use n Threads to encode +_abitrate = 112 # Audio Bitrate in kBit/s +_vbitrate = 22 # Video Bitrate in kBit/s, Values < 52 are used as a CRF-Factor +_threads = "auto" # Use n Threads to encode _mpbin = None # mplayer binary, if set to None it is searched in your $PATH _ffbin = None # ffmpeg binary, if set to None it is searched in your $PATH @@ -56,7 +56,7 @@ def main(argv): output = "n900encode.mp4" mpopts = "" abitrate = _abitrate * 1000 - vbitrate = _vbitrate * 1000 + vbitrate = int(_vbitrate) threads = _threads overwrite = False for opt, arg in opts: @@ -69,7 +69,7 @@ def main(argv): elif opt in ("-a", "--abitrate"): abitrate = int(arg) * 1000 elif opt in ("-v", "--vbitrate"): - vbitrate = int(arg) * 1000 + vbitrate = int(arg) elif opt in ("-t", "--threads"): threads = arg elif opt in ("-f", "--force-overwrite"): @@ -165,7 +165,7 @@ def convert(input, output, res, abitrate, vbitrate, threads, mpopts): # Define mplayer command for video decoding mpvideodec = [ mpbin, "-sws", "9", - "-vf", "scale=" + str(res[0]) + ":" + str(res[1]) + ",unsharp=c4x4:0.3:l5x5:0.5", + "-vf", "scale=" + str(res[0]) + ":" + str(res[1]) + ",dsize=" + str(res[0]) + ":" + str(res[1]) + ",unsharp=c4x4:0.3:l5x5:0.5", "-ass", "-vo", "yuv4mpeg:file=" + vfifo, "-ao", "null", "-nosound", @@ -193,6 +193,14 @@ def convert(input, output, res, abitrate, vbitrate, threads, mpopts): # Define ffmpeg command for a/v encoding + + if (vbitrate > 51): + rmode = "-b:v" + vbitr = str(vbitrate*1000) + else: + rmode = "-crf" + vbitr = str(vbitrate) + ffmenc = [ ffbin, "-f", "yuv4mpegpipe", "-i", vfifo, @@ -206,17 +214,13 @@ def convert(input, output, res, abitrate, vbitrate, threads, mpopts): "-threads", str(threads), "-vprofile", "baseline", "-tune", "animation", - "-b:v", str(vbitrate), - "-flags", "+loop", "-cmp", "+chroma", + rmode, vbitr, + "-flags", "+loop", "-cmp", "+chroma", "-coder", "0", "-partitions", "+parti4x4+partp8x8+partb8x8", - "-subq", "5", "-trellis", "1", "-refs", "1", - "-coder", "0", "-me_range", "16", - "-g", "300", "-keyint_min", "25", - "-sc_threshold", "40", "-i_qfactor", "0.71", - "-bt", "640", "-bufsize", "10M", "-maxrate", "1000000", - "-rc_eq", "'blurCplx^(1-qComp)'", - "-qcomp", "0.62", "-qmin", "10", "-qmax", "51", - "-x264opts", "level=3.0", "-f", "mp4", + "-subq", "7", "-trellis", "1", "-refs", "3", + "-me_range", "16", "-me_method", "hex", + "-bufsize", "10M", "-maxrate", "1000000", + "-x264opts", "level=3.1", "-f", "mp4", output ] # Start mplayer decoding processes in background @@ -273,7 +277,7 @@ def usage(): print(" --output [-o]: Name of the converted Video") print(" --mpopts \"\" [-m]: Additional options for mplayer (eg -sid 1 or -aid 1) Must be enclosed in \"\"") print(" --abitrate
[-a]: Audio Bitrate in KBit/s") - print(" --vbitrate
[-v]: Video Bitrate in kBit/s") + print(" --vbitrate
[-v]: Video Bitrate in kBit/s, values less than 52 will be used as CRF-Factor") print(" --threads [-t]: Use Threads to encode") print(" --force-overwrite [-f]: Overwrite output-file if existing") print(" --help [-h]: Print this Help") From 05ef2a0f8ce835116d485f9cbe8c04f474b601ba Mon Sep 17 00:00:00 2001 From: Andrwe Lord Weber Date: Wed, 29 Aug 2012 11:13:34 +0300 Subject: [PATCH 3/7] Deleted a misplaced tab --- n900-encode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/n900-encode.py b/n900-encode.py index 3ab601d..f89e7cf 100755 --- a/n900-encode.py +++ b/n900-encode.py @@ -236,7 +236,7 @@ def convert(input, output, res, abitrate, vbitrate, threads, mpopts): subprocess.check_call(ffmenc) except subprocess.CalledProcessError: print("Error: Encoding thread failed!") - sys .exit(4) + sys.exit(4) def progpath(program): From b60e8edf7accf2cf9ca3e725e2171a06996ded20 Mon Sep 17 00:00:00 2001 From: Stefan Brand Date: Wed, 29 Aug 2012 10:35:10 +0200 Subject: [PATCH 4/7] Removed the unneeded exit from the cleanup function --- n900-encode.py | 1 - 1 file changed, 1 deletion(-) diff --git a/n900-encode.py b/n900-encode.py index f89e7cf..67e07eb 100755 --- a/n900-encode.py +++ b/n900-encode.py @@ -264,7 +264,6 @@ def cleanup(): os.remove(afifo) if (vfifo != None): os.remove(vfifo) - os._exit(0) def usage(): """Print avaiable commandline arguments""" From 7fc87e6be91e37f2270a7c0aeb50bff9cd6a81cf Mon Sep 17 00:00:00 2001 From: Stefan Brand Date: Wed, 29 Aug 2012 10:47:20 +0200 Subject: [PATCH 5/7] Added some error handling for invalid commandline options --- n900-encode.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/n900-encode.py b/n900-encode.py index 67e07eb..2aad794 100755 --- a/n900-encode.py +++ b/n900-encode.py @@ -48,8 +48,11 @@ def main(argv): # CLI Argument Processing try: opts, args = getopt.getopt(argv, "i:o:m:v:a:t:hf", ["input=", "output=", "mpopts=", "abitrate=", "vbitrate=", "threads=", "help", "force-overwrite"]) - except getopt.GetoptError as err: - printi(str(err)) + except: + usage() + + if (len(args) != 0): + print("Error: Unsupported Arguments found!") usage() input = None @@ -256,9 +259,11 @@ def cleanup(): # Cleanup try: if (mda != None): - os.kill(mda.pid()) + if (mda.pid() != None): + os.kill(mda.pid()) if (mdv != None): - os.kill(mdv.pid()) + if (mda.pid() != None): + os.kill(mdv.pid()) finally: if (afifo != None): os.remove(afifo) From a0ed1528460f07abb7faa80d46dd55109d0a2ab2 Mon Sep 17 00:00:00 2001 From: Stefan Brand Date: Wed, 29 Aug 2012 10:51:57 +0200 Subject: [PATCH 6/7] Added Error handling for missing input file --- n900-encode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/n900-encode.py b/n900-encode.py index 2aad794..04b606c 100755 --- a/n900-encode.py +++ b/n900-encode.py @@ -102,7 +102,7 @@ def main(argv): sys.exit(1) # Check input and output files - if not os.path.isfile(input): + if (input == None or not os.path.isfile(input)): print("Error: input file is not a valid File or doesn't exist") sys.exit(2) From 30359c25dd4c270520a095f4aa5b49ebd9846fc3 Mon Sep 17 00:00:00 2001 From: Stefan Brand Date: Wed, 29 Aug 2012 11:49:05 +0200 Subject: [PATCH 7/7] Added more error handling --- n900-encode.py | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/n900-encode.py b/n900-encode.py index 04b606c..5ac67c8 100755 --- a/n900-encode.py +++ b/n900-encode.py @@ -83,7 +83,7 @@ def main(argv): # Check for needed Programs global mpbin mpbin = None - if not _mpbin == None and os.path.exists(_mpbin) and not os.path.isdir(_mpbin): + if not _mpbin == None and os.path.isfile(_mpbin): mpbin = _mpbin else: mpbin = progpath("mplayer") @@ -93,7 +93,7 @@ def main(argv): global ffbin ffbin = None - if not _ffbin == None and os.path.exists(_ffbin) and not os.path.isdir(_ffbin): + if not _ffbin == None and os.path.isfile(_ffbin): ffbin = _ffbin else: ffbin = progpath("ffmpeg") @@ -124,7 +124,11 @@ def calculate(input): # Get characteristics using mplayer cmd=[mpbin, "-ao", "null", "-vo", "null", "-frames", "0", "-identify", input] - mp = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() + try: + mp = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() + except: + print("Error: Couldn't execute mplayer") + sys.exit(1) try: s = re.compile("^ID_VIDEO_ASPECT=(.*)$", re.M) @@ -162,8 +166,12 @@ def convert(input, output, res, abitrate, vbitrate, threads, mpopts): pid = os.getpid() afifo = "/tmp/stream" + str(pid) + ".wav" vfifo = "/tmp/stream" + str(pid) + ".yuv" - os.mkfifo(afifo) - os.mkfifo(vfifo) + try: + os.mkfifo(afifo) + os.mkfifo(vfifo) + except: + print("Error: Couldn't create fifos!") + sys.exit(2) # Define mplayer command for video decoding mpvideodec = [ mpbin, @@ -233,7 +241,16 @@ def convert(input, output, res, abitrate, vbitrate, threads, mpopts): except: print("Error: Starting decoding threads failed!") sys.exit(3) - + + print("Waiting for decoding threads to start...") + + # Wait + sleep(2) + # Check if the decoding processes are running + if (mda.poll() != None or mdv.poll() != None): + print("Error: Starting decoding threads failed!") + sys.exit(3) + # Start ffmpeg encoding process in foreground try: subprocess.check_call(ffmenc) @@ -259,21 +276,21 @@ def cleanup(): # Cleanup try: if (mda != None): - if (mda.pid() != None): - os.kill(mda.pid()) + if (mda.returncode == None): + mda.kill() if (mdv != None): - if (mda.pid() != None): - os.kill(mdv.pid()) + if (mdv.returncode == None): + mdv.kill() finally: - if (afifo != None): + if (afifo != None and os.path.exists(afifo)): os.remove(afifo) - if (vfifo != None): + if (vfifo != None and os.path.exists(vfifo)): os.remove(vfifo) def usage(): """Print avaiable commandline arguments""" - print("This is n900-encode.py (C) 2010 Stefan Brand ") + print("This is n900-encode.py (C) 2012 Stefan Brand ") print("Usage:") print(" n900-encode.py --input [opts]\n") print("Options:")