11import argparse
2+ import glob
23import os
34import sys
45
6+ from encode import encode_to_hevc
57from extract_audio import extract_audio
68from extract_subs import extract_subs
79from multi import multi
1113from utils import __current_version__ , is_tool , credz , str2dict
1214
1315# Constant variables
14- MODES_SUPPORTING_MULTI_INPUTS = ["shader" , "multi" ]
16+ MODES_SUPPORTING_MULTI_INPUTS = ["shader" , "multi" , "encode" ]
1517
1618# Print credits
1719credz ()
4345 subs - Extract subtitles from a media file
4446 mux - Mux/compile a media file with audio files and subtitle files
4547 multi - Apply shader with -ss and -sa, audio, subs and mux mode in order
48+ encode - Encode media files using X265 with predefined settings
4649 split - Split a media file into parts''' )
4750parser .add_argument ("-ew" , "--width" , required = False , type = int , default = 3840 ,
4851 help = "Desired width when applying shader" )
6972 default = False ,
7073 help = "Set this flag if you want to manually mux audio when using mode shader" )
7174parser .add_argument ("-sm" , "--skip_menus" , required = False , type = str2dict ,
72- help = '''Skip shader/encoding choice menus when using mode shader
73- Example :
75+ help = '''Skip choice menus
76+ Examples for mode shader :
7477 --skip_menus="shader=4,encoder=cpu,codec=h264,preset=fast,crf=23"
75- --skip_menus="shader=4,encoder=nvenc,codec=hevc,preset=fast,qp=24"''' )
78+ --skip_menus="shader=4,encoder=nvenc,codec=hevc,preset=fast,qp=24"
79+ Example for mode audio:
80+ --skip_menus="convert=0"
81+ Example for mode encode:
82+ --skip_menus="encode=0"''' )
7683parser .add_argument ("-al" , "--audio_language" , required = False , type = str ,
7784 help =
7885 '''Set this to the audio track language for the output video.
8289 action = 'store_true' ,
8390 default = False ,
8491 help = "Set this flag to delete output files that have failed to compile when using mode multi" )
92+ parser .add_argument ("-si" , "--skip_input" , required = False , action = 'append' ,
93+ help = "Input file to skip when using a directory as an input for modes shader and multi" )
8594
8695args = vars (parser .parse_args ())
8796if args ['version' ]:
@@ -97,21 +106,25 @@ def exit_if_missing(file_path: str, allow_dir: bool = True):
97106 elif allow_dir is False :
98107 print ("error: cannot use a directory ({0}) as an input for this mode"
99108 .format (file_path ))
109+ sys .exit (- 2 )
100110
101111
102- fn = args [ 'input' ]
112+ # Validate "mode" argument
103113mode = str (args ['mode' ]).lower ()
114+ if mode == "subtitles" :
115+ mode = "subs"
104116
105117# Validate "input" argument
118+ fn = args ['input' ]
106119if fn is None :
107120 parser .print_help ()
108121 print ("error: the following arguments are required: -i/--input" )
109122 sys .exit (- 2 )
110123if type (fn ) is list :
111124 if len (fn ) != 1 :
112- if mode != "shader" :
125+ if mode not in MODES_SUPPORTING_MULTI_INPUTS :
113126 print (
114- "error: Cannot use multiple inputs with mode={0}" .format (mode ))
127+ "error: cannot use multiple inputs with mode={0}" .format (mode ))
115128 sys .exit (- 2 )
116129 for file in fn :
117130 exit_if_missing (file , mode in MODES_SUPPORTING_MULTI_INPUTS )
@@ -120,9 +133,9 @@ def exit_if_missing(file_path: str, allow_dir: bool = True):
120133 exit_if_missing (fn , mode in MODES_SUPPORTING_MULTI_INPUTS )
121134else :
122135 exit_if_missing (fn , mode in MODES_SUPPORTING_MULTI_INPUTS )
123-
124- if mode == "subtitles" :
125- mode = "subs"
136+ if mode in MODES_SUPPORTING_MULTI_INPUTS :
137+ if type ( fn ) is str :
138+ fn = [ fn ]
126139
127140# Validate "output" argument
128141if mode == "audio" or mode == "subs" :
@@ -131,36 +144,86 @@ def exit_if_missing(file_path: str, allow_dir: bool = True):
131144 output = ""
132145 if output != "" :
133146 if not os .path .isdir (output ):
134- print ("Output directory {0} does not exist" .format (output ))
147+ print ("error: output directory {0} does not exist" .format (output ))
135148 sys .exit (- 2 )
136149 else :
137150 if not output .endswith ("/" ):
138151 output = output + "/"
139- elif mode == "mux" or mode == "shader" or mode == "multi" :
152+ elif mode in MODES_SUPPORTING_MULTI_INPUTS :
153+ output = args ['output' ] or "out.mkv"
154+ if os .path .isdir (output ) and not os .path .exists (output ):
155+ try :
156+ os .mkdir (output )
157+ except Exception as e :
158+ print (
159+ "error: failed to create output directory={0}:" .format (output ))
160+ print (e )
161+ sys .exit (- 2 )
162+ else :
140163 output = args ['output' ] or "out.mkv"
141- elif mode == "split" :
142- output = args ['output' ]
143164
165+ # Collect input file paths from the input argument(s)
166+ in_files = []
167+ if mode in MODES_SUPPORTING_MULTI_INPUTS :
168+ skip_inputs = args ['skip_input' ]
169+ if skip_inputs is None :
170+ skip_inputs = []
171+ elif type (skip_inputs ) is str :
172+ skip_inputs = [skip_inputs ]
173+
174+ for file in fn :
175+ if os .path .isdir (file ):
176+ for file_in_dir in glob .glob (
177+ os .path .join (file , "*.mkv" )
178+ ) + glob .glob (
179+ os .path .join (file , "*.mp4" )
180+ ):
181+ file_name = os .path .basename (file_in_dir )
182+ if file_name in skip_inputs :
183+ continue
184+ in_files .append (os .path .join (file_in_dir ))
185+ else :
186+ # Only here for consistency
187+ # Why would you specify a file input then add that file
188+ # to a list of files to ignore?
189+ if file in skip_inputs :
190+ continue
191+ in_files .append (os .path .join (file ))
192+ file_count = len (in_files )
193+ if file_count > 1 :
194+ if not os .path .isdir (output ):
195+ print (
196+ "error: output path must be a directory when there are more than one input files" )
197+ sys .exit (- 2 )
198+ elif file_count == 0 :
199+ print ("error: no valid input media files found" )
200+ sys .exit (- 2 )
201+
202+ # Validate "skip_menus" argument
203+ skip_menus = args ['skip_menus' ]
204+ if skip_menus is None :
205+ skip_menus = {}
206+
207+ # Perform action based on mode
144208if mode == "audio" :
145- extract_audio (fn , output )
209+ extract_audio (fn , output , skip_menus )
146210elif mode == "subs" :
147211 extract_subs (fn , output )
148212elif mode == "mux" :
149213 mux (fn , output )
150214elif mode == "shader" :
151- if type (fn ) is str :
152- fn = [fn ]
153- shader (fn , args ['width' ], args ['height' ], args ['shader_dir' ], args ['bit' ],
154- args ['audio_language' ], args ['softsubs' ], args ['softaudio' ],
155- args ['skip_menus' ] or {}, output )
215+ shader (in_files , args ['width' ], args ['height' ],
216+ args ['shader_dir' ], args ['bit' ], args ['audio_language' ],
217+ args ['softsubs' ], args ['softaudio' ], skip_menus , True , output )
156218elif mode == "multi" :
157- if type (fn ) is str :
158- fn = [fn ]
159- multi (fn , args ['width' ], args ['height' ], args ['shader_dir' ], args ['bit' ],
160- args ['skip_menus' ], args ['delete_failures' ], output )
219+ multi (in_files , args ['width' ], args ['height' ],
220+ args ['shader_dir' ], args ['bit' ], skip_menus ,
221+ args ['delete_failures' ], output )
222+ elif mode == "encode" :
223+ encode_to_hevc (in_files , output , skip_menus )
161224elif mode == "split" :
162225 length = get_video_length (fn )
163226 split_by_seconds (filename = fn , split_length = args ['split_length' ],
164227 video_length = length , split_dir = output )
165228else :
166- print ("Unknown option : {0}" .format (mode ))
229+ print ("Unknown mode : {0}" .format (mode ))
0 commit comments