def measure_frame_size( api: Api, renderer: AssRenderer, event: AssEvent ) -> T.Tuple[int, int]: if not any(style.name == event.style for style in renderer.style_list): return (0, 0) fake_event_list = AssEventList() fake_event_list.append(copy(event)) renderer.set_source( style_list=renderer.style_list, event_list=fake_event_list, meta=renderer.meta, video_resolution=renderer.video_resolution, ) layers = [ layer for layer in renderer.render_raw(time=event.start) if layer.type == 0 ] if not layers: return (0, 0) min_x = min(layer.dst_x for layer in layers) min_y = min(layer.dst_y for layer in layers) max_x = max(layer.dst_x + layer.w for layer in layers) max_y = max(layer.dst_y + layer.h for layer in layers) aspect_ratio = ( api.video.current_stream.aspect_ratio if api.video.current_stream else 1 ) return (int((max_x - min_x) * aspect_ratio), max_y - min_y)
def update_preview(self) -> None: selected_style = self._selected_style if not selected_style: self._preview_box.clear() return resolution = (self._preview_box.width(), self._preview_box.height()) if resolution[0] <= 0 or resolution[1] <= 0: self._preview_box.clear() return fake_style = copy(selected_style) fake_style.name = "Default" if ( self._api.video.current_stream and self._api.video.current_stream.is_ready ): fake_style.scale( resolution[1] / self._api.video.current_stream.height ) fake_style_list = AssStyleList() fake_style_list.append(fake_style) fake_event = AssEvent( start=0, end=1000, text=self.preview_text.replace("\n", "\\N"), style=fake_style.name, ) fake_event_list = AssEventList() fake_event_list.append(fake_event) fake_meta = AssMeta() image = PIL.Image.new(mode="RGBA", size=resolution) background_path = self._background_combobox.currentData() if background_path and background_path.exists(): background = PIL.Image.open(background_path) for y in range(0, resolution[1], background.height): for x in range(0, resolution[0], background.width): image.paste(background, (x, y)) self._renderer.set_source( fake_style_list, fake_event_list, fake_meta, resolution ) subs_image = self._renderer.render( time=0, aspect_ratio=( self._api.video.current_stream.aspect_ratio if self._api.video.current_stream else 1 ), ) image = PIL.Image.composite(subs_image, image, subs_image) image = PIL.ImageQt.ImageQt(image) image = QtGui.QImage(image) self._preview_box.setPixmap(QtGui.QPixmap.fromImage(image))
def test_check_double_words(text, violation_text): event_list = AssEventList() event_list.append(AssEvent(text=text)) results = list(check_double_words(event_list[0])) if violation_text is None: assert len(results) == 0 else: assert len(results) == 1 assert results[0].text == violation_text
def test_check_ass_tags(text, violation_text_re): event_list = AssEventList() event_list.append(AssEvent(text=text)) results = list(check_ass_tags(event_list[0])) if violation_text_re is None: assert len(results) == 0 else: assert len(results) == 1 assert re.match(violation_text_re, results[0].text)
def test_check_quotes( text: str, expected_violations: T.List[T.Tuple[str, LogLevel]]) -> None: event_list = AssEventList() event_list.append(AssEvent(text=text)) results = list(check_quotes(event_list[0])) assert len(results) == len(expected_violations) for expected_violation, result in zip(expected_violations, results): violation_text_re, log_level = expected_violation assert re.match(violation_text_re, result.text) assert result.log_level == log_level
def test_check_durations_too_short_gap_empty_lines() -> None: event_list = AssEventList() event_list.append(AssEvent(start=0, end=500, text="test")) event_list.append(AssEvent(start=550, end=550)) event_list.append(AssEvent(start=600, end=900, text="test")) results = list(check_durations(event_list[0])) assert len(results) == 1 assert results[0].text == "gap shorter than 250 ms (100 ms)"
def test_check_line_continuation(texts: T.List[str], violation_text: T.Optional[str]) -> None: event_list = AssEventList() for text in texts: event_list.append(AssEvent(text=text)) results = [] for event in event_list: results += list(check_line_continuation(event)) if violation_text is None: assert len(results) == 0 else: assert len(results) == 1 assert results[0].text == violation_text
def test_check_unnecessary_breaks(text, violation_text): api = MagicMock() api.video.current_stream.aspect_ratio = 1 api.subs.meta = {"PlayResX": 1280} with patch( "quality_check.check_unnecessary_breaks.measure_frame_size", return_value=(100, 0), ): event_list = AssEventList() event_list.append(AssEvent(text=text)) renderer = MagicMock() results = list(check_unnecessary_breaks(event_list[0], api, renderer)) if violation_text is None: assert len(results) == 0 else: assert len(results) == 1 assert results[0].text == violation_text
def test_check_durations_good_gap() -> None: event_list = AssEventList() event_list.append(AssEvent(start=0, end=500, text="test")) event_list.append(AssEvent(start=750, end=900, text="test")) assert len(list(check_durations(event_list[0]))) == 0
def test_violation_multiple_events() -> None: event_list = AssEventList() event_list.append(AssEvent(start=0, end=0)) event_list.append(AssEvent(start=0, end=0)) violation = Violation([event_list[0], event_list[1]], "test") assert repr(violation) == "#1+#2: test"
def test_violation_single_event() -> None: event_list = AssEventList() event_list.append(AssEvent(start=0, end=0)) violation = Violation(event_list[0], "test") assert repr(violation) == "#1: test"
def __init__(self) -> None: """Initialize self.""" self.styles = AssStyleList() self.events = AssEventList() self.meta = AssMeta()