1414except ImportError :
1515 sys .exit ("FATAL: failed to import TranscodeSession from src/TranscodeSession.py\n " )
1616
17- """
17+ def validate_args ():
18+ """ Exits with error messages if command-line arguments are invalid
19+ """
20+ parser = argparse .ArgumentParser (description = "Transcodes given file(s) to HEVC format." )
21+ install_group = parser .add_mutually_exclusive_group ()
22+ install_group .add_argument ("--install" , action = "store_true" , help = "install symlink to transcode.py on $PATH" )
23+ install_group .add_argument ("--uninstall" , action = "store_true" , help = "remove symlink to transcode.py" )
24+ files_group = parser .add_mutually_exclusive_group ()
25+ files_group .add_argument ("--file" , help = "relative path to movie in source directory" )
26+ files_group .add_argument ("--all" , action = "store_true" , help = "transcode all supported movies in source directory" )
27+ parser .add_argument ("--quality" , type = int , help = "HandBrake quality slider value (-12,51)" )
28+ parser .add_argument ("--preset" , help = "override video encoder preset" )
29+ preset_group = parser .add_mutually_exclusive_group ()
30+ preset_group .add_argument ("--baseline" , action = "store_true" , help = "use baseline encoder options" )
31+ preset_group .add_argument ("--best" , action = "store_true" , help = "use highest quality encoder options" )
32+ parser .add_argument ("--small" , action = "store_true" , help = "use additional encoder options to minimize filesize at the expense of speed" )
33+ parser .add_argument ("--delete" , action = "store_true" , help = "delete output files when complete/interrupted" )
34+ args = parser .parse_args ()
35+
36+ valid_arguments = False
1837
19- TODO:
20- - allow comma-separated string for --preset, e.g. medium,slow,slower, map to list
21- - add check: if working directory == script location, exit with warning to symlink transcode.py onto $PATH, else if different directory but no symlink, prompt to run --install
22- - add --install arg (with optional path to custom $PATH location) to create symlink at /usr/local/bin or custom $PATH location?
23- - once profiling is complete, only append file decorator if --test is specified
38+ if args .install or args .uninstall :
39+ if len (sys .argv ) > 2 :
40+ print ("\n FATAL: --install/--uninstall may not be called with any other arguments" )
41+ else :
42+ if args .install :
43+ symlink (True )
44+ else :
45+ symlink (False )
46+ elif os .path .dirname (os .path .realpath (__file__ )) == os .getcwd ():
47+ print ("\n FATAL: invalid working directory: running from master directory. Please create working directory in another location." )
48+ elif not "source" in os .listdir ():
49+ print ("\n FATAL: invalid working directory: ./source/ does not exist" )
50+ elif args .file and not os .path .exists (args .file ):
51+ print ("\n FATAL:" , args .file , "not found!" )
52+ elif args .preset and not args .preset .lower () in ("ultrafast" , "superfast" , "veryfast" , "faster" , "fast" , "medium" , "slow" , "slower" , "veryslow" , "placebo" ):
53+ print ("\n FATAL:" , args .preset , "not valid!" )
54+ elif args .quality and not args .quality in range (- 12 , 51 ):
55+ print ("\n ATAL: quality must be between -12 and 51 (lower is slower + higher quality)" )
56+ else :
57+ valid_arguments = True
2458
25- """
59+ if not valid_arguments :
60+ sys .exit ("Invalid command-line arguments.\n " )
61+ elif args .all and args .quality :
62+ print ("\n Warning! Combining --all and --quality options is not recommended and may not produce optimal HEVC transcodes." )
63+ proceed = get_user_response ()
64+ if not proceed :
65+ sys .exit ("Aborting invocation with --all and --quality options.\n " )
66+
67+ if not os .path .isdir ("performance" ):
68+ try :
69+ os .mkdir ("performance" )
70+ except FileExistsError :
71+ sys .exit ("\n FATAL: can't create directory \" performance\" because file with same name exists" )
72+ if not os .path .isdir ("hevc" ):
73+ try :
74+ os .mkdir ("hevc" )
75+ except FileExistsError :
76+ sys .exit ("\n FATAL: can't create directory \" hevc\" because file with same name exists" )
77+
78+ return args
79+
80+ def get_user_response ():
81+ """ Accepts yes/no answer as user input and returns as boolean
82+ """
83+ while "need response" :
84+ reply = str (input (" Proceed? (y/n) " )).lower ().strip ()
85+ if len (reply ) > 0 :
86+ if reply [0 ] == "y" :
87+ response = True
88+ break
89+ if reply [0 ] == "n" :
90+ response = False
91+ break
92+
93+ return response
94+
95+ def symlink (install ):
96+ """ Installs / uninstalls a symlink to transcode.py in /usr/local/bin or alternate $PATH location
97+ """
98+ script_name = os .path .basename (sys .argv [0 ])
99+ script_realpath = os .path .realpath (__file__ )
100+ script_on_path = False
101+ for location in os .get_exec_path ():
102+ if script_name in os .listdir (location ):
103+ script_on_path = True
104+ script_path_location = os .path .join (location , script_name )
105+ break
106+
107+ if script_on_path :
108+ path_dir = os .path .dirname (script_path_location )
109+ script_executable = os .access (script_realpath , os .X_OK )
110+
111+ if install :
112+ if script_on_path :
113+ sys .exit ("\n {script_name} already on $PATH at {script_path_location}, skipping install.\n " .format (script_name = script_name , script_path_location = script_path_location ))
114+ else :
115+ print ("\n Create symlink for {script_name} on $PATH?" .format (script_name = script_name ))
116+ proceed = get_user_response ()
117+ if proceed :
118+ if not oct (os .stat (script_realpath ).st_mode )[- 3 :] == 755 :
119+ os .chmod (script_realpath , 0o755 )
120+ print ("Use default location? /usr/local/bin" )
121+ default_location = get_user_response ()
122+ if default_location :
123+ os .symlink (script_realpath , os .path .join ("/usr/local/bin" , script_name ))
124+ sys .exit ("Created symlink to {script_name} in /usr/local/bin\n " )
125+ else :
126+ print ("Use alternate $PATH location?" )
127+ alternate_location = get_user_response ()
128+ if alternate_location :
129+ alternate_path = str (input ("Alternate $PATH location: (case-sensitive) " ))
130+ if alternate_path [0 ] == "~" : alternate_path = os .path .expanduser (alternate_path )
131+ if alternate_path in os .get_exec_path ():
132+ os .symlink (script_realpath , os .path .join (alternate_path , script_name ))
133+ sys .exit ("Created symlink to {script_name} in {alternate_path}\n " .format (script_name = script_name , alternate_path = alternate_path ))
134+ else :
135+ sys .exit ("\n Error: {alternate_path} not found on $PATH, aborting install.\n " .format (alternate_path = alternate_path ))
136+ else :
137+ sys .exit ("Aborting install.\n " )
138+ else :
139+ sys .exit ("Aborting install.\n " )
140+ else :
141+ if not script_on_path :
142+ sys .exit ("\n {script_name} not on $PATH, skipping uninstall.\n " .format (script_name = script_name ))
143+ else :
144+ print ("\n Found {script_name} on $PATH in {path_dir}\n " .format (script_name = script_name , path_dir = path_dir ))
145+ if os .path .islink (script_path_location ):
146+ print ("Remove symlink to {script_name} in {path_dir}?" .format (script_name = script_name , path_dir = path_dir ))
147+ proceed = get_user_response ()
148+ if proceed :
149+ os .unlink (script_path_location )
150+ print ("Unlinked {script_path_location}\n " .format (script_path_location = script_path_location ))
151+ else :
152+ sys .exit ("Aborting uninstall.\n " )
153+ else :
154+ sys .exit ("Error: {script_path_location} exists on $PATH but is not a symlink, skipping uninstall.\n " .format (script_path_location = script_path_location ))
155+ sys .exit ()
26156
27157def build_source_list (args ):
28158 """ Constructs and returns list of source files
29159 """
30160 extensions = [".mp4" , ".m4v" , ".mov" , ".mkv" , ".mpg" , ".mpeg" , ".avi" , ".wmv" , ".flv" , ".webm" , ".ts" ]
161+
31162 print ("\n Building source list..." )
163+
32164 if args .all :
33165 source_files = ["source/" + file for file in os .listdir ("source" ) if os .path .splitext (file )[1 ].lower () in extensions ]
34166 else :
@@ -44,66 +176,17 @@ def build_source_list(args):
44176 source_files = [file for file in source_files if file is not source_file ]
45177
46178 if len (source_files ) == 0 :
47- sys .exit ("All supported files in ./source/ have already been transcoded. Exiting.\n " )
179+ if args .all :
180+ sys .exit ("All supported files in ./source/ have already been transcoded. Exiting.\n " )
181+ else :
182+ sys .exit ("File exists. Exiting." )
48183 else :
49184 print (str (source_files ) + "\n " )
50185
51186 return source_files
52187
53- def validate_args (args ):
54- """ Exits with error messages if command-line arguments are invalid
55- """
56- valid_arguments = False
57- if not "source" in os .listdir ():
58- print ("FATAL: invalid working directory!" )
59- elif args .file and not os .path .exists (args .file ):
60- print ("FATAL:" , args .file , "not found!" )
61- elif args .preset and not args .preset .lower () in ("ultrafast" , "superfast" , "veryfast" , "faster" , "fast" , "medium" , "slow" , "slower" , "veryslow" , "placebo" ):
62- print ("FATAL:" , args .preset , "not valid!" )
63- elif args .quality and not args .quality in range (- 12 , 51 ):
64- print ("FATAL: quality must be between -12 and 51 (lower is slower + higher quality)" )
65- else :
66- valid_arguments = True
67-
68- if not valid_arguments :
69- sys .exit ("Invalid command-line arguments.\n " )
70- elif args .all and args .quality :
71- print ("Warning! Combining --all and --quality options is not recommended and may not produce optimal HEVC transcodes." )
72- while "need response" :
73- reply = str (input ("Proceed? (y/n)" )).lower ().strip ()
74- if reply [0 ] == "y" :
75- break
76- if reply [0 ] == "n" :
77- sys .exit ("Aborting invocation with --all and --quality options.\n " )
78-
79- if not os .path .isdir ("performance" ):
80- try :
81- os .mkdir ("performance" )
82- except FileExistsError :
83- sys .exit ("FATAL: can't create directory \" performance\" because file with same name exists" )
84- if not os .path .isdir ("hevc" ):
85- try :
86- os .mkdir ("hevc" )
87- except FileExistsError :
88- sys .exit ("FATAL: can't create directory \" hevc\" because file with same name exists" )
89-
90188def main ():
91- # Define command-line arguments
92- parser = argparse .ArgumentParser ()
93- files_group = parser .add_mutually_exclusive_group (required = True )
94- files_group .add_argument ("-f" , "--file" , help = "relative path to movie in source directory" )
95- files_group .add_argument ("--all" , action = "store_true" , help = "transcode all supported movies in source directory" )
96- parser .add_argument ("-q" , "--quality" , type = int , help = "HandBrake quality slider value (-12,51)" )
97- parser .add_argument ("--preset" , help = "override video encoder preset" )
98- preset_group = parser .add_mutually_exclusive_group (required = False )
99- preset_group .add_argument ("--baseline" , action = "store_true" , help = "use baseline encoder options" )
100- preset_group .add_argument ("--best" , action = "store_true" , help = "use highest quality encoder options" )
101- parser .add_argument ("--small" , action = "store_true" , help = "use additional encoder options to minimize filesize at the expense of speed" )
102- parser .add_argument ("--delete" , action = "store_true" , help = "delete output files when complete/interrupted" )
103- args = parser .parse_args ()
104- validate_args (args )
105-
106- # Do the thing
189+ args = validate_args ()
107190 source_files = build_source_list (args )
108191 time_script_started = datetime .now ()
109192 for file in source_files :
0 commit comments