def __call__(self, region): try: start_ms, end_ms = region start = float(start_ms) / 1000.0 end = float(end_ms) / 1000.0 if start > self.include_before: start = start - self.include_before end += self.include_after if not self.is_keep or not self.output: temp = tempfile.NamedTemporaryFile(suffix=self.suffix, delete=False) command = self.cmd.format(start=start, dura=end - start, in_=self.source_path, out_=temp.name) prcs = subprocess.Popen(constants.cmd_conversion(command), stdout=subprocess.PIPE, stderr=subprocess.PIPE) prcs.communicate() return temp.name filename = self.output \ + "-{start:0>8.3f}-{end:0>8.3f}{suffix}".format( start=start, end=end, suffix=self.suffix) command = self.cmd.format(start=start, dura=end - start, in_=self.source_path, out_=filename) prcs = subprocess.Popen(constants.cmd_conversion(command), stdout=subprocess.PIPE, stderr=subprocess.PIPE) err = prcs.communicate()[1] if err: return None audio_file = open(filename, mode="rb") audio_data = audio_file.read() audio_file.close() if len(audio_data) <= 4: return None return filename except KeyboardInterrupt: return None except subprocess.CalledProcessError as ffmpeg_exec_error: raise exceptions.AutosubException( _("Error: ffmpeg can't split your file. " "Check your audio processing options.") ) from ffmpeg_exec_error
def __call__(self, region): try: start_ms, end_ms = region start = float(start_ms) / 1000.0 end = float(end_ms) / 1000.0 if start > self.include_before: start = start - self.include_before end += self.include_after if not self.is_keep or not self.output: temp = tempfile.NamedTemporaryFile(suffix=self.suffix, delete=False) command = self.cmd.format(start=start, dura=end - start, in_=self.source_path, out_=temp.name) subprocess.check_output( constants.cmd_conversion(command), stdin=open(os.devnull)) return temp.name filename = self.output \ + "-{start:0>8.3f}-{end:0>8.3f}{suffix}".format( start=start, end=end, suffix=self.suffix) command = self.cmd.format(start=start, dura=end - start, in_=self.source_path, out_=filename) subprocess.check_output( constants.cmd_conversion(command), stdin=open(os.devnull)) return filename except KeyboardInterrupt: return None except subprocess.CalledProcessError: raise exceptions.AutosubException( _("Error: ffmpeg can't split your file. " "Check your audio processing options.") )
def main(): # pylint: disable=too-many-branches, too-many-statements, too-many-locals """ Run autosub as a command-line program. """ is_pause = False # todo1: move into constants to support locale and dependency input option_parser = options.get_cmd_parser() if len(sys.argv) > 1: args = option_parser.parse_args() else: option_parser.print_help() new_argv = input(_("\nInput args(without \"autosub\"): ")) args = option_parser.parse_args(shlex.split(new_argv)) is_pause = True if args.https_proxy: os.environ['https_proxy'] = args.https_proxy if args.http_proxy: os.environ['http_proxy'] = args.http_proxy if args.proxy_username: os.environ['proxy_username'] = args.proxy_username if args.proxy_password: os.environ['proxy_password'] = args.proxy_password try: if args.speech_config: cmdline_utils.validate_config_args(args) if cmdline_utils.list_args(args): raise exceptions.AutosubException(_("\nAll works done.")) if not args.yes: input_m = input else: input_m = None styles_list = [] result = cmdline_utils.validate_io(args, styles_list) if result: if not constants.FFMPEG_CMD: raise exceptions.AutosubException( _("Error: Dependency ffmpeg" " not found on this machine.")) if not constants.FFPROBE_CMD: raise exceptions.AutosubException( _("Error: Dependency ffprobe" " not found on this machine.")) cmdline_utils.fix_args(args) if args.audio_process: args.audio_process = {k.lower() for k in args.audio_process} args.audio_process = \ args.audio_process & constants.DEFAULT_AUDIO_PRCS_MODE_SET if not args.audio_process: raise exceptions.AutosubException( _("Error: The args of \"-ap\"/\"--audio-process\" are wrong." "\nNo works done.")) if 'o' in args.audio_process: args.keep = True prcs_file = ffmpeg_utils.audio_pre_prcs( filename=args.input, is_keep=args.keep, cmds=args.audio_process_cmd, output_name=args.output, input_m=input_m) if not prcs_file: raise exceptions.AutosubException(_("No works done.")) args.input = prcs_file raise exceptions.AutosubException( _("Audio pre-processing complete.\nAll works done.")) if 's' in args.audio_process: args.keep = True if 'y' in args.audio_process: prcs_file = ffmpeg_utils.audio_pre_prcs( filename=args.input, is_keep=args.keep, cmds=args.audio_process_cmd, output_name=args.output, input_m=input_m) args.audio_split_cmd = \ args.audio_split_cmd.replace( "-vn -ac [channel] -ar [sample_rate] ", "") if not prcs_file: print( _("Audio pre-processing failed." "\nUse default method.")) else: args.input = prcs_file print(_("Audio pre-processing complete.")) else: if args.audio_split_cmd == constants.DEFAULT_AUDIO_SPLT: # if user doesn't modify the audio_split_cmd if args.api_suffix == ".ogg": # regard ogg as ogg_opus args.audio_split_cmd = \ args.audio_split_cmd.replace( "-vn", "-vn -c:a libopus") elif args.api_suffix == ".pcm": # raw pcm args.audio_split_cmd = \ args.audio_split_cmd.replace( "-vn", "-vn -c:a pcm_s16le -f s16le") args.audio_split_cmd = \ args.audio_split_cmd.replace( "[channel]", "{channel}".format(channel=args.api_audio_channel)) args.audio_split_cmd = \ args.audio_split_cmd.replace( "[sample_rate]", "{sample_rate}".format(sample_rate=args.api_sample_rate)) cmdline_utils.validate_aovp_args(args) fps = cmdline_utils.get_fps(args=args, input_m=input_m) cmdline_utils.audio_or_video_prcs(args, fps=fps, input_m=input_m, styles_list=styles_list) else: result = cmdline_utils.validate_sp_args(args) fps = cmdline_utils.get_fps(args=args, input_m=input_m) if result: args.output_files = args.output_files & \ constants.DEFAULT_SUB_MODE_SET if not args.output_files: raise exceptions.AutosubException( _("Error: No valid \"-of\"/\"--output-files\" arguments." )) cmdline_utils.sub_trans(args, input_m=input_m, fps=fps, styles_list=None) else: cmdline_utils.sub_conversion(args, input_m=input_m, fps=fps) raise exceptions.AutosubException(_("\nAll works done.")) except KeyboardInterrupt: print(_("\nKeyboardInterrupt. Works stopped.")) except pysubs2.exceptions.Pysubs2Error: print(_("\nError: pysubs2.exceptions. Check your file format.")) except exceptions.AutosubException as err_msg: print(err_msg) if is_pause: input(_("Press Enter to exit...")) return 0
def audio_or_video_prcs( # pylint: disable=too-many-branches, too-many-statements, too-many-locals, too-many-arguments args, input_m=input, fps=30.0, styles_list=None, no_audio_prcs=False): """ Give args and process an input audio or video file. """ if args.http_speech_api: gsv2_api_url = "http://" + constants.GOOGLE_SPEECH_V2_API_URL else: gsv2_api_url = "https://" + constants.GOOGLE_SPEECH_V2_API_URL if not args.output_files: raise exceptions.AutosubException( _("\nNo works done." " Check your \"-of\"/\"--output-files\" option.")) if args.ext_regions: # use external speech regions print(_("Use external speech regions.")) audio_wav_temp = tempfile.NamedTemporaryFile(suffix='.wav', delete=False) audio_wav = audio_wav_temp.name audio_wav_temp.close() command = args.audio_conversion_cmd.format(in_=args.input, channel=1, sample_rate=16000, out_=audio_wav) print(command) subprocess.check_output(constants.cmd_conversion(command), stdin=open(os.devnull)) regions = sub_utils.sub_to_speech_regions(audio_wav=audio_wav, sub_file=args.ext_regions) os.remove(audio_wav) else: # use auditok_gen_speech_regions mode = 0 if args.strict_min_length: mode = auditok.StreamTokenizer.STRICT_MIN_LENGTH if args.drop_trailing_silence: mode = mode | auditok.StreamTokenizer.DROP_TRAILING_SILENCE elif args.drop_trailing_silence: mode = auditok.StreamTokenizer.DROP_TRAILING_SILENCE audio_wav_temp = tempfile.NamedTemporaryFile(suffix='.wav', delete=False) audio_wav = audio_wav_temp.name audio_wav_temp.close() command = args.audio_conversion_cmd.format(in_=args.input, channel=1, sample_rate=48000, out_=audio_wav) print( _("\nConvert source audio to \"{name}\" " "and get audio length for regions detection.").format( name=audio_wav)) print(command) subprocess.check_output(constants.cmd_conversion(command), stdin=open(os.devnull)) if not ffmpeg_utils.ffprobe_check_file(audio_wav): raise exceptions.AutosubException( _("Error: Convert source audio to \"{name}\" failed.").format( name=audio_wav)) regions = core.auditok_gen_speech_regions( audio_wav=audio_wav, energy_threshold=args.energy_threshold, min_region_size=constants.MIN_REGION_SIZE, max_region_size=constants.MAX_REGION_SIZE, max_continuous_silence=constants.DEFAULT_CONTINUOUS_SILENCE, mode=mode) os.remove(audio_wav) print(_("\n\"{name}\" has been deleted.").format(name=audio_wav)) if not regions: raise exceptions.AutosubException( _("Error: Can't get speech regions.")) if args.speech_language or \ args.audio_process and 's' in args.audio_process: # process output first try: args.output_files.remove("regions") if args.styles and \ (args.format == 'ass' or args.format == 'ssa' or args.format == 'ass.json'): times_string = core.list_to_ass_str( text_list=regions, styles_list=styles_list, subtitles_file_format=args.format) else: times_string = core.list_to_sub_str( timed_text=regions, fps=fps, subtitles_file_format=args.format) # times to subtitles string times_name = "{base}.{nt}.{extension}".format( base=args.output, nt="times", extension=args.format) subtitles_file_path = core.str_to_file(str_=times_string, output=times_name, input_m=input_m) # subtitles string to file print( _("Times file created at \"{}\".").format(subtitles_file_path)) if not args.output_files: raise exceptions.AutosubException(_("\nAll works done.")) except KeyError: pass if not no_audio_prcs: audio_for_api_temp = tempfile.NamedTemporaryFile( suffix=args.api_suffix, delete=False) audio_for_api = audio_for_api_temp.name audio_for_api_temp.close() command = args.audio_conversion_cmd.format( in_=args.input, channel=args.api_audio_channel, sample_rate=args.api_sample_rate, out_=audio_for_api) print( _("\nConvert to \"{name}\" " "for API.").format(name=audio_for_api)) print(command) subprocess.check_output(constants.cmd_conversion(command), stdin=open(os.devnull)) if not ffmpeg_utils.ffprobe_check_file(audio_for_api): raise exceptions.AutosubException( _("Error: Convert source audio to \"{name}\" failed."). format(name=audio_for_api)) else: audio_for_api = args.input audio_fragments = core.bulk_audio_conversion( source_file=audio_for_api, output=args.output, regions=regions, split_cmd=args.audio_split_cmd, suffix=args.api_suffix, concurrency=args.audio_concurrency, is_keep=args.keep) if not audio_fragments or \ len(audio_fragments) != len(regions): if not args.keep: for audio_fragment in audio_fragments: os.remove(audio_fragment) raise exceptions.ConversionException( _("Error: Conversion failed.")) if not args.keep: os.remove(audio_for_api) print( _("\n\"{name}\" has been deleted.").format(name=audio_for_api)) if args.audio_process and 's' in args.audio_process: raise exceptions.AutosubException( _("Audio processing complete.\nAll works done.")) # speech to text text_list = core.audio_to_text(audio_fragments=audio_fragments, api_url=gsv2_api_url, regions=regions, api_key=args.gspeechv2, concurrency=args.speech_concurrency, src_language=args.speech_language, min_confidence=args.min_confidence, audio_rate=args.api_sample_rate, is_keep=args.keep) if not text_list or len(text_list) != len(regions): raise exceptions.SpeechToTextException( _("Error: Speech-to-text failed.\nAll works done.")) timed_text = get_timed_text(is_empty_dropped=args.drop_empty_regions, regions=regions, text_list=text_list) if args.dst_language: # process output first try: args.output_files.remove("src") if args.styles and \ (args.format == 'ass' or args.format == 'ssa' or args.format == 'ass.json'): src_string = core.list_to_ass_str( text_list=timed_text, styles_list=styles_list[:2], subtitles_file_format=args.format, ) else: src_string = core.list_to_sub_str( timed_text=timed_text, fps=fps, subtitles_file_format=args.format) # formatting timed_text to subtitles string src_name = "{base}.{nt}.{extension}".format( base=args.output, nt=args.speech_language, extension=args.format) subtitles_file_path = core.str_to_file(str_=src_string, output=src_name, input_m=input_m) # subtitles string to file print( _("Speech language subtitles " "file created at \"{}\".").format(subtitles_file_path)) if not args.output_files: raise exceptions.AutosubException(_("\nAll works done.")) except KeyError: pass # text translation if args.gtransv2: # use gtransv2 translated_text = core.list_to_gtv2( text_list=text_list, api_key=args.gtransv2, concurrency=args.trans_concurrency, src_language=args.src_language, dst_language=args.dst_language, lines_per_trans=args.lines_per_trans) else: # use googletrans translated_text = core.list_to_googletrans( text_list, src_language=args.src_language, dst_language=args.dst_language, sleep_seconds=args.sleep_seconds, user_agent=args.user_agent, service_urls=args.service_urls) if not translated_text or len(translated_text) != len(regions): raise exceptions.AutosubException( _("Error: Translation failed.")) timed_trans = get_timed_text( is_empty_dropped=args.drop_empty_regions, regions=regions, text_list=translated_text) try: args.output_files.remove("bilingual") if args.styles and \ (args.format == 'ass' or args.format == 'ssa' or args.format == 'ass.json'): bilingual_string = core.list_to_ass_str( text_list=[timed_text, timed_trans], styles_list=styles_list, subtitles_file_format=args.format, ) else: bilingual_string = core.list_to_sub_str( timed_text=timed_text + timed_trans, fps=fps, subtitles_file_format=args.format) # formatting timed_text to subtitles string bilingual_name = "{base}.{nt}.{extension}".format( base=args.output, nt=args.src_language + '&' + args.dst_language, extension=args.format) subtitles_file_path = core.str_to_file(str_=bilingual_string, output=bilingual_name, input_m=input_m) # subtitles string to file print( _("Bilingual subtitles file " "created at \"{}\".").format(subtitles_file_path)) if not args.output_files: raise exceptions.AutosubException(_("\nAll works done.")) except KeyError: pass try: args.output_files.remove("dst") # formatting timed_text to subtitles string if args.styles and \ (args.format == 'ass' or args.format == 'ssa' or args.format == 'ass.json'): if len(args.styles) == 4: dst_string = core.list_to_ass_str( text_list=timed_trans, styles_list=styles_list[2:4], subtitles_file_format=args.format, ) else: dst_string = core.list_to_ass_str( text_list=timed_trans, styles_list=styles_list, subtitles_file_format=args.format, ) else: dst_string = core.list_to_sub_str( timed_text=timed_trans, fps=fps, subtitles_file_format=args.format) dst_name = "{base}.{nt}.{extension}".format( base=args.output, nt=args.dst_language, extension=args.format) subtitles_file_path = core.str_to_file(str_=dst_string, output=dst_name, input_m=input_m) # subtitles string to file print( _("Destination language subtitles " "file created at \"{}\".").format(subtitles_file_path)) except KeyError: pass else: if len(args.output_files) > 1 or not ({"dst", "src"} & args.output_files): print( _("Override \"-of\"/\"--output-files\" due to your args too few." "\nOutput source subtitles file only.")) timed_text = get_timed_text( is_empty_dropped=args.drop_empty_regions, regions=regions, text_list=text_list) if args.styles and \ (args.format == 'ass' or args.format == 'ssa' or args.format == 'ass.json'): src_string = core.list_to_ass_str( text_list=timed_text, styles_list=styles_list, subtitles_file_format=args.format, ) else: src_string = core.list_to_sub_str( timed_text=timed_text, fps=fps, subtitles_file_format=args.format) # formatting timed_text to subtitles string src_name = "{base}.{nt}.{extension}".format( base=args.output, nt=args.speech_language, extension=args.format) subtitles_file_path = core.str_to_file(str_=src_string, output=src_name, input_m=input_m) # subtitles string to file print( _("Speech language subtitles " "file created at \"{}\".").format(subtitles_file_path)) else: print( _("Override \"-of\"/\"--output-files\" due to your args too few." "\nOutput regions subtitles file only.")) if args.styles and \ (args.format == 'ass' or args.format == 'ssa' or args.format == 'ass.json'): times_subtitles = core.list_to_ass_str( text_list=regions, styles_list=styles_list, subtitles_file_format=args.format) else: times_subtitles = core.list_to_sub_str( timed_text=regions, fps=fps, subtitles_file_format=args.format) # times to subtitles string times_name = "{base}.{nt}.{extension}".format(base=args.output, nt="times", extension=args.format) subtitles_file_path = core.str_to_file(str_=times_subtitles, output=times_name, input_m=input_m) # subtitles string to file print(_("Times file created at \"{}\".").format(subtitles_file_path))
def subs_trans( # pylint: disable=too-many-branches, too-many-statements, too-many-locals args, input_m=input, fps=30.0, styles_list=None): """ Give args and translate a subtitles file. """ if not args.output_files: raise exceptions.AutosubException( _("\nNo works done." " Check your \"-of\"/\"--output-files\" option.")) src_sub = pysubs2.SSAFile.load(args.input) text_list = [] if args.styles and \ (args.format == 'ass' or args.format == 'ssa' or args.format == 'ass.json'): src_sub.styles = \ {styles_list[i]: styles_list[i + 1] for i in range(0, len(styles_list), 2)} for event in src_sub.events: event.style = styles_list[0] text_list.append(event.text) else: styles_list = [ src_sub.events[0].style, ] for event in src_sub.events: text_list.append(event.text) # text translation if args.gtransv2: # use gtransv2 translated_text = core.list_to_gtv2( text_list=text_list, api_key=args.gtransv2, concurrency=args.trans_concurrency, src_language=args.src_language, dst_language=args.dst_language, lines_per_trans=args.lines_per_trans) else: # use googletrans translated_text = core.list_to_googletrans( text_list, src_language=args.src_language, dst_language=args.dst_language, sleep_seconds=args.sleep_seconds, user_agent=args.user_agent, service_urls=args.service_urls) if not translated_text or len(translated_text) != len(text_list): raise exceptions.AutosubException(_("Error: Translation failed.")) try: args.output_files.remove("bilingual") bilingual_sub = pysubs2.SSAFile() bilingual_sub.styles = src_sub.styles bilingual_sub.events = src_sub.events[:] if args.styles and \ len(styles_list) == 2 and \ (args.format == 'ass' or args.format == 'ssa' or args.format == 'ass.json'): sub_utils.pysubs2_ssa_event_add(src_ssafile=bilingual_sub, dst_ssafile=bilingual_sub, text_list=translated_text, style_name=styles_list[2]) else: sub_utils.pysubs2_ssa_event_add(src_ssafile=bilingual_sub, dst_ssafile=bilingual_sub, text_list=translated_text, style_name=styles_list[0]) if args.format != 'ass.json': bilingual_string = bilingual_sub.to_string(format_=args.format, fps=fps) else: bilingual_string = bilingual_sub.to_string(format_='json') if args.format == 'mpl2': extension = 'mpl2.txt' else: extension = args.format bilingual_name = "{base}.{nt}.{extension}".format( base=args.output, nt=args.src_language + '&' + args.dst_language, extension=extension) subtitles_file_path = core.str_to_file(str_=bilingual_string, output=bilingual_name, input_m=input_m) # subtitles string to file print( _("Bilingual subtitles file " "created at \"{}\".").format(subtitles_file_path)) if not args.output_files: raise exceptions.AutosubException(_("\nAll works done.")) except KeyError: pass try: args.output_files.remove("dst") dst_sub = pysubs2.SSAFile() dst_sub.styles = src_sub.styles if len(styles_list) == 2: sub_utils.pysubs2_ssa_event_add(src_ssafile=src_sub, dst_ssafile=dst_sub, text_list=translated_text, style_name=styles_list[2]) else: sub_utils.pysubs2_ssa_event_add(src_ssafile=src_sub, dst_ssafile=dst_sub, text_list=translated_text, style_name=styles_list[0]) if args.format != 'ass.json': dst_string = dst_sub.to_string(format_=args.format, fps=fps) else: dst_string = dst_sub.to_string(format_='json') if args.format == 'mpl2': extension = 'mpl2.txt' else: extension = args.format dst_name = "{base}.{nt}.{extension}".format(base=args.output, nt=args.dst_language, extension=extension) subtitles_file_path = core.str_to_file(str_=dst_string, output=dst_name, input_m=input_m) # subtitles string to file print( _("Destination language subtitles " "file created at \"{}\".").format(subtitles_file_path)) except KeyError: pass
def validate_sp_args(args): # pylint: disable=too-many-branches,too-many-return-statements, too-many-statements """ Check that the commandline arguments passed to autosub are valid for subtitles processing. """ if args.src_language: if args.dst_language is None: raise exceptions.AutosubException( _("Error: Destination language not provided.")) is_src_matched = False is_dst_matched = False for key in googletrans.constants.LANGUAGES: if args.src_language.lower() == key.lower(): args.src_language = key is_src_matched = True if args.dst_language.lower() == key.lower(): args.dst_language = key is_dst_matched = True if not is_src_matched: if not args.gtransv2: if args.best_match and 'src' in args.best_match: print( _("Warning: Source language \"{src}\" not supported. " "Run with \"-lsc\"/\"--list-translation-codes\" " "to see all supported languages.").format( src=args.src_language)) best_result = lang_code_utils.match_print( dsr_lang=args.src_language, match_list=list( googletrans.constants.LANGUAGES.keys()), min_score=args.min_score) if best_result: print( _("Use \"{lang_code}\" instead.").format( lang_code=best_result[0])) args.src_language = best_result[0] else: raise exceptions.AutosubException( _("Match failed. Still using \"{lang_code}\". " "Program stopped.").format( lang_code=args.src_language)) else: raise exceptions.AutosubException( _("Error: Source language \"{src}\" not supported. " "Run with \"-lsc\"/\"--list-translation-codes\" " "to see all supported languages. " "Or use \"-bm\"/\"--best-match\" to get a best match." ).format(src=args.src_language)) if not is_dst_matched: if not args.gtransv2: if args.best_match and 'd' in args.best_match: print( _("Warning: Destination language \"{dst}\" not supported. " "Run with \"-lsc\"/\"--list-translation-codes\" " "to see all supported languages.").format( dst=args.dst_language)) best_result = lang_code_utils.match_print( dsr_lang=args.dst_language, match_list=list( googletrans.constants.LANGUAGES.keys()), min_score=args.min_score) if best_result: print( _("Use \"{lang_code}\" instead.").format( lang_code=best_result[0])) args.dst_language = best_result[0] else: raise exceptions.AutosubException( _("Match failed. Still using \"{lang_code}\". " "Program stopped.").format( lang_code=args.dst_language)) else: raise exceptions.AutosubException( _("Error: Destination language \"{dst}\" not supported. " "Run with \"-lsc\"/\"--list-translation-codes\" " "to see all supported languages. " "Or use \"-bm\"/\"--best-match\" to get a best match." ).format(dst=args.dst_language)) if args.dst_language == args.src_language: raise exceptions.AutosubException( _("Error: Source language is the same as the Destination language." )) else: raise exceptions.AutosubException( _("Error: Source language not provided.")) if args.styles == ' ': # when args.styles is used but without option # its value is ' ' if not args.ext_regions: raise exceptions.AutosubException( _("Error: External speech regions file not provided.")) else: args.styles = args.ext_regions
def validate_aovp_args(args): # pylint: disable=too-many-branches, too-many-return-statements, too-many-statements """ Check that the commandline arguments passed to autosub are valid for audio or video processing. """ if args.sleep_seconds < 0 or args.lines_per_trans < 0: raise exceptions.AutosubException( _("Error: \"-slp\"/\"--sleep-seconds\" arg is illegal.")) if args.speech_language: # pylint: disable=too-many-nested-blocks if not args.gspeechv2: args.speech_language = args.speech_language.lower() if args.speech_language \ not in constants.SPEECH_TO_TEXT_LANGUAGE_CODES: print( _("Warning: Speech language \"{src}\" not recommended. " "Run with \"-lsc\"/\"--list-speech-codes\" " "to see all supported languages.").format( src=args.speech_language)) if args.best_match and 's' in args.best_match: best_result = lang_code_utils.match_print( dsr_lang=args.speech_language, match_list=list( constants.SPEECH_TO_TEXT_LANGUAGE_CODES.keys()), min_score=args.min_score) if best_result: print( _("Use langcodes-py2 to standardize the result.")) args.speech_language = langcodes.standardize_tag( best_result[0]) print( _("Use \"{lang_code}\" instead.").format( lang_code=args.speech_language)) else: print( _("Match failed. Still using \"{lang_code}\"."). format(lang_code=args.speech_language)) if args.min_confidence < 0.0 or args.min_confidence > 1.0: raise exceptions.AutosubException( _("Error: The arg of \"-mnc\"/\"--min-confidence\" isn't legal." )) if args.dst_language is None: print( _("Destination language not provided. " "Only performing speech recognition.")) else: if not args.src_language: print( _("Source language not provided. " "Use Speech language instead.")) args.src_language = args.speech_language if not args.best_match: args.best_match = {'src'} elif 'src' not in args.best_match: args.best_match.add('src') is_src_matched = False is_dst_matched = False for key in googletrans.constants.LANGUAGES: if args.src_language.lower() == key.lower(): args.src_language = key is_src_matched = True if args.dst_language.lower() == key.lower(): args.dst_language = key is_dst_matched = True if not is_src_matched: if not args.gtransv2: if args.best_match and 'src' in args.best_match: print( _("Warning: Source language \"{src}\" not supported. " "Run with \"-lsc\"/\"--list-translation-codes\" " "to see all supported languages.").format( src=args.src_language)) best_result = lang_code_utils.match_print( dsr_lang=args.src_language, match_list=list( googletrans.constants.LANGUAGES.keys()), min_score=args.min_score) if best_result: print( _("Use \"{lang_code}\" instead.").format( lang_code=best_result[0])) args.src_language = best_result[0] else: raise exceptions.AutosubException( _("Match failed. Still using \"{lang_code}\". " "Program stopped.").format( lang_code=args.src_language)) else: raise exceptions.AutosubException( _("Error: Source language \"{src}\" not supported. " "Run with \"-lsc\"/\"--list-translation-codes\" " "to see all supported languages. " "Or use \"-bm\"/\"--best-match\" to get a best match." ).format(src=args.src_language)) if not is_dst_matched: if not args.gtransv2: if args.best_match and 'd' in args.best_match: print( _("Warning: Destination language \"{dst}\" not supported. " "Run with \"-lsc\"/\"--list-translation-codes\" " "to see all supported languages.").format( dst=args.dst_language)) best_result = lang_code_utils.match_print( dsr_lang=args.dst_language, match_list=list( googletrans.constants.LANGUAGES.keys()), min_score=args.min_score) if best_result: print( _("Use \"{lang_code}\" instead.").format( lang_code=best_result[0])) args.dst_language = best_result[0] else: raise exceptions.AutosubException( _("Match failed. Still using \"{lang_code}\". " "Program stopped.").format( lang_code=args.dst_language)) else: raise exceptions.AutosubException( _("Error: Destination language \"{dst}\" not supported. " "Run with \"-lsc\"/\"--list-translation-codes\" " "to see all supported languages. " "Or use \"-bm\"/\"--best-match\" to get a best match." ).format(dst=args.dst_language)) if args.dst_language == args.speech_language \ or args.src_language == args.dst_language: print( _("Speech language is the same as the Destination language. " "Only performing speech recognition.")) args.dst_language = None args.src_language = None else: if args.ext_regions: if not args.keep: raise exceptions.AutosubException( _("You've already input times. " "No works done.")) else: print( _("Speech language not provided. " "Only performing speech regions detection.")) if args.styles == ' ': # when args.styles is used but without option # its value is ' ' if not args.ext_regions: raise exceptions.AutosubException( _("Error: External speech regions file not provided.")) else: args.styles = args.ext_regions
def validate_io( # pylint: disable=too-many-branches, too-many-statements args, styles_list): """ Give args and choose workflow depends on the io options. """ if not args.input or not os.path.isfile(args.input): raise exceptions.AutosubException( _("Error: arg of \"-i\"/\"--input\": \"{path}\" isn't valid. " "You need to give a valid path.").format(path=args.input)) if args.styles: # pylint: disable=too-many-nested-blocks if not os.path.isfile(args.styles): raise exceptions.AutosubException( _("Error: arg of \"-sty\"/\"--styles\": \"{path}\" isn't valid. " "You need to give a valid path.").format(path=args.styles)) if args.styles_name: if len(args.styles_name) > 2: raise exceptions.AutosubException( _("Error: Too many \"-sn\"/\"--styles-name\" arguments.")) else: style_obj = pysubs2.SSAFile.load(args.styles) ass_styles = style_obj.styles.get(args.styles_name[0]) if ass_styles: styles_dict = {args.styles_name[0]: ass_styles} if len(args.styles_name) == 2: ass_styles = style_obj.styles.get(args.styles_name[1]) if ass_styles: styles_dict[args.styles_name[1]] = ass_styles else: raise exceptions.AutosubException( _("Error: \"-sn\"/\"--styles-name\" " "arguments aren't in \"{path}\".").format( path=args.styles)) for item in styles_dict.items(): styles_list.append(item[0]) styles_list.append(item[1]) else: raise exceptions.AutosubException( _("Error: \"-sn\"/\"--styles-name\" " "arguments aren't in \"{path}\".").format( path=args.styles)) if args.ext_regions and not os.path.isfile(args.ext_regions): raise exceptions.AutosubException( _("Error: arg of \"-er\"/\"--ext-regions\": \"{path}\" isn't valid. " "You need to give a valid path.").format(path=args.ext_regions)) input_name = os.path.splitext(args.input) input_ext = input_name[-1] input_fmt = input_ext.strip('.') input_path = input_name[0] is_ass_input = input_fmt in constants.INPUT_FORMAT if not args.output: args.output = input_path # get output name from input path if not args.format: # get format from input if is_ass_input: args.format = input_fmt print( _("No output format specified. " "Use input format \"{fmt}\" " "for output.").format(fmt=input_fmt)) else: # get format from default args.format = constants.DEFAULT_SUBTITLES_FORMAT elif os.path.isdir(args.output): args.output = os.path.join( args.output, os.path.basename(args.input).rstrip(input_ext)) # output = path + basename of input without extension print( _("Your output is a directory not a file path. " "Now file path set to \"{new}\".").format(new=args.output)) if not args.format: # get format from input if is_ass_input: args.format = input_fmt print( _("No output format specified. " "Use input format \"{fmt}\" " "for output.").format(fmt=input_fmt)) else: # get format from default args.format = constants.DEFAULT_SUBTITLES_FORMAT else: if not args.format: # get format from output args.format = input_ext.strip('.') # format = output name extension without dot args.output = input_path # output = output name without extension if args.format not in constants.OUTPUT_FORMAT: raise exceptions.AutosubException( _("Error: Output subtitles format \"{fmt}\" not supported. " "Run with \"-lf\"/\"--list-formats\" to see all supported formats.\n" "Or use ffmpeg or SubtitleEdit to convert the formats.").format( fmt=args.format)) args.output_files = set(args.output_files) if "all" in args.output_files: args.output_files = constants.DEFAULT_MODE_SET else: if not is_ass_input: args.output_files = args.output_files & \ constants.DEFAULT_MODE_SET if not args.output_files: raise exceptions.AutosubException( _("Error: No valid \"-of\"/\"--output-files\" arguments.")) else: args.output_files = args.output_files & \ constants.DEFAULT_SUB_MODE_SET if not args.output_files: raise exceptions.AutosubException( _("Error: No valid \"-of\"/\"--output-files\" arguments.")) if args.best_match: args.best_match = {k.lower() for k in args.best_match} if 'all' in args.best_match: args.best_match = constants.DEFAULT_LANG_MODE_SET else: args.best_match = \ args.best_match & constants.DEFAULT_LANG_MODE_SET if is_ass_input: print(_("Input is a subtitles file.")) return 1 return 0
def main(): # pylint: disable=too-many-branches, too-many-statements, too-many-locals """ Run autosub as a command-line program. """ args = options.get_cmd_args() if args.https_proxy: os.environ['https_proxy'] = args.https_proxy if args.http_proxy: os.environ['http_proxy'] = args.http_proxy if args.proxy_username: os.environ['proxy_username'] = args.proxy_username if args.proxy_password: os.environ['proxy_password'] = args.proxy_password try: if cmdline_utils.list_args(args): raise exceptions.AutosubException(_("\nAll works done.")) if not args.yes: try: input_m = raw_input except NameError: input_m = input else: input_m = None styles_list = [] validate_result = cmdline_utils.validate_io(args, styles_list) if validate_result == 0: if not constants.FFMPEG_CMD: raise exceptions.AutosubException( _("Error: Dependency ffmpeg" " not found on this machine.")) if not constants.FFPROBE_CMD: raise exceptions.AutosubException( _("Error: Dependency ffprobe" " not found on this machine.")) cmdline_utils.fix_args(args) if args.audio_process: args.audio_process = {k.lower() for k in args.audio_process} args.audio_process = \ args.audio_process & constants.DEFAULT_AUDIO_PRCS_MODE_SET if not args.audio_process: raise exceptions.AutosubException( _("Error: The args of \"-ap\"/\"--audio-process\" are wrong." "\nNo works done.")) if 'o' in args.audio_process: args.keep = True prcs_file = ffmpeg_utils.audio_pre_prcs( filename=args.input, is_keep=args.keep, cmds=args.audio_process_cmd, output_name=args.output, input_m=input_m) if not prcs_file: raise exceptions.AutosubException(_("No works done.")) args.input = prcs_file raise exceptions.AutosubException( _("Audio pre-processing complete.\nAll works done.")) if 's' in args.audio_process: args.keep = True if 'y' in args.audio_process: prcs_file = ffmpeg_utils.audio_pre_prcs( filename=args.input, is_keep=args.keep, cmds=args.audio_process_cmd, output_name=args.output, input_m=input_m) args.audio_split_cmd = \ args.audio_split_cmd.replace( "-vn -ac [channel] -ar [sample_rate] ", "") if not prcs_file: print( _("Audio pre-processing failed." "\nUse default method.")) else: args.input = prcs_file print(_("Audio pre-processing complete.")) else: args.audio_split_cmd = \ args.audio_split_cmd.replace( "[channel]", "{channel}".format(channel=args.api_audio_channel)) args.audio_split_cmd = \ args.audio_split_cmd.replace( "[sample_rate]", "{sample_rate}".format(sample_rate=args.api_sample_rate)) if args.api_suffix == ".ogg": # regard ogg as ogg_opus args.audio_split_cmd = \ args.audio_split_cmd.replace( "-vn", "-vn -c:a libopus") cmdline_utils.validate_aovp_args(args) fps = cmdline_utils.get_fps(args=args, input_m=input_m) cmdline_utils.audio_or_video_prcs(args, fps=fps, input_m=input_m, styles_list=styles_list) elif validate_result == 1: cmdline_utils.validate_sp_args(args) fps = cmdline_utils.get_fps(args=args, input_m=input_m) cmdline_utils.subs_trans(args, input_m=input_m, fps=fps, styles_list=None) except KeyboardInterrupt: print(_("\nKeyboardInterrupt. Works stopped.")) return 1 except pysubs2.exceptions.Pysubs2Error: print(_("\nError: pysubs2.exceptions. Check your file format.")) return 1 except exceptions.AutosubException as err_msg: print(err_msg) return 0 print(_("\nAll works done.")) return 0
def main(): # pylint: disable=too-many-branches, too-many-statements, too-many-locals """ Run autosub as a command-line program. """ args = options.get_cmd_args() if args.https_proxy: os.environ['https_proxy'] = args.https_proxy if args.http_proxy: os.environ['http_proxy'] = args.http_proxy if args.proxy_username: os.environ['proxy_username'] = args.proxy_username if args.proxy_password: os.environ['proxy_password'] = args.proxy_password try: if cmdline_utils.list_args(args): raise exceptions.AutosubException(_("\nAll works done.")) if not args.yes: try: input_m = raw_input except NameError: input_m = input else: input_m = None styles_list = [] validate_result = cmdline_utils.validate_io(args, styles_list) if validate_result == 0: ffmpeg_cmd = ffmpeg_utils.get_cmd("ffmpeg") if not ffmpeg_cmd: raise exceptions.AutosubException( _("Error: Dependency ffmpeg" " not found on this machine.")) ffmpeg_cmd = ffmpeg_cmd + ' ' if args.audio_process: args.audio_process = {k.lower() for k in args.audio_process} args.audio_process = \ args.audio_process & constants.DEFAULT_AUDIO_PRCS_MODE_SET if not args.audio_process: raise exceptions.AutosubException( _("Error: The args of \"-ap\"/\"--audio-process\" are wrong." "\nNo works done.")) if 'o' in args.audio_process: args.keep = True prcs_file = ffmpeg_utils.audio_pre_prcs( filename=args.input, is_keep=args.keep, cmds=args.audio_process_cmd, output_name=args.output, input_m=input_m, ffmpeg_cmd=ffmpeg_cmd) if not prcs_file: raise exceptions.AutosubException(_("No works done.")) else: args.input = prcs_file raise exceptions.AutosubException( _("Audio pre-processing complete.\nAll works done." )) if 's' in args.audio_process: args.keep = True if 'y' in args.audio_process: prcs_file = ffmpeg_utils.audio_pre_prcs( filename=args.input, is_keep=args.keep, cmds=args.audio_process_cmd, output_name=args.output, input_m=input_m, ffmpeg_cmd=ffmpeg_cmd) if not prcs_file: no_audio_prcs = False else: args.input = prcs_file print(_("Audio pre-processing complete.")) no_audio_prcs = True elif 'n' in args.audio_process: print( _("No extra check/conversion " "before the speech-to-text procedure.")) no_audio_prcs = True else: no_audio_prcs = False else: no_audio_prcs = False cmdline_utils.validate_aovp_args(args) cmdline_utils.fix_args(args, ffmpeg_cmd=ffmpeg_cmd) fps = cmdline_utils.get_fps(args=args, input_m=input_m) cmdline_utils.audio_or_video_prcs(args, fps=fps, input_m=input_m, styles_list=styles_list, no_audio_prcs=no_audio_prcs) elif validate_result == 1: cmdline_utils.validate_sp_args(args) fps = cmdline_utils.get_fps(args=args, input_m=input_m) cmdline_utils.subs_trans(args, input_m=input_m, fps=fps, styles_list=None) except KeyboardInterrupt: print(_("\nKeyboardInterrupt. Works stopped.")) return 1 except pysubs2.exceptions.Pysubs2Error: print(_("\nError: pysubs2.exceptions. Check your file format.")) return 1 except exceptions.AutosubException as err_msg: print(err_msg) return 0 print(_("\nAll works done.")) return 0