def test_throw_exception_on_vtt2srt_exception(self, mock_communicate): try: Undertest.vtt2srt(self.__real_vtt_path, "output") except Exception as e: self.assertTrue(mock_communicate.called) self.assertTrue(isinstance(e, TerminalException)) else: self.fail("Should have thrown exception")
def test_remove_trailing_newlines(self): output_file_path = os.path.join(self.__resource_tmp, "stripped.txt") Undertest.remove_trailing_newlines(self.__with_newlines_path, output_file_path) with open(output_file_path, "r", encoding="utf8") as file: lines = file.readlines() self.assertEqual(3, len(lines)) self.assertEqual("\n", lines[0]) self.assertEqual("\n", lines[1]) self.assertEqual("Contains two leading newlines and three trailing newlines", lines[2])
def test_microdvd2srt(self): output_file_path = os.path.join(self.__resource_tmp, "converted.sub") Undertest.microdvd2srt(self.__real_mircodvd_path, output_file_path) self.assertTrue(os.path.isfile(output_file_path))
def test_srt2microdvd(self): output_file_path = os.path.join(self.__resource_tmp, "converted.sub") Undertest.srt2microdvd(self.__real_srt_path, output_file_path) self.assertTrue(filecmp.cmp(self.__real_mircodvd_path, output_file_path))
def main(): if sys.version_info.major != 3: print("Cannot find Python 3") sys.exit(20) try: import subaligner except ModuleNotFoundError: print("Subaligner is not installed") sys.exit(20) from subaligner._version import __version__ parser = argparse.ArgumentParser( description="Run single-stage alignment (v%s)" % __version__, formatter_class=argparse.RawTextHelpFormatter) required_args = parser.add_argument_group("required arguments") required_args.add_argument( "-v", "--video_path", type=str, default="", help="File path or URL to the video file", required=True, ) from subaligner.subtitle import Subtitle required_args.add_argument( "-s", "--subtitle_path", type=str, default="", help= "File path or URL to the subtitle file (Extensions of supported subtitles: {}) or selector for the embedded subtitle (e.g., embedded:page_num=888 or embedded:stream_index=0)" .format(", ".join(Subtitle.subtitle_extensions())), required=True, ) parser.add_argument( "-l", "--max_logloss", type=float, default=float("inf"), help="Max global log loss for alignment", ) parser.add_argument( "-tod", "--training_output_directory", type=str, default=os.path.abspath(os.path.dirname(subaligner.__file__)), help="Path to the output directory containing training results", ) parser.add_argument( "-o", "--output", type=str, default="", help="Path to the output subtitle file", ) parser.add_argument("-d", "--debug", action="store_true", help="Print out debugging information") parser.add_argument("-q", "--quiet", action="store_true", help="Switch off logging information") parser.add_argument("-ver", "--version", action="version", version=__version__) FLAGS, unparsed = parser.parse_known_args() if FLAGS.video_path == "": print("--video_path was not passed in") sys.exit(21) if FLAGS.subtitle_path == "": print("--subtitle_path was not passed in") sys.exit(21) if FLAGS.subtitle_path.lower().startswith("http") and FLAGS.output == "": print( "--output was not passed in for alignment on a remote subtitle file" ) sys.exit(21) if FLAGS.subtitle_path.lower().startswith( "teletext:") and FLAGS.output == "": print("--output was not passed in for alignment on embedded subtitles") sys.exit(21) local_video_path = FLAGS.video_path local_subtitle_path = FLAGS.subtitle_path from subaligner.logger import Logger Logger.VERBOSE = FLAGS.debug Logger.QUIET = FLAGS.quiet from subaligner.predictor import Predictor from subaligner.exception import UnsupportedFormatException from subaligner.exception import TerminalException from subaligner.utils import Utils try: if FLAGS.video_path.lower().startswith("http"): _, local_video_path = tempfile.mkstemp() _, video_file_extension = os.path.splitext( FLAGS.video_path.lower()) local_video_path = "{}{}".format(local_video_path, video_file_extension) Utils.download_file(FLAGS.video_path, local_video_path) if FLAGS.subtitle_path.lower().startswith("http"): _, local_subtitle_path = tempfile.mkstemp() _, subtitle_file_extension = os.path.splitext( FLAGS.subtitle_path.lower()) local_subtitle_path = "{}{}".format(local_subtitle_path, subtitle_file_extension) Utils.download_file(FLAGS.subtitle_path, local_subtitle_path) if FLAGS.subtitle_path.lower().startswith("embedded:"): _, local_subtitle_path = tempfile.mkstemp() _, subtitle_file_extension = os.path.splitext(FLAGS.output) local_subtitle_path = "{}{}".format(local_subtitle_path, subtitle_file_extension) params = FLAGS.subtitle_path.lower().split(":")[1].split(",") if params and "=" in params[0]: params = { param.split("=")[0]: param.split("=")[1] for param in params } if "page_num" in params: Utils.extract_teletext_as_subtitle(local_video_path, int(params["page_num"]), local_subtitle_path) elif "stream_index" in params: Utils.extract_matroska_subtitle( local_video_path, int(params["stream_index"]), local_subtitle_path) else: print("Embedded subtitle selector cannot be empty") sys.exit(21) predictor = Predictor() subs, audio_file_path, voice_probabilities, frame_rate = predictor.predict_single_pass( video_file_path=local_video_path, subtitle_file_path=local_subtitle_path, weights_dir=os.path.join(FLAGS.training_output_directory, "models/training/weights")) aligned_subtitle_path = "_aligned.".join( FLAGS.subtitle_path.rsplit(".", 1)).replace( ".stl", ".srt") if FLAGS.output == "" else FLAGS.output Subtitle.export_subtitle(local_subtitle_path, subs, aligned_subtitle_path, frame_rate) log_loss = predictor.get_log_loss(voice_probabilities, subs) if log_loss is None or log_loss > FLAGS.max_logloss: print("Alignment failed with a too high loss value: {}".format( log_loss)) _remove_tmp_files(FLAGS, local_video_path, local_subtitle_path) sys.exit(22) print("Aligned subtitle saved to: {}".format(aligned_subtitle_path)) except UnsupportedFormatException as e: print("{}\n{}".format( str(e), "".join(traceback.format_stack()) if FLAGS.debug else "")) _remove_tmp_files(FLAGS, local_video_path, local_subtitle_path) sys.exit(23) except TerminalException as e: print("{}\n{}".format( str(e), "".join(traceback.format_stack()) if FLAGS.debug else "")) _remove_tmp_files(FLAGS, local_video_path, local_subtitle_path) sys.exit(24) except Exception as e: print("{}\n{}".format( str(e), "".join(traceback.format_stack()) if FLAGS.debug else "")) _remove_tmp_files(FLAGS, local_video_path, local_subtitle_path) sys.exit(1) else: _remove_tmp_files(FLAGS, local_video_path, local_subtitle_path) sys.exit(0)
def test_extract_teletext_as_srt(self): output_file_path = os.path.join(self.__resource_tmp, "extracted.teletext.srt") Undertest.extract_teletext_as_subtitle(self.__ts_file_path, 888, output_file_path) self.assertTrue(os.path.isfile(output_file_path))
def test_ass2srt(self): output_file_path = os.path.join(self.__resource_tmp, "converted.srt") Undertest.ass2srt(self.__real_ass_path, output_file_path) self.assertTrue(os.path.isfile(output_file_path))
def test_srt2ttml(self, mock_read, mock_write): Undertest.srt2ttml(self.__mocked_srt_path) self.assertTrue(mock_read.called) self.assertTrue(mock_write.called)
def test_throw_exception_on_extracting_teletext_timeout(self, mock_communicate): output_file_path = os.path.join(self.__resource_tmp, "extracted.tmp.srt") self._assert_exception_on_subproces( lambda: Undertest.extract_teletext_as_subtitle(self.__ts_file_path, 888, output_file_path), mock_communicate)
def test_throw_exception_on_vtt2srt_exception(self, mock_communicate): self._assert_exception_on_subproces(lambda: Undertest.vtt2srt(self.__real_vtt_path, "output"), mock_communicate)
def test_throw_exception_on_srt2vtt_with_error_code(self, mock_communicate): self._assert_exception_on_subproces(lambda: Undertest.srt2vtt(self.__real_srt_path, "output"), mock_communicate)
def test_detect_encoding(self): self.assertEqual("ASCII", Undertest.detect_encoding(self.__real_srt_path)) self.assertEqual("UTF-8", Undertest.detect_encoding(self.__mkv_file_path))
def test_contains_embedded_subtitle(self): self.assertTrue(Undertest.contains_embedded_subtitles(self.__mkv_file_path)) self.assertFalse(Undertest.contains_embedded_subtitles(self.__mp4_file_path))
def test_download(self, mocked_copyfileobj, mocked_open, mocked_get): Undertest.download_file("remote_file_url", "local_file_path") mocked_get.assert_called_once_with("remote_file_url", verify=True, stream=True) mocked_open.assert_called_once_with("local_file_path", "wb") mocked_copyfileobj.assert_called_once_with(ANY, ANY)
def test_extract_matroska_subtitle(self): output_file_path = os.path.join(self.__resource_tmp, "extracted.matroska.srt") Undertest.extract_matroska_subtitle(self.__mkv_file_path, 0, output_file_path) self.assertTrue(os.path.isfile(output_file_path))
def test_srt2mpl2(self): output_file_path = os.path.join(self.__resource_tmp, "converted.mpl2.txt") Undertest.srt2mpl2(self.__real_srt_path, output_file_path) self.assertTrue(filecmp.cmp(self.__real_mpl2_path, output_file_path))
def test_tmp2srt(self): output_file_path = os.path.join(self.__resource_tmp, "converted.tmp.txt") Undertest.mpl22srt(self.__real_mpl2_path, output_file_path) self.assertTrue(os.path.isfile(output_file_path))
def test_throw_exception_on_extracting_matroska_subtitle_exception(self, mock_communicate): output_file_path = os.path.join(self.__resource_tmp, "extracted.tmp.srt") self._assert_exception_on_subproces( lambda: Undertest.extract_matroska_subtitle(self.__mkv_file_path, 0, output_file_path), mock_communicate)
def test_throw_exception_on_detecting_embedded_subtitles_exception(self, mock_communicate): self._assert_exception_on_subproces( lambda: self.assertTrue(Undertest.contains_embedded_subtitles(self.__mkv_file_path)), mock_communicate)
def test_vtt2srt(self): output_file_path = os.path.join(self.__resource_tmp, "converted.vtt.srt") Undertest.vtt2srt(self.__real_vtt_path, output_file_path) self.assertTrue(filecmp.cmp(self.__real_srt_path, output_file_path))
def test_ttml2srt(self, mock_read, mock_write): Undertest.ttml2srt(self.__mocked_ttml_path) self.assertTrue(mock_read.called) self.assertTrue(mock_write.called)
def main(): if sys.version_info.major != 3: print("Cannot find Python 3") sys.exit(20) try: import subaligner except ModuleNotFoundError: print("Subaligner is not installed") sys.exit(20) from subaligner._version import __version__ parser = argparse.ArgumentParser( description= "Convert a subtitle from input format to output format (v%s)" % __version__, formatter_class=argparse.RawTextHelpFormatter) required_args = parser.add_argument_group("required arguments") required_args.add_argument( "-i", "--input_subtitle_path", type=str, default="", help="File path or URL to the input subtitle file", required=True, ) required_args.add_argument( "-o", "--output_subtitle_path", type=str, default="", help="File path to the output subtitle file", required=True, ) parser.add_argument("-d", "--debug", action="store_true", help="Print out debugging information") parser.add_argument("-q", "--quiet", action="store_true", help="Switch off logging information") parser.add_argument("-ver", "--version", action="version", version=__version__) FLAGS, unparsed = parser.parse_known_args() if FLAGS.input_subtitle_path == "": print("--input_subtitle_path was not passed in") sys.exit(21) if FLAGS.output_subtitle_path == "": print("--output_subtitle_path was not passed in") sys.exit(21) local_subtitle_path = FLAGS.input_subtitle_path from subaligner.logger import Logger Logger.VERBOSE = FLAGS.debug Logger.QUIET = FLAGS.quiet from subaligner.subtitle import Subtitle from subaligner.exception import UnsupportedFormatException, TerminalException from subaligner.utils import Utils try: if FLAGS.input_subtitle_path.lower().startswith("http"): _, local_subtitle_path = tempfile.mkstemp() _, subtitle_file_extension = os.path.splitext( FLAGS.input_subtitle_path.lower()) local_subtitle_path = "{}{}".format(local_subtitle_path, subtitle_file_extension) Utils.download_file(FLAGS.input_subtitle_path, local_subtitle_path) subtitle = Subtitle.load(local_subtitle_path) Subtitle.save_subs_as_target_format(subtitle.subs, local_subtitle_path, FLAGS.output_subtitle_path) print("Subtitle converted and saved to: {}".format( FLAGS.output_subtitle_path)) except UnsupportedFormatException as e: print("{}\n{}".format( str(e), "".join(traceback.format_stack()) if FLAGS.debug else "")) _remove_tmp_files(FLAGS, local_subtitle_path) sys.exit(23) except TerminalException as e: print("{}\n{}".format( str(e), "".join(traceback.format_stack()) if FLAGS.debug else "")) _remove_tmp_files(FLAGS, local_subtitle_path) sys.exit(24) except Exception as e: print("{}\n{}".format( str(e), "".join(traceback.format_stack()) if FLAGS.debug else "")) _remove_tmp_files(FLAGS, local_subtitle_path) sys.exit(1) else: _remove_tmp_files(FLAGS, local_subtitle_path) sys.exit(0)
def test_srt2ssa(self): output_file_path = os.path.join(self.__resource_tmp, "converted.ssa") Undertest.srt2ssa(self.__real_srt_path, output_file_path) self.assertTrue(filecmp.cmp(self.__real_ssa_path, output_file_path))
def test_sami2srt(self, mock_read, mock_write): Undertest.sami2srt(self.__mocked_sami_path) self.assertTrue(mock_read.called) self.assertTrue(mock_write.called)