diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 890982a..d20df1a 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -32,6 +32,7 @@ jobs: - uses: actions/setup-python@v5 with: python-version: '3.10' + cache: 'pip' - uses: actions/setup-java@v4 with: @@ -41,13 +42,30 @@ jobs: - name: Install hunspell run: sudo apt-get install -y hunspell libhunspell-dev hunspell-en-us + - name: Lint with Ruff + run: | + pip install ruff + ruff check --output-format=github . + continue-on-error: true + - name: test run: | pip install -r requirements.txt pip install -r dev_requirements.txt python3 -c "import language_tool_python; tool = language_tool_python.LanguageTool('en')" cd dvrprocess - pytest --cov . --cov-branch --cov-report term-missing + pytest . --junitxml=../junit/test-results.xml --cov --cov-branch --cov-report=xml:../coverage.xml --cov-report=html:../htmlcov --cov-report=term-missing + + - name: Upload pytest test results + uses: actions/upload-artifact@v4 + with: + name: pytest-results + path: | + junit/test-results.xml + coverage.xml + htmlcov + # Use always() to always run this step to publish test results when there are test failures + if: ${{ always() }} build-and-push-image: runs-on: ubuntu-22.04 diff --git a/.gitignore b/.gitignore index fc1f72a..1b9edc0 100644 --- a/.gitignore +++ b/.gitignore @@ -39,13 +39,14 @@ pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ +junit/ .tox/ .nox/ .coverage .coverage.* .cache -nosetests.xml -coverage.xml +nosetests.*xml +coverage*.xml *.cover *.py,cover .hypothesis/ diff --git a/Dockerfile-test b/Dockerfile-test index 79d51f5..ae1a501 100644 --- a/Dockerfile-test +++ b/Dockerfile-test @@ -1,4 +1,4 @@ -FROM ubuntu:22.04 +FROM ubuntu:23.10 ENV DEBIAN_FRONTEND=noninteractive diff --git a/dev_requirements.txt b/dev_requirements.txt index 4220a11..f503606 100644 --- a/dev_requirements.txt +++ b/dev_requirements.txt @@ -1,2 +1,2 @@ -pytest==7.4.2 -pytest-cov==4.1.0 +pytest==8.1.1 +pytest-cov==5.0.0 diff --git a/dvrprocess/comchap-apply.py b/dvrprocess/comchap-apply.py index c8906e5..aa24d05 100755 --- a/dvrprocess/comchap-apply.py +++ b/dvrprocess/comchap-apply.py @@ -129,7 +129,7 @@ def comchap_apply(media_paths, dry_run=False, comskip_ini=None, workdir=None, fo return_code = result[1].get() except CalledProcessError as e: return_code = e.returncode - except: + except Exception: pool.terminate() return 255 @@ -167,7 +167,7 @@ def comchap_apply(media_paths, dry_run=False, comskip_ini=None, workdir=None, fo return 0 if check_compute and common.should_stop_processing(): - logger.info(f"INFO: not enough compute available") + logger.info("INFO: not enough compute available") return 0 bytes_progress.stop() diff --git a/dvrprocess/comchap.py b/dvrprocess/comchap.py index 11e97a8..09ac792 100755 --- a/dvrprocess/comchap.py +++ b/dvrprocess/comchap.py @@ -458,7 +458,7 @@ def do_comchap(infile, outfile, edlfile=None, delete_edl=True, delete_meta=True, with open(metafile, "w") as metafd: metafd.write(";FFMETADATA1\n") with open(mkvchapterfile, "w") as mkvchapterfd: - mkvchapterfd.write(f""" + mkvchapterfd.write(""" \n""") @@ -485,7 +485,7 @@ def do_comchap(infile, outfile, edlfile=None, delete_edl=True, delete_meta=True, write_chapter_metadata(metafd, start, duration, f"Chapter {chapter_num}") write_chapter_atom(mkvchapterfd, start, duration, f"Chapter {chapter_num}") - mkvchapterfd.write(f"""\n""") + mkvchapterfd.write("""\n""") # need this outside of metafd and mkvchapterfd blocks to ensure it's flushed and closed if hascommercials: diff --git a/dvrprocess/comcut.py b/dvrprocess/comcut.py index e91fe08..cbfed0d 100755 --- a/dvrprocess/comcut.py +++ b/dvrprocess/comcut.py @@ -126,7 +126,7 @@ def comcut(infile, outfile, delete_edl=True, force_clear_edl=False, delete_meta= input_duration = float(input_info[constants.K_FORMAT]['duration']) if len(edl_events) > 0: if edl_events[-1].end > input_duration + 3: - logger.fatal(f"edl cuts past end of file") + logger.fatal("edl cuts past end of file") return 255 keyframes = common.load_keyframes_by_seconds(infile) @@ -468,7 +468,7 @@ def comcut(infile, outfile, delete_edl=True, force_clear_edl=False, delete_meta= output_mapping = f"[v{output_stream_idx}]" video_filter_str += output_mapping - ffmpeg_command.extend([f"-filter_complex", video_filter_str]) + ffmpeg_command.extend(["-filter_complex", video_filter_str]) ffmpeg_command.extend(["-map", output_mapping]) ffmpeg_command.extend(encoding_options) @@ -539,8 +539,8 @@ def comcut(infile, outfile, delete_edl=True, force_clear_edl=False, delete_meta= # verify video is valid try: common.find_input_info(temp_outfile or outfile) - except: - logger.error(f"Cut file is not readable by ffmpeg, skipping") + except Exception: + logger.error("Cut file is not readable by ffmpeg, skipping") os.remove(temp_outfile or outfile) return 255 diff --git a/dvrprocess/common/__init__.py b/dvrprocess/common/__init__.py index 2cb50cd..190fe26 100644 --- a/dvrprocess/common/__init__.py +++ b/dvrprocess/common/__init__.py @@ -22,7 +22,7 @@ from psutil import AccessDenied, NoSuchProcess from . import hwaccel, tools, config, constants, progress, procprofile -from .proc_invoker import StreamCapture +from .proc_invoker import StreamCapture, pre_flight_check from .terminalui import terminalui_wrapper _allocate_lock = _thread.allocate_lock @@ -804,7 +804,7 @@ def map_opus_audio_stream(arguments: list[str], audio_info: dict, audio_stream_i if i > 0: mute_filter_complex += '+' mute_filter_complex += f"c{in_ch_idx[0]}" - mute_filter_complex += f'[afiltered]' + mute_filter_complex += '[afiltered]' arguments.extend(["-filter_complex", mute_filter_complex, "-map", "[afiltered]"]) else: arguments.extend(["-map", f"{audio_stream_idx}:{audio_info[constants.K_STREAM_INDEX]}"]) @@ -888,8 +888,8 @@ def filepath_is_mkv(filepath): return filename.endswith(".mkv") and not filename.startswith('.') -def filter_for_mkv(l): - return filter(lambda f: filepath_is_mkv(f), l) +def filter_for_mkv(file_list): + return filter(lambda f: filepath_is_mkv(f), file_list) def split_every(n, iterable): @@ -994,7 +994,7 @@ def setup_logging(level=logging.INFO): def setup_cli(level=logging.INFO, start_gauges=True): - proc_invoker.pre_flight_check() + pre_flight_check() setup_logging(level) setup_debugging() if start_gauges: diff --git a/dvrprocess/common/edl_util.py b/dvrprocess/common/edl_util.py index ee6ff3d..962d012 100644 --- a/dvrprocess/common/edl_util.py +++ b/dvrprocess/common/edl_util.py @@ -1,5 +1,5 @@ import logging -from copy import copy, deepcopy +from copy import copy from enum import Enum from typing import Union diff --git a/dvrprocess/common/hwaccel.py b/dvrprocess/common/hwaccel.py index 64b77c6..d99892c 100644 --- a/dvrprocess/common/hwaccel.py +++ b/dvrprocess/common/hwaccel.py @@ -364,7 +364,7 @@ def _nvenc_encoding(output_stream: str, codec: str, output_type: str, tune: str, options = [f"-c:{output_stream}"] if codec in ['h265']: - options.extend([f"hevc_nvenc"]) + options.extend(["hevc_nvenc"]) else: options.extend([f"{codec}_nvenc"]) diff --git a/dvrprocess/common/proc_invoker.py b/dvrprocess/common/proc_invoker.py index 3a63d06..8896100 100644 --- a/dvrprocess/common/proc_invoker.py +++ b/dvrprocess/common/proc_invoker.py @@ -21,13 +21,13 @@ def __init__(self, command_basename: str, version=None): _all_invokers.append(self) def run(self, arguments: list[str], **kwargs) -> int: - raise NotImplemented() + raise NotImplementedError() def check_output(self, arguments: list[str], **kwargs) -> str: - raise NotImplemented() + raise NotImplementedError() def Popen(self, arguments: list[str], **kwargs) -> subprocess.Popen[str]: - raise NotImplemented() + raise NotImplementedError() def present(self) -> bool: """ @@ -87,12 +87,12 @@ def _run(self, arguments: list[str], kwargs) -> int: if result.stdout: try: logger.debug(str(result.stdout)) - except: + except Exception: pass if result.stderr: try: logger.debug(str(result.stderr)) - except: + except Exception: pass if result.returncode == 130: diff --git a/dvrprocess/common/progress.py b/dvrprocess/common/progress.py index 7dfa6d7..24b4245 100644 --- a/dvrprocess/common/progress.py +++ b/dvrprocess/common/progress.py @@ -544,7 +544,8 @@ def __init__(self): self.cpu_percent.renderer = _percent_renderer self.cpu_percent.critical_range = (90, 101) - loadavg_renderer = lambda v: f"{v: 2.2f}" + def loadavg_renderer(value): + return f"{value: 2.2f}" self.loadavg1 = gauge('load1') self.loadavg1.renderer = loadavg_renderer # self.loadavg5 = gauge('load5') diff --git a/dvrprocess/common/subtitle.py b/dvrprocess/common/subtitle.py index 087e11f..4d95968 100644 --- a/dvrprocess/common/subtitle.py +++ b/dvrprocess/common/subtitle.py @@ -148,8 +148,8 @@ def normalized_texts(self) -> list[str]: def set_normalized_texts(self, new_values: list[str]): self._normalized_texts = new_values - l = list(map(lambda e: e[0:2], map(lambda f: f.split(), self._normalized_texts))) - self._normalized_start_words = set([item for sublist in l for item in sublist]) + words = list(map(lambda e: e[0:2], map(lambda f: f.split(), self._normalized_texts))) + self._normalized_start_words = set([item for sublist in words for item in sublist]) def normalized_start_words(self) -> set[str]: self._check_normalized_texts() diff --git a/dvrprocess/common/terminalui.py b/dvrprocess/common/terminalui.py index c155265..8df22a4 100644 --- a/dvrprocess/common/terminalui.py +++ b/dvrprocess/common/terminalui.py @@ -73,7 +73,7 @@ def emit(self, record: logging.LogRecord) -> None: self.y = min(self.y + 1, max_y) self.refresh() - except: + except Exception: # don't break the application because of a logging error pass finally: @@ -336,7 +336,7 @@ def __init__(self, screen): # hide the cursor try: curses.curs_set(0) - except: + except Exception: pass self.gauge_win: GaugeWindow = None @@ -409,7 +409,7 @@ def main(screen) -> int: # show the cursor try: curses.curs_set(1) - except: + except Exception: pass stderr_capture = StreamCapture('stderr') diff --git a/dvrprocess/common/tools.py b/dvrprocess/common/tools.py index 7b8355d..1133eb4 100644 --- a/dvrprocess/common/tools.py +++ b/dvrprocess/common/tools.py @@ -58,13 +58,13 @@ def _run(self, arguments: list[str], kwargs) -> int: duration = None ffmpeg_progress = None stream_gen = ProcessStreamGenerator(proc) - for _, l in stream_gen.generator(): - duration_match = self.duration_matcher.search(l) + for _, err_line in stream_gen.generator(): + duration_match = self.duration_matcher.search(err_line) if duration_match: duration = ceil(edl_util.parse_edl_ts(duration_match.group(1))) if ffmpeg_progress is None: ffmpeg_progress = progress.progress(task_name, 0, duration) - time_match = self.time_matcher.search(l) + time_match = self.time_matcher.search(err_line) if time_match and ffmpeg_progress: ffmpeg_progress.progress(ceil(edl_util.parse_edl_ts(time_match.group(1))), end=duration) proc.wait() @@ -125,8 +125,8 @@ def _run(self, arguments: list[str], kwargs) -> int: proc = subprocess.Popen(arguments, **kwargs2) se_progress = None stream_gen = ProcessStreamGenerator(proc) - for l, _ in stream_gen.generator(): - pct_match = self.pct_matcher.search(l) + for output_line, _ in stream_gen.generator(): + pct_match = self.pct_matcher.search(output_line) if pct_match: if se_progress is None: se_progress = progress.progress(task_name, 0, 100) @@ -172,8 +172,8 @@ def _run(self, arguments: list[str], kwargs) -> int: proc = subprocess.Popen(arguments, **kwargs2) se_progress = None stream_gen = ProcessStreamGenerator(proc) - for l, _ in stream_gen.generator(): - pct_match = self.pct_matcher.search(l) + for output_line, _ in stream_gen.generator(): + pct_match = self.pct_matcher.search(output_line) if pct_match: if se_progress is None: se_progress = progress.progress(task_name, 0, 100) diff --git a/dvrprocess/common/vosk.py b/dvrprocess/common/vosk.py index 272848a..5f208db 100644 --- a/dvrprocess/common/vosk.py +++ b/dvrprocess/common/vosk.py @@ -133,7 +133,7 @@ def kaldi_recognizer(language: str, freq: int, num_channels: int) -> BaseKaldiRe logger.info(f"Using remote transcriber at {rec.remote_url}") else: rec = LocalKaldiRecognizer(_vosk_language, freq, num_channels) - except BaseException as e: + except BaseException: logger.info("Remote transcriber not available") REMOTE_KALDI_SERVER[_vosk_language] = False rec = LocalKaldiRecognizer(_vosk_language, freq, num_channels) diff --git a/dvrprocess/comtune.py b/dvrprocess/comtune.py index 93810d0..04591b1 100755 --- a/dvrprocess/comtune.py +++ b/dvrprocess/comtune.py @@ -850,7 +850,7 @@ def get_comskip_starter_ini_sources(): script_dir = os.path.dirname(os.path.realpath(sys.argv[0])) return [f"{os.environ['HOME']}/.comskip-starter.ini", f"{script_dir}/comskip-starter.ini", - f"/etc/comskip-starter.ini"] + "/etc/comskip-starter.ini"] @lru_cache(maxsize=None) @@ -1158,7 +1158,7 @@ def should_stop() -> bool: return True if check_compute and common.should_stop_processing(): - logger.info(f"INFO: not enough compute available") + logger.info("INFO: not enough compute available") return True return False diff --git a/dvrprocess/conflict-resolve.py b/dvrprocess/conflict-resolve.py index 1749667..adea8ed 100755 --- a/dvrprocess/conflict-resolve.py +++ b/dvrprocess/conflict-resolve.py @@ -35,7 +35,7 @@ def dryrun(self): def resolution_generator(paths: list[str]): latest_filter_hash = profanity_filter.compute_filter_hash() - latest_filter_version = profanity_filter.FILTER_VERSION + # latest_filter_version = profanity_filter.FILTER_VERSION for conflict_path, _ in common.generate_video_files(paths, fail_on_missing=False): if 'conflicted copy' not in conflict_path: continue diff --git a/dvrprocess/find_need_transcode.py b/dvrprocess/find_need_transcode.py index 526fec2..bfc7e3f 100755 --- a/dvrprocess/find_need_transcode.py +++ b/dvrprocess/find_need_transcode.py @@ -427,7 +427,7 @@ def _plex_host_name_to_local(file_name: str, media_roots: list[str]) -> Tuple[st if i >= 0: for root in media_roots: f = os.path.join(root, file_name[i:]) - logger.debug(f"Checking if %s is a valid path for %s", f, file_name) + logger.debug("Checking if %s is a valid path for %s", f, file_name) if os.path.isfile(f): return f, file_name[i:] return None, None diff --git a/dvrprocess/profanity-filter-apply.py b/dvrprocess/profanity-filter-apply.py index fec1e84..b9444a7 100755 --- a/dvrprocess/profanity-filter-apply.py +++ b/dvrprocess/profanity-filter-apply.py @@ -226,7 +226,7 @@ def profanity_filter_apply(media_paths, plex_url=None, dry_run=False, workdir=No return 0 if check_compute and common.should_stop_processing(): - logger.info(f"not enough compute available") + logger.info("not enough compute available") return 0 try: diff --git a/dvrprocess/profanity_filter.py b/dvrprocess/profanity_filter.py index 4902b1d..7823bcb 100755 --- a/dvrprocess/profanity_filter.py +++ b/dvrprocess/profanity_filter.py @@ -376,7 +376,7 @@ def do_profanity_filter(input_file, dry_run=False, keep=False, force=False, filt f"subtitle filtered = {subtitle_filtered_idx}, subtitle filtered forced = {subtitle_filtered_forced_idx}, audio filtered = {audio_filtered_idx}, subtitle per words = {subtitle_words_idx}") if filter_skip: - logger.debug(f"Removing filtered streams") + logger.debug("Removing filtered streams") # Original audio stream arguments.extend(["-map", f"{streams_file}:{audio_original_idx}", @@ -410,10 +410,10 @@ def do_profanity_filter(input_file, dry_run=False, keep=False, force=False, filt if subtitle_srt_words is not None: arguments.extend(["-i", subtitle_srt_words, "-map", f"{streams_file + 2}:0", - f"-metadata:s:s:1", f'title={constants.TITLE_WORDS}', + "-metadata:s:s:1", f'title={constants.TITLE_WORDS}', "-metadata:s:s:1", f'{constants.K_AUDIO_TO_TEXT_VERSION}={audio_to_text_version if audio_to_text_version else ""}', - f"-disposition:s:1", "-default+metadata"]) + "-disposition:s:1", "-default+metadata"]) subtitle_output_idx += 1 elif subtitle_words_idx is not None: arguments.extend(["-map", f"{streams_file}:{subtitle_words_idx}", @@ -872,7 +872,7 @@ def need_original_subtitle_ocr(subtitle_original: dict, media_duration: float, f duration = edl_util.parse_edl_ts(duration_s) if duration < (media_duration * 0.60): return True - except: + except Exception: pass return force @@ -910,7 +910,7 @@ def need_original_subtitle_transcribed(subtitle_original: dict, current_audio2te duration = edl_util.parse_edl_ts(duration_s) if duration < (media_duration * 0.60): return True - except: + except Exception: pass if not current_audio2text_subtitle_version: @@ -1021,7 +1021,7 @@ def ocr_subtitle_bitmap_to_srt(input_info, temp_base, language=None, verbose=Fal tools.subtitle_edit.run([subtitle_filename], check=True) if not os.access(subtitle_srt_filename, os.R_OK): - logger.error(f"SRT not generated from OCR") + logger.error("SRT not generated from OCR") return None word_found_pct = words_in_dictionary_pct(subtitle_srt_filename, language, @@ -1791,7 +1791,7 @@ def fix_subtitle_audio_alignment(subtitle_inout: Union[AssFile, SubRipFile], wor min_fuzz_ratios = [88, 85, 80, 70] # percentage of words to fuzz +/- from each input subtitle element word_count_fuzz_pct = 0.40 - unclaimed_word_capture_duration_max_ms = 1800 + # unclaimed_word_capture_duration_max_ms = 1800 # multiple runs work, it would be better to fix so a single pass works *shrug passes = 2 # for non-DVR source, passes = 0, so we don't move events but we still capture missing words diff --git a/dvrprocess/smart-comcut.py b/dvrprocess/smart-comcut.py index 9dc34d9..3f27d26 100755 --- a/dvrprocess/smart-comcut.py +++ b/dvrprocess/smart-comcut.py @@ -233,7 +233,7 @@ def smart_comcut_cli_run(args: list, dry_run, keep, workdir, preset, force_encod # Sort and ignore top and bottom durations numbers for average. Probably should use sigma instead. videos.sort(key=lambda v: v['duration']) - video_count_to_trim = int(math.ceil(len(videos) / 10.0)) + # video_count_to_trim = int(math.ceil(len(videos) / 10.0)) # videos_for_stats = videos[video_count_to_trim:-video_count_to_trim] videos_for_stats = videos @@ -381,7 +381,6 @@ def cut(filepath, keep=False, workdir=None, preset=None, force_encode=False, crop_frame_op: crop_frame.CropFrameOperation = crop_frame.CropFrameOperation.NONE, crop_frame_fixed: Union[str, None] = None, desired_video_codecs=None): - filepath_stat = os.stat(filepath) dirname = os.path.dirname(filepath) basename = os.path.basename(filepath) tempfilename = f"{dirname}/.~{basename.replace('.mkv', '.transcoded.mkv')}" @@ -395,6 +394,7 @@ def cut(filepath, keep=False, workdir=None, preset=None, force_encode=False, if os.path.exists(tempfilename): os.remove(tempfilename) return + # filepath_stat = os.stat(filepath) # if os.stat(tempfilename).st_size < (filepath_stat.st_size / 2): # logger.error(f"Cut file is less than half of original, skipping") # os.remove(tempfilename) diff --git a/dvrprocess/test_find_desired_keyframe.py b/dvrprocess/test_find_desired_keyframe.py index 2d2709e..fbe76bf 100644 --- a/dvrprocess/test_find_desired_keyframe.py +++ b/dvrprocess/test_find_desired_keyframe.py @@ -1,4 +1,5 @@ import unittest + import common @@ -11,56 +12,56 @@ def test_empty(self): self.assertEqual(100.0, common.find_desired_keyframe([], 100.0)) def test_single_entry(self): - l = [0.0, 100.0] - self.assertEqual(100.0, common.find_desired_keyframe(l, 100.0)) - self.assertEqual(100.0, common.find_desired_keyframe(l, 90.0)) - self.assertEqual(100.0, common.find_desired_keyframe(l, 110.0)) + keyframes = [0.0, 100.0] + self.assertEqual(100.0, common.find_desired_keyframe(keyframes, 100.0)) + self.assertEqual(100.0, common.find_desired_keyframe(keyframes, 90.0)) + self.assertEqual(100.0, common.find_desired_keyframe(keyframes, 110.0)) def test_single_two(self): - l = [0.0, 50.5, 100.0] - self.assertEqual(100.0, common.find_desired_keyframe(l, 100.0)) - self.assertEqual(100.0, common.find_desired_keyframe(l, 90.0)) - self.assertEqual(100.0, common.find_desired_keyframe(l, 110.0)) + keyframes = [0.0, 50.5, 100.0] + self.assertEqual(100.0, common.find_desired_keyframe(keyframes, 100.0)) + self.assertEqual(100.0, common.find_desired_keyframe(keyframes, 90.0)) + self.assertEqual(100.0, common.find_desired_keyframe(keyframes, 110.0)) def test_exact(self): - l = [0.0, 25.0, 50.5, 100.0, 201.2] - self.assertEqual(25.0, common.find_desired_keyframe(l, 25.0)) - self.assertEqual(50.5, common.find_desired_keyframe(l, 50.5)) - self.assertEqual(100.0, common.find_desired_keyframe(l, 100.0)) - self.assertEqual(201.2, common.find_desired_keyframe(l, 201.2)) + keyframes = [0.0, 25.0, 50.5, 100.0, 201.2] + self.assertEqual(25.0, common.find_desired_keyframe(keyframes, 25.0)) + self.assertEqual(50.5, common.find_desired_keyframe(keyframes, 50.5)) + self.assertEqual(100.0, common.find_desired_keyframe(keyframes, 100.0)) + self.assertEqual(201.2, common.find_desired_keyframe(keyframes, 201.2)) def test_closest(self): - l = [0.0, 25.0, 50.5, 100.0, 201.2] - self.assertEqual(0.0, common.find_desired_keyframe(l, 10.0)) - self.assertEqual(25.0, common.find_desired_keyframe(l, 21.0)) - self.assertEqual(25.0, common.find_desired_keyframe(l, 27.0)) - self.assertEqual(50.5, common.find_desired_keyframe(l, 48.0)) - self.assertEqual(50.5, common.find_desired_keyframe(l, 51.0)) - self.assertEqual(50.5, common.find_desired_keyframe(l, 60.0)) - self.assertEqual(100.0, common.find_desired_keyframe(l, 88.0)) - self.assertEqual(100.0, common.find_desired_keyframe(l, 150.0)) - self.assertEqual(201.2, common.find_desired_keyframe(l, 220.0)) + keyframes = [0.0, 25.0, 50.5, 100.0, 201.2] + self.assertEqual(0.0, common.find_desired_keyframe(keyframes, 10.0)) + self.assertEqual(25.0, common.find_desired_keyframe(keyframes, 21.0)) + self.assertEqual(25.0, common.find_desired_keyframe(keyframes, 27.0)) + self.assertEqual(50.5, common.find_desired_keyframe(keyframes, 48.0)) + self.assertEqual(50.5, common.find_desired_keyframe(keyframes, 51.0)) + self.assertEqual(50.5, common.find_desired_keyframe(keyframes, 60.0)) + self.assertEqual(100.0, common.find_desired_keyframe(keyframes, 88.0)) + self.assertEqual(100.0, common.find_desired_keyframe(keyframes, 150.0)) + self.assertEqual(201.2, common.find_desired_keyframe(keyframes, 220.0)) def test_closest_offset(self): - l = [1.0, 26.0, 51.5, 101.0, 202.2] - self.assertEqual(1.0, common.find_desired_keyframe(l, 10.0)) - self.assertEqual(26.0, common.find_desired_keyframe(l, 21.0)) - self.assertEqual(26.0, common.find_desired_keyframe(l, 27.0)) - self.assertEqual(51.5, common.find_desired_keyframe(l, 48.0)) - self.assertEqual(51.5, common.find_desired_keyframe(l, 51.0)) - self.assertEqual(51.5, common.find_desired_keyframe(l, 60.0)) - self.assertEqual(101.0, common.find_desired_keyframe(l, 88.0)) - self.assertEqual(101.0, common.find_desired_keyframe(l, 150.0)) - self.assertEqual(202.2, common.find_desired_keyframe(l, 220.0)) + keyframes = [1.0, 26.0, 51.5, 101.0, 202.2] + self.assertEqual(1.0, common.find_desired_keyframe(keyframes, 10.0)) + self.assertEqual(26.0, common.find_desired_keyframe(keyframes, 21.0)) + self.assertEqual(26.0, common.find_desired_keyframe(keyframes, 27.0)) + self.assertEqual(51.5, common.find_desired_keyframe(keyframes, 48.0)) + self.assertEqual(51.5, common.find_desired_keyframe(keyframes, 51.0)) + self.assertEqual(51.5, common.find_desired_keyframe(keyframes, 60.0)) + self.assertEqual(101.0, common.find_desired_keyframe(keyframes, 88.0)) + self.assertEqual(101.0, common.find_desired_keyframe(keyframes, 150.0)) + self.assertEqual(202.2, common.find_desired_keyframe(keyframes, 220.0)) def test_force_after(self): - l = [0.0, 25.0, 50.5, 100.0, 201.2] - self.assertEqual(25.0, common.find_desired_keyframe(l, 10.0, common.KeyframeSearchPreference.AFTER)) - self.assertEqual(25.0, common.find_desired_keyframe(l, 21.0, common.KeyframeSearchPreference.AFTER)) - self.assertEqual(50.5, common.find_desired_keyframe(l, 27.0, common.KeyframeSearchPreference.AFTER)) - self.assertEqual(50.5, common.find_desired_keyframe(l, 48.0, common.KeyframeSearchPreference.AFTER)) - self.assertEqual(100.0, common.find_desired_keyframe(l, 51.0, common.KeyframeSearchPreference.AFTER)) - self.assertEqual(100.0, common.find_desired_keyframe(l, 60.0, common.KeyframeSearchPreference.AFTER)) - self.assertEqual(100.0, common.find_desired_keyframe(l, 88.0, common.KeyframeSearchPreference.AFTER)) - self.assertEqual(201.2, common.find_desired_keyframe(l, 150.0, common.KeyframeSearchPreference.AFTER)) - self.assertEqual(201.2, common.find_desired_keyframe(l, 220.0, common.KeyframeSearchPreference.AFTER)) + keyframes = [0.0, 25.0, 50.5, 100.0, 201.2] + self.assertEqual(25.0, common.find_desired_keyframe(keyframes, 10.0, common.KeyframeSearchPreference.AFTER)) + self.assertEqual(25.0, common.find_desired_keyframe(keyframes, 21.0, common.KeyframeSearchPreference.AFTER)) + self.assertEqual(50.5, common.find_desired_keyframe(keyframes, 27.0, common.KeyframeSearchPreference.AFTER)) + self.assertEqual(50.5, common.find_desired_keyframe(keyframes, 48.0, common.KeyframeSearchPreference.AFTER)) + self.assertEqual(100.0, common.find_desired_keyframe(keyframes, 51.0, common.KeyframeSearchPreference.AFTER)) + self.assertEqual(100.0, common.find_desired_keyframe(keyframes, 60.0, common.KeyframeSearchPreference.AFTER)) + self.assertEqual(100.0, common.find_desired_keyframe(keyframes, 88.0, common.KeyframeSearchPreference.AFTER)) + self.assertEqual(201.2, common.find_desired_keyframe(keyframes, 150.0, common.KeyframeSearchPreference.AFTER)) + self.assertEqual(201.2, common.find_desired_keyframe(keyframes, 220.0, common.KeyframeSearchPreference.AFTER)) diff --git a/dvrprocess/test_profanity_filter_streams.py b/dvrprocess/test_profanity_filter_streams.py index 6fbe6c6..84b1898 100644 --- a/dvrprocess/test_profanity_filter_streams.py +++ b/dvrprocess/test_profanity_filter_streams.py @@ -340,7 +340,7 @@ def mock(method_name: str, arguments: list, **kwargs): root = tree.getroot() for k, v in expected_tags.items(): found = False - for el in root.findall(f'.//Simple'): + for el in root.findall('.//Simple'): if el.find('Name').text == k: found = True if v is not None: @@ -708,7 +708,7 @@ def test_apply_unfiltered_sub_orig_text__mute_voice_channels__filtered(self): tools.ffmpeg = proc_invoker.MockProcInvoker('ffmpeg', mocks=[ self._mock_ffmpeg_extract_audio_for_transcribing("filtered.wav"), self._mock_ffmpeg_extract_subtitle_original('needs_filtered.ssa.txt'), - {'method_name': 'check_output', 'result': self._read_file(f'../fixtures/ffmpeg-5-layouts.txt')}, + {'method_name': 'check_output', 'result': self._read_file('../fixtures/ffmpeg-5-layouts.txt')}, self._mock_ffmpeg_create_with_filtered_streams(4, mapped_stream_count=8), ]) profanity_filter.do_profanity_filter(mkv_path, mute_channels=config.MuteChannels.VOICE) @@ -720,7 +720,7 @@ def test_apply_unfiltered_sub_orig_image__mute_voice_channels__filtered(self): tools.ffmpeg = proc_invoker.MockProcInvoker('ffmpeg', mocks=[ self._mock_ffmpeg_extract_dvdsub, self._mock_ffmpeg_extract_audio_for_transcribing("filtered.wav"), - {'method_name': 'check_output', 'result': self._read_file(f'../fixtures/ffmpeg-5-layouts.txt')}, + {'method_name': 'check_output', 'result': self._read_file('../fixtures/ffmpeg-5-layouts.txt')}, self._mock_ffmpeg_create_with_filtered_streams(5, mapped_stream_count=9, expected_args=['pan=5.1']), ]) tools.subtitle_edit = proc_invoker.MockProcInvoker('subtitle-edit', mocks=[ @@ -729,11 +729,11 @@ def test_apply_unfiltered_sub_orig_image__mute_voice_channels__filtered(self): profanity_filter.do_profanity_filter(mkv_path, mute_channels=config.MuteChannels.VOICE) def test_is_ripped_from_media_true(self): - with open(f"../fixtures/media_state_ripped.json", "rt") as f: + with open("../fixtures/media_state_ripped.json", "rt") as f: input_info_json = json.load(f) self.assertTrue(is_ripped_from_media(input_info_json)) def test_is_ripped_from_media_false(self): - with open(f"../fixtures/media_state_unfiltered_sub_orig_image.json", "rt") as f: + with open("../fixtures/media_state_unfiltered_sub_orig_image.json", "rt") as f: input_info_json = json.load(f) self.assertFalse(is_ripped_from_media(input_info_json)) diff --git a/dvrprocess/test_tools.py b/dvrprocess/test_tools.py index c1fc744..3edde01 100644 --- a/dvrprocess/test_tools.py +++ b/dvrprocess/test_tools.py @@ -68,7 +68,7 @@ def __init__(self, methodName: str = ...): def setUp(self) -> None: tools.ffmpeg = proc_invoker.MockProcInvoker('ffmpeg', mocks=[ - {'method_name': 'check_output', 'result': _read_file(f'../fixtures/ffmpeg-5-layouts.txt')}, + {'method_name': 'check_output', 'result': _read_file('../fixtures/ffmpeg-5-layouts.txt')}, ]) self.layouts = tools.get_audio_layouts(refresh=True) diff --git a/dvrprocess/tvshow-summary.py b/dvrprocess/tvshow-summary.py index 9464971..73bb64c 100755 --- a/dvrprocess/tvshow-summary.py +++ b/dvrprocess/tvshow-summary.py @@ -107,9 +107,9 @@ def episode_human_sort_key(e): def episode_human_sort(seq): - l = list(seq) - l.sort(key=episode_human_sort_key) - return l + result = list(seq) + result.sort(key=episode_human_sort_key) + return result # Print a CSV of all shows, all episodes diff --git a/dvrprocess/tvshow-suspicious.py b/dvrprocess/tvshow-suspicious.py index 6160fa2..1298095 100755 --- a/dvrprocess/tvshow-suspicious.py +++ b/dvrprocess/tvshow-suspicious.py @@ -110,9 +110,9 @@ def episode_human_sort_key(e): def episode_human_sort(seq): - l = list(seq) - l.sort(key=episode_human_sort_key) - return l + result = list(seq) + result.sort(key=episode_human_sort_key) + return result # Print a CSV of all shows, all episodes diff --git a/fixtures/bones-s02e01-aligned.ssa b/fixtures/bones-s02e01-aligned.ssa index be8673a..27c7a8b 100644 --- a/fixtures/bones-s02e01-aligned.ssa +++ b/fixtures/bones-s02e01-aligned.ssa @@ -125,7 +125,7 @@ Dialogue: 0,0:05:25.38,0:05:27.41,Default,,0,0,0,,{TIME:325380,327412}♪ [Theme Dialogue: 0,0:05:54.65,0:06:00.02,Default,,0,0,0,,{TIME:354656,360024}If something happened to you what would\Nhappen to them the whole their education Dialogue: 0,0:06:00.17,0:06:05.81,Default,,0,0,0,,{TIME:360175,365815}Their future you need life insurance\Nchances are select gold can help you get it Dialogue: 0,0:06:05.99,0:06:11.12,Default,,0,0,0,,{TIME:365995,371125}For less than a dollar a day for like\Nquote found Jacob forty-five hundred -Dialogue: 0,0:06:11.12,0:06:15.47,Default,,0,0,0,,{TIME:371125,375475}a thousand dollar policy for only\Nnineteen dollars a month and select\Nquote found +Dialogue: 0,0:06:11.12,0:06:15.47,Default,,0,0,0,,{TIME:371125,375475}Thousand dollar policy for only nineteen\Ndollars a month and select quote found Dialogue: 0,0:06:15.47,0:06:19.70,Default,,0,0,0,,{TIME:375475,379705}His wife Wendy of five hundred thousand\Ndollar policy for only seventeen dollars Dialogue: 0,0:06:19.70,0:06:25.16,Default,,0,0,0,,{TIME:379705,385165}A month or secret at select quote we\Naggressively comparison shop highly rated Dialogue: 0,0:06:25.16,0:06:31.28,Default,,0,0,0,,{TIME:385165,391285}Companies to find you the company with\Nthe best rates we found Gary thirty-five @@ -414,7 +414,7 @@ Dialogue: 0,0:23:43.10,0:23:45.74,Default,,0,0,0,,{TIME:1423105,1425743}- Which Dialogue: 0,0:23:45.74,0:23:48.05,Default,,0,0,0,,{TIME:1425743,1428055}- Five-gallon mason jars.\N-\N[ Zack ] Six of them. Dialogue: 0,0:23:48.05,0:23:50.66,Default,,0,0,0,,{TIME:1428055,1430665}- Filled with gasoline.\N- That or moonshine. Dialogue: 0,0:23:51.32,0:23:54.30,Default,,0,0,0,,{TIME:1431320,1434305}Why does the whole lab\Nsmell like a luau? -Dialogue: 0,0:23:54.35,0:23:55.22,Default,,0,0,0,,{TIME:1434355,1435223}Out because I. +Dialogue: 0,0:23:54.35,0:23:55.22,Default,,0,0,0,,{TIME:1434355,1435223}Our because I. Dialogue: 0,0:23:55.22,0:23:58.45,Default,,0,0,0,,{TIME:1435225,1438455}Zack and Hodgins are proving\Nthat there was extra accelerant\Nin Lynch's vehicle. Dialogue: 0,0:23:58.45,0:24:01.76,Default,,0,0,0,,{TIME:1438455,1441765}- Using what medium?\N- Artificial bone\Ncovered with Spam. Dialogue: 0,0:24:01.76,0:24:04.73,Default,,0,0,0,,{TIME:1441765,1444735}Turn this off. @@ -526,7 +526,7 @@ Dialogue: 0,0:30:17.54,0:30:24.99,Default,,0,0,0,,{TIME:1817545,1824990}Can affo Dialogue: 0,0:30:24.99,0:30:29.10,Default,,0,0,0,,{TIME:1824990,1829100}Give you flexible financing super\Nflexible new adjusted terms because\Nyou're in Dialogue: 0,0:30:29.10,0:30:32.90,Default,,0,0,0,,{TIME:1829100,1832909}Control oh cool we can change a down\Npayment to exactly what fits our budget and Dialogue: 0,0:30:32.91,0:30:36.33,Default,,0,0,0,,{TIME:1832910,1836339}You can easily see your monthly payment\Nchange to this number checkout go to -Dialogue: 0,0:30:36.33,0:30:41.97,Default,,0,0,0,,{TIME:1836339,1841970}Drive the car on your terms this\Nunderwear R P proof ban period proof and +Dialogue: 0,0:30:36.33,0:30:41.97,Default,,0,0,0,,{TIME:1836339,1841970}Drive the car on your terms these\Nunderwear R P proof ban period proof and Dialogue: 0,0:30:41.97,0:30:46.83,Default,,0,0,0,,{TIME:1841970,1846830}Sweat proof their leakproof underwear\Nfrom next comfy and confident protection Dialogue: 0,0:30:46.83,0:30:51.11,Default,,0,0,0,,{TIME:1846830,1851118}That field just like normal for so many\Nstyles and colors to choose from Dialogue: 0,0:30:51.12,0:30:56.57,Default,,0,0,0,,{TIME:1851121,1856578}Switching is easy at next dot com put\Nthe CFL the Miami team evidence. @@ -648,12 +648,12 @@ Dialogue: 0,0:36:43.71,0:36:48.60,Default,,0,0,0,,{TIME:2203710,2208600}Security Dialogue: 0,0:36:48.60,0:36:53.79,Default,,0,0,0,,{TIME:2208600,2213790}All of your original meta care coverage\Nblush extra benefits you get an old and Dialogue: 0,0:36:53.79,0:36:59.34,Default,,0,0,0,,{TIME:2213790,2219340}One plan designed to fit your needs so\Nyou can be your best every day you could Dialogue: 0,0:36:59.34,0:37:05.03,Default,,0,0,0,,{TIME:2219340,2225039}Have medical coverage prescription drugs\Nwith zero dollar generics little vision -Dialogue: 0,0:37:05.03,0:37:09.66,Default,,0,0,0,,{TIME:2225039,2229660}And hearing loss of the Welsher visual\Nflex card money for over the counter +Dialogue: 0,0:37:05.03,0:37:09.66,Default,,0,0,0,,{TIME:2225039,2229660}And hearing loss of the Belcher visual\Nflex card money for over the counter Dialogue: 0,0:37:09.66,0:37:15.45,Default,,0,0,0,,{TIME:2229660,2235450}Items a buddy bag and your social\Nsecurity check each month and so much more Dialogue: 0,0:37:16.09,0:37:20.37,Default,,0,0,0,,{TIME:2236095,2240370}There's more good news you can get a\NWalker plan for a zero dollar monthly Dialogue: 0,0:37:20.37,0:37:25.32,Default,,0,0,0,,{TIME:2240370,2245320}Premium good well here offer all of\Nthose benefits for a zero dollar monthly Dialogue: 0,0:37:25.32,0:37:30.66,Default,,0,0,0,,{TIME:2245320,2250660}Premium it's simple medicare advantage\Nand medicare part D prescription drug -Dialogue: 0,0:37:30.66,0:37:35.67,Default,,0,0,0,,{TIME:2250660,2255670}Coverage is important parts of medicare\NWalker has a contract with medicare to +Dialogue: 0,0:37:30.66,0:37:35.67,Default,,0,0,0,,{TIME:2250660,2255670}Coverage are important parts of medicare\NWalker has a contract with medicare to Dialogue: 0,0:37:35.67,0:37:41.28,Default,,0,0,0,,{TIME:2255670,2261280}Offer and provide these important\Noptions to call right now to get your free Dialogue: 0,0:37:41.28,0:37:45.81,Default,,0,0,0,,{TIME:2261280,2265810}Copy of the Walker all in one guy and\Ncall one eight six seven four zero Dialogue: 0,0:37:45.81,0:37:51.02,Default,,0,0,0,,{TIME:2265810,2271029}Four nine three seven now there was\Nabsolutely no obligation for requesting @@ -872,7 +872,7 @@ Dialogue: 0,0:50:11.47,0:50:13.75,Default,,0,0,0,,{TIME:3011470,3013755}♪♪ Dialogue: 0,0:50:18.84,0:50:23.31,Default,,0,0,0,,{TIME:3018840,3023310}If something happened to you what would\Nhappen to them their whole their Dialogue: 0,0:50:23.31,0:50:29.56,Default,,0,0,0,,{TIME:3023310,3029565}Education their future you need\Ninsurance and chances are select quote\Ncan help Dialogue: 0,0:50:29.56,0:50:35.08,Default,,0,0,0,,{TIME:3029565,3035085}You get it for less than a dollar a day\Nselect quote found Jacob forty-five -Dialogue: 0,0:50:35.08,0:50:39.13,Default,,0,0,0,,{TIME:3035085,3039135}a hundred thousand dollar policy for\Nonly nineteen dollars a month and select +Dialogue: 0,0:50:35.08,0:50:39.13,Default,,0,0,0,,{TIME:3035085,3039135}Hundred thousand dollar policy for only\Nnineteen dollars a month and select Dialogue: 0,0:50:39.16,0:50:42.88,Default,,0,0,0,,{TIME:3039165,3042885}Quote found his wife Wendy of five\Nhundred thousand dollar policy for only Dialogue: 0,0:50:42.88,0:50:48.28,Default,,0,0,0,,{TIME:3042885,3048285}Seventeen dollars a month or secret that\Nselect quote we aggressively comparison Dialogue: 0,0:50:48.28,0:50:54.31,Default,,0,0,0,,{TIME:3048285,3054315}Shop highly rated companies to find you\Nthe company with the best rates we found @@ -881,7 +881,7 @@ Dialogue: 0,0:50:59.23,0:51:04.18,Default,,0,0,0,,{TIME:3059235,3064185}Why pay Dialogue: 0,0:51:04.39,0:51:07.75,Default,,0,0,0,,{TIME:3064395,3067754}Call one eight hundred three zero four\Nthree five nine or good as Dialogue: 0,0:51:07.75,0:51:12.64,Default,,0,0,0,,{TIME:3067754,3072645}Electrical dot com now and get the\Ninsurance your family needs at a price you Dialogue: 0,0:51:12.64,0:51:21.28,Default,,0,0,0,,{TIME:3072645,3081285}Can afford select quote we shop you\Nsave. The Omaha steaks semi-annual sale is -Dialogue: 0,0:51:21.28,0:51:26.32,Default,,0,0,0,,{TIME:3081285,3086325}Here right now we're offering fifty\Npercent off Site wide the only number that +Dialogue: 0,0:51:21.28,0:51:26.32,Default,,0,0,0,,{TIME:3081285,3086325}Here right now we're offering fifty\Npercent off sitewide the only number that Dialogue: 0,0:51:26.32,0:51:30.97,Default,,0,0,0,,{TIME:3086325,3090975}Hasn't changed is are one hundred\Npercent guarantee that you'll love every bite Dialogue: 0,0:51:31.56,0:51:35.50,Default,,0,0,0,,{TIME:3091564,3095505}If you've never tried Omaha steaks save\Nan extra thirty dollars with promo code Dialogue: 0,0:51:35.50,0:51:40.84,Default,,0,0,0,,{TIME:3095505,3100845}First time visit Omaha steaks dot com\Nslash TD today why wouldn't you want to @@ -895,11 +895,11 @@ Dialogue: 0,0:52:07.93,0:52:12.43,Default,,0,0,0,,{TIME:3127935,3132435}Ten no o Dialogue: 0,0:52:12.43,0:52:16.54,Default,,0,0,0,,{TIME:3132435,3136545}Infinitely more effective than a shower\Nalone so just take a shower or shower Dialogue: 0,0:52:16.54,0:52:22.30,Default,,0,0,0,,{TIME:3136545,3142300}With Lump and be zero out of time Greg\NI'm dead the five years of magic spooked Dialogue: 0,0:52:22.69,0:52:26.77,Default,,0,0,0,,{TIME:3142695,3146775}We grew up loving Syria we quickly\Nrealized our childhood favorites were just -Dialogue: 0,0:52:26.83,0:52:30.94,Default,,0,0,0,,{TIME:3146835,3150945}Empty carbs and sugar, so we set out to\Ninvent our own from scratch we got rid of +Dialogue: 0,0:52:26.83,0:52:30.94,Default,,0,0,0,,{TIME:3146835,3150945}Empty carbs and sugar so we set out to\Ninvent our own from scratch we got rid of Dialogue: 0,0:52:30.94,0:52:35.26,Default,,0,0,0,,{TIME:3150945,3155265}The sugar dreams and all the other done\Nand that left us with fifth then we Dialogue: 0,0:52:35.26,0:52:39.97,Default,,0,0,0,,{TIME:3155265,3159973}Recreated the magical taste packed with\Nprotein it's dead classics theory of Dialogue: 0,0:52:39.97,0:52:45.13,Default,,0,0,0,,{TIME:3159973,3165135}Shit we loved it and everyone else seem\Nto love it to record it matter expert -Dialogue: 0,0:52:45.40,0:52:50.80,Default,,0,0,0,,{TIME:3165405,3170805}Try the magic for yourself at magic food\Ndot com this underwear R P proof then +Dialogue: 0,0:52:45.40,0:52:50.80,Default,,0,0,0,,{TIME:3165405,3170805}Try the magic for yourself at magic food\Ndot com these underwear R P proof then Dialogue: 0,0:52:50.80,0:52:55.96,Default,,0,0,0,,{TIME:3170805,3175965}Period proof and Sweat proof their\Nleak-proof underwear from next comfy and Dialogue: 0,0:52:55.96,0:53:00.55,Default,,0,0,0,,{TIME:3175965,3180555}Confident protection that field just\Nlike normal with so many styles and colors Dialogue: 0,0:53:00.55,0:53:05.83,Default,,0,0,0,,{TIME:3180555,3185835}To choose from switching is easy at next\Ndot com you plan to bring extra office diff --git a/fixtures/bones-s02e11-aligned.ssa b/fixtures/bones-s02e11-aligned.ssa index 8b0857e..fa30592 100644 --- a/fixtures/bones-s02e11-aligned.ssa +++ b/fixtures/bones-s02e11-aligned.ssa @@ -112,8 +112,8 @@ Dialogue: 0,0:05:56.50,0:06:08.53,Default,,0,0,0,,{TIME:356503,368533}Which is h Dialogue: 0,0:06:08.53,0:06:12.07,Default,,0,0,0,,{TIME:368533,372073}Of twenty-twenty to go to the athletics\Ndot com and get to for twenty-four Dialogue: 0,0:06:12.07,0:06:16.36,Default,,0,0,0,,{TIME:372073,376361}Dollar bottom up to eighty percent of\Neverything and brand-new activewear style Dialogue: 0,0:06:16.39,0:06:22.18,Default,,0,0,0,,{TIME:376393,382183}In the classics inspired college been\Npregnant at the best prices every you -Dialogue: 0,0:06:22.18,0:06:26.05,Default,,0,0,0,,{TIME:382183,386052}Know that feeling when it's four am, and\Nyou're changing a wet diaper for the -Dialogue: 0,0:06:26.11,0:06:31.03,Default,,0,0,0,,{TIME:386113,391033}Bird night in a row I couldn't take it\Nany more than a found coterie, and it was +Dialogue: 0,0:06:22.18,0:06:26.05,Default,,0,0,0,,{TIME:382183,386052}Know that feeling when it's four am and\Nyou're changing a wet diaper for the +Dialogue: 0,0:06:26.11,0:06:31.03,Default,,0,0,0,,{TIME:386113,391033}Bird night in a row I couldn't take it\Nany more than a found coterie and it was Dialogue: 0,0:06:31.03,0:06:35.17,Default,,0,0,0,,{TIME:391033,395173}Love at first overnight is a twelve-hour\Nday parade gets the job done. Dialogue: 0,0:06:35.17,0:06:37.13,Default,,0,0,0,,{TIME:395173,397130}[music playing] Dialogue: 0,0:06:37.23,0:06:41.39,Default,,0,0,0,,{TIME:397230,401393}Today, you can give\Na gift like no other, @@ -339,7 +339,7 @@ Dialogue: 0,0:18:03.85,0:18:04.75,Default,,0,0,0,,{TIME:1083854,1084758}ALEVE Dialogue: 0,0:18:04.75,0:18:05.98,Default,,0,0,0,,{TIME:1084758,1085988}- Who do you take it\Nfor? Dialogue: 0,0:18:12.97,0:18:17.35,Default,,0,0,0,,{TIME:1092974,1097358}Say what are you doing just playing\Nsolitaire oh Jane it's not the nineties Dialogue: 0,0:18:17.35,0:18:24.34,Default,,0,0,0,,{TIME:1097358,1104348}Anymore. Grand arbiter has everything\Nyou love about the nostalgic solitaire so -Dialogue: 0,0:18:24.34,0:18:31.42,Default,,0,0,0,,{TIME:1104348,1111427}Much more exciting is rewarding harvest\Nfeeling and even build your own join any +Dialogue: 0,0:18:24.34,0:18:31.42,Default,,0,0,0,,{TIME:1104348,1111427}Much more exciting is rewarding harvest\Nfeeling and even builds your own join any Dialogue: 0,0:18:31.75,0:18:36.82,Default,,0,0,0,,{TIME:1111753,1116827}Or newer will just sound care download\Nsolitaire grand Horowitz between now if Dialogue: 0,0:18:36.82,0:18:41.95,Default,,0,0,0,,{TIME:1116827,1121958}You're a medicare beneficiary in the\Narea cold out to see how this little card Dialogue: 0,0:18:42.13,0:18:46.87,Default,,0,0,0,,{TIME:1122138,1126878}Could use a big benefit including money\Nheaded back to your social security @@ -352,7 +352,7 @@ Dialogue: 0,0:19:13.57,0:19:19.33,Default,,0,0,0,,{TIME:1153578,1159338}Buddy ba Dialogue: 0,0:19:19.33,0:19:24.94,Default,,0,0,0,,{TIME:1159338,1164948}Good news you can get a Walker plan zero\Ndollar monthly premium all good well Dialogue: 0,0:19:24.95,0:19:29.62,Default,,0,0,0,,{TIME:1164957,1169628}Your offer all of those benefits for\Nzero dollar monthly premium it's simple Dialogue: 0,0:19:30.14,0:19:34.78,Default,,0,0,0,,{TIME:1170146,1174788}Medicare advantage and medicare part D\Nprescription drug coverage or important -Dialogue: 0,0:19:34.81,0:19:39.73,Default,,0,0,0,,{TIME:1174818,1179738}Parts of medicare wheelchair has a\Ncontract with medicare to offer and provide +Dialogue: 0,0:19:34.81,0:19:39.73,Default,,0,0,0,,{TIME:1174818,1179738}Parts of medicare wheelchair have a\Ncontract with medicare to offer and provide Dialogue: 0,0:19:39.73,0:19:45.34,Default,,0,0,0,,{TIME:1179738,1185347}These important options. Call right now\Nto get your free copy of the Walker all Dialogue: 0,0:19:45.34,0:19:50.17,Default,,0,0,0,,{TIME:1185348,1190178}In one guy and call one eight six seven\Nfour zero four nine three seven know Dialogue: 0,0:19:51.10,0:19:56.50,Default,,0,0,0,,{TIME:1191108,1196508}There was absolutely no obligation for\Nrequesting this free information. Offers @@ -819,13 +819,13 @@ Dialogue: 0,0:46:12.61,0:46:16.77,Default,,0,0,0,,{TIME:2772610,2776778}I say, Dialogue: 0,0:46:16.77,0:46:19.77,Default,,0,0,0,,{TIME:2776778,2779778}♪♪ Dialogue: 0,0:46:20.22,0:46:21.45,Default,,0,0,0,,{TIME:2780228,2781458}ALEVE Dialogue: 0,0:46:21.45,0:46:22.68,Default,,0,0,0,,{TIME:2781458,2782688}- Who do you take it\Nfor? -Dialogue: 0,0:46:22.87,0:46:30.09,Default,,0,0,0,,{TIME:2782870,2790098}The whether to last second bake sale.\NTaco Tuesday or a meal for your future in +Dialogue: 0,0:46:22.87,0:46:30.09,Default,,0,0,0,,{TIME:2782870,2790098}Whether to last second bake sale. Taco\NTuesday or a meal for your future in Dialogue: 0,0:46:30.09,0:46:35.34,Default,,0,0,0,,{TIME:2790098,2795342}Laws. It's going to be great the\NMcCormick by your side for over one hundred Dialogue: 0,0:46:35.35,0:46:41.61,Default,,0,0,0,,{TIME:2795353,2801618}Thirty years it's going to be great. My\Nlife used to be so calm and fun until Dialogue: 0,0:46:41.61,0:46:48.96,Default,,0,0,0,,{TIME:2801618,2808968}One day. oh, where'd the farm go the\Ncards they will guide me home you might Dialogue: 0,0:46:48.96,0:46:52.92,Default,,0,0,0,,{TIME:2808968,2812928}Think you know how to play solitaire\Ngrand Harbor face challenges to Dialogue: 0,0:46:52.93,0:46:58.38,Default,,0,0,0,,{TIME:2812930,2818388}The next level with exciting ways to\Nplay it'll keep you sharp it's even better -Dialogue: 0,0:46:58.41,0:47:03.99,Default,,0,0,0,,{TIME:2818418,2823998}Then ordinary so at the end of the day\Nwhen you want to wine play solids grand +Dialogue: 0,0:46:58.41,0:47:03.99,Default,,0,0,0,,{TIME:2818418,2823998}Than ordinary so at the end of the day\Nwhen you want to wine play solids grand Dialogue: 0,0:47:04.00,0:47:11.22,Default,,0,0,0,,{TIME:2824004,2831228}Harvest and explore new world of to\Ndownload for free. Is my friend's death Dialogue: 0,0:47:11.52,0:47:15.78,Default,,0,0,0,,{TIME:2831529,2835788}Because she's a reward Sadie queen she\Nhas the trouble cash rewards card and I Dialogue: 0,0:47:15.80,0:47:20.01,Default,,0,0,0,,{TIME:2835802,2840018}Would triple cash rewards back on PBS\Nand no annual fee or spend more time diff --git a/fixtures/men-in-black-aligned.srt b/fixtures/men-in-black-aligned.srt index 57066e0..8c081fd 100755 --- a/fixtures/men-in-black-aligned.srt +++ b/fixtures/men-in-black-aligned.srt @@ -143,7 +143,7 @@ is by the. 31 00:05:12,160 --> 00:05:14,347 -Although the whether say I'd say. +Although whether say I'd say. 32 00:05:14,421 --> 00:05:17,152 diff --git a/fixtures/rp_s01e01.srt.txt b/fixtures/rp_s01e01.srt.txt index d9d8ed3..a324078 100644 --- a/fixtures/rp_s01e01.srt.txt +++ b/fixtures/rp_s01e01.srt.txt @@ -94,7 +94,7 @@ Many. 21 00:06:26,227 --> 00:06:35,317 -But not before. The two every corner of +But not before. The to every corner of me to. 22 @@ -130,7 +130,7 @@ the other commanders or right and our 29 00:09:25,867 --> 00:09:31,282 -Enemy is. the latest closing. Flesh in. +Enemy is. latest closing. Flesh in. 30 00:10:32,262 --> 00:10:35,172 @@ -165,7 +165,7 @@ now whatever happened here was long ago. 37 00:13:24,035 --> 00:13:28,002 -Stone cannot hide them mark on whose +Stone cannot hide them mark on who's very hand is flame and clinched. 38 @@ -691,7 +691,7 @@ the land a windless only in the blessing 146 00:35:43,972 --> 00:35:51,352 Round conduct which is broken into be -healed go there go, and I promise you +healed go there go and I promise you 147 00:35:52,432 --> 00:35:57,802 @@ -742,7 +742,7 @@ well as years as ever and the poisoning 157 00:38:16,822 --> 00:38:22,461 What poisoning the one who were just -discussing no no no no was poisoned grass +discussing no, no no, no was poisoned grass 158 00:38:22,822 --> 00:38:27,562 @@ -808,8 +808,8 @@ call them artifices. Most wounds to our 171 00:40:43,387 --> 00:40:49,477 -Bodies he'll have their own a code, so -it is their labor instead to render hidden +Bodies he'll have their own a code so it +is their labor instead to render hidden 172 00:40:49,477 --> 00:40:57,547 @@ -851,7 +851,7 @@ without have to keep one eye squarely 180 00:41:49,987 --> 00:41:56,557 On you well do you think me blind I -think he talked too much, and you smell of +think he talked too much and you smell of 181 00:41:56,557 --> 00:42:00,037 @@ -908,7 +908,7 @@ and you shall be returning home to far more 192 00:43:46,656 --> 00:43:54,097 -Then you left. On as. title. Your life +Than you left. On as. title. Your life will begin a new. 193 @@ -924,7 +924,7 @@ their ancestors once did. But because 195 00:44:06,577 --> 00:44:14,347 -Of whom they still are and be grateful +Of who they still are and be grateful 196 00:44:15,517 --> 00:44:17,887 @@ -1103,7 +1103,7 @@ with him. But I'll allow you to explain 233 00:51:05,977 --> 00:51:13,430 -The details' lord Caleb Rimbaud as +The details lord Caleb Rimbaud as 234 00:51:14,587 --> 00:51:19,955 @@ -1153,7 +1153,7 @@ variation hope most of all that. Why. 244 00:52:36,059 --> 00:52:39,610 -The people of and where known for having +The people of and were known for having been especially strong and the loyalty to 245 diff --git a/requirements.txt b/requirements.txt index 1f19a0a..9aded4e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,9 +1,9 @@ ass-parser==1.0 pysrt==1.1.2 -plexapi==4.15.7 -psutil==5.9.7 +plexapi==4.15.12 +psutil==5.9.8 requests==2.31.0 -pygad==3.3.0 +pygad==3.3.1 # specific version of numpy required for pygad 2023-01-18 # numpy==1.23.5 vosk==0.3.44 @@ -11,4 +11,4 @@ websockets==12.0 IMDbPY==2022.7.9 thefuzz[speedup]==0.19.0 num2words==0.5.13 -language-tool-python==2.7.1 +language-tool-python==2.8