From 41cef6af3e7f3cd9bf7a83aa444647b5d3d868cc Mon Sep 17 00:00:00 2001 From: Jesse Bannon Date: Sat, 26 Nov 2022 12:25:05 -0800 Subject: [PATCH] test --- src/ytdl_sub/plugins/file_convert.py | 61 +++++++++++++++---- tests/e2e/plugins/test_file_convert.py | 37 +++++++++++ .../file_convert/output_custom_ffmpeg.json | 7 +++ .../file_convert/output_custom_ffmpeg.txt | 15 +++++ 4 files changed, 108 insertions(+), 12 deletions(-) create mode 100644 tests/resources/expected_downloads_summaries/plugins/file_convert/output_custom_ffmpeg.json create mode 100644 tests/resources/transaction_log_summaries/plugins/file_convert/output_custom_ffmpeg.txt diff --git a/src/ytdl_sub/plugins/file_convert.py b/src/ytdl_sub/plugins/file_convert.py index 05f19700..e7dfd067 100644 --- a/src/ytdl_sub/plugins/file_convert.py +++ b/src/ytdl_sub/plugins/file_convert.py @@ -5,9 +5,13 @@ from typing import Optional from ytdl_sub.entries.entry import Entry from ytdl_sub.entries.variables.kwargs import EXT -from ytdl_sub.plugins.plugin import Plugin, PluginPriority +from ytdl_sub.plugins.plugin import Plugin from ytdl_sub.plugins.plugin import PluginOptions +from ytdl_sub.plugins.plugin import PluginPriority from ytdl_sub.utils.exceptions import FileNotDownloadedException +from ytdl_sub.utils.exceptions import ValidationException +from ytdl_sub.utils.ffmpeg import FFMPEG +from ytdl_sub.utils.file_handler import FileHandler from ytdl_sub.utils.file_handler import FileMetadata from ytdl_sub.validators.audo_codec_validator import FileTypeValidator from ytdl_sub.validators.string_formatter_validators import OverridesStringFormatterValidator @@ -30,7 +34,7 @@ class FileConvertOptions(PluginOptions): my_example_preset: file_convert: convert_to: "mp4" - convert_with: "custom" + convert_with: "ffmpeg" ffmpeg_post_process_args: "asfd" """ @@ -48,9 +52,15 @@ class FileConvertOptions(PluginOptions): def __init__(self, name, value): super().__init__(name, value) - self._convert_to: str = self._validate_key(key="convert_to", validator=FileTypeValidator).value - self._convert_with: str = self._validate_key_if_present(key="convert_with", validator=FileConvertWithValidator, default="yt-dlp").value - self._ffmpeg_post_process_args: Optional[str] = self._validate_key_if_present(key="ffmpeg_post_process_args", validator=OverridesStringFormatterValidator) + self._convert_to: str = self._validate_key( + key="convert_to", validator=FileTypeValidator + ).value + self._convert_with: str = self._validate_key_if_present( + key="convert_with", validator=FileConvertWithValidator, default="yt-dlp" + ).value + self._ffmpeg_post_process_args = self._validate_key_if_present( + key="ffmpeg_post_process_args", validator=OverridesStringFormatterValidator + ) if self._convert_to == "ffmpeg" and not self._ffmpeg_post_process_args: raise self._validation_exception( @@ -78,7 +88,7 @@ class FileConvertOptions(PluginOptions): return self._convert_with @property - def ffmpeg_post_process_args(self) -> Optional[str]: + def ffmpeg_post_process_args(self) -> Optional[OverridesStringFormatterValidator]: """ Optional. ffmpeg args to post-process an entry file with. The args will be inserted in the form of: @@ -130,16 +140,43 @@ class FileConvertPlugin(Plugin[FileConvertOptions]): Raises ------ FileNotDownloadedException - If the audio file is not found + If the downloaded file is not found + ValidationException + User ffmpeg arguments errored """ new_ext = self.plugin_options.convert_to + input_video_file_path = entry.get_download_file_path() converted_video_file_path = entry.get_download_file_path().removesuffix(entry.ext) + new_ext - if self.plugin_options.convert_with == "yt-dlp": - if not self.is_dry_run: - if not os.path.isfile(converted_video_file_path): - raise FileNotDownloadedException("Failed to find the converted video file") - else: # ffmpeg + # FFMpeg input video file should already be converted + if self.plugin_options.convert_with == "yt-dlp": + input_video_file_path = converted_video_file_path + + if not self.is_dry_run: + if not os.path.isfile(input_video_file_path): + raise FileNotDownloadedException("Failed to find the input file") + + if self.plugin_options.ffmpeg_post_process_args: + tmp_output_file = ( + converted_video_file_path.removesuffix(new_ext) + f".tmp.{new_ext}" + ) + ffmpeg_args_list = self.overrides.apply_formatter( + self.plugin_options.ffmpeg_post_process_args + ).split() + ffmpeg_args = ["-i", input_video_file_path] + ffmpeg_args_list + [tmp_output_file] + try: + FFMPEG.run(ffmpeg_args) + except Exception as exc: + raise ValidationException( + f"ffmpeg_post_process_args {' '.join(ffmpeg_args)} result in an error" + ) from exc + + if not os.path.isfile(tmp_output_file): + raise ValidationException( + "file_convert ffmpeg_post_process_args did not produce an output file" + ) + + FileHandler.move(tmp_output_file, converted_video_file_path) if entry.ext != new_ext: entry.add_kwargs( diff --git a/tests/e2e/plugins/test_file_convert.py b/tests/e2e/plugins/test_file_convert.py index fdb24dfe..f5558ca8 100644 --- a/tests/e2e/plugins/test_file_convert.py +++ b/tests/e2e/plugins/test_file_convert.py @@ -1,6 +1,7 @@ import pytest from expected_download import assert_expected_downloads from expected_transaction_log import assert_transaction_log_matches +from mergedeep import mergedeep from ytdl_sub.subscriptions.subscription import Subscription @@ -45,3 +46,39 @@ class TestFileConvert: dry_run=dry_run, expected_download_summary_file_name="plugins/file_convert/output.json", ) + + @pytest.mark.parametrize("dry_run", [True, False]) + def test_file_convert_custom_ffmpeg( + self, + music_video_config, + preset_dict, + output_directory, + dry_run, + ): + mergedeep.merge( + preset_dict, + { + "file_convert": { + "convert_to": "mkv", + "convert_with": "ffmpeg", + "ffmpeg_post_process_args": "-vcodec copy -acodec copy -scodec mov_text", + } + }, + ) + subscription = Subscription.from_dict( + config=music_video_config, + preset_name="file_convert_test", + preset_dict=preset_dict, + ) + + transaction_log = subscription.download(dry_run=dry_run) + assert_transaction_log_matches( + output_directory=output_directory, + transaction_log=transaction_log, + transaction_log_summary_file_name="plugins/file_convert/output_custom_ffmpeg.txt", + ) + assert_expected_downloads( + output_directory=output_directory, + dry_run=dry_run, + expected_download_summary_file_name="plugins/file_convert/output_custom_ffmpeg.json", + ) diff --git a/tests/resources/expected_downloads_summaries/plugins/file_convert/output_custom_ffmpeg.json b/tests/resources/expected_downloads_summaries/plugins/file_convert/output_custom_ffmpeg.json new file mode 100644 index 00000000..db055d59 --- /dev/null +++ b/tests/resources/expected_downloads_summaries/plugins/file_convert/output_custom_ffmpeg.json @@ -0,0 +1,7 @@ +{ + ".ytdl-sub-file_convert_test-download-archive.json": "74813dccf4e9732e49f5dc3c2d66f3be", + "Beyond The Guitar/Beyond The Guitar - When you hear Hugh Jackman is returning as Wolverine in Deadpool 3-thumb.jpg": "662fcaadf6e80d63591bac19a5fdffb0", + "Beyond The Guitar/Beyond The Guitar - When you hear Hugh Jackman is returning as Wolverine in Deadpool 3.info.json": "29118ff7fad058437325513f60649dc8", + "Beyond The Guitar/Beyond The Guitar - When you hear Hugh Jackman is returning as Wolverine in Deadpool 3.mkv": "91b167c199a33cb6b6746506f135741f", + "Beyond The Guitar/Beyond The Guitar - When you hear Hugh Jackman is returning as Wolverine in Deadpool 3.nfo": "cacf09ab38f9b3085da9c5af516cf22a" +} \ No newline at end of file diff --git a/tests/resources/transaction_log_summaries/plugins/file_convert/output_custom_ffmpeg.txt b/tests/resources/transaction_log_summaries/plugins/file_convert/output_custom_ffmpeg.txt new file mode 100644 index 00000000..78664c61 --- /dev/null +++ b/tests/resources/transaction_log_summaries/plugins/file_convert/output_custom_ffmpeg.txt @@ -0,0 +1,15 @@ +Files created: +---------------------------------------- +{output_directory} + .ytdl-sub-file_convert_test-download-archive.json +{output_directory}/Beyond The Guitar + Beyond The Guitar - When you hear Hugh Jackman is returning as Wolverine in Deadpool 3-thumb.jpg + Beyond The Guitar - When you hear Hugh Jackman is returning as Wolverine in Deadpool 3.info.json + Beyond The Guitar - When you hear Hugh Jackman is returning as Wolverine in Deadpool 3.mkv + Beyond The Guitar - When you hear Hugh Jackman is returning as Wolverine in Deadpool 3.nfo + NFO tags: + musicvideo: + album: Music Videos + artist: Beyond The Guitar + title: When you hear Hugh Jackman is returning as Wolverine in Deadpool 3 + year: 2022 \ No newline at end of file