[FEATURE] Support best codec type in audio_extract

This commit is contained in:
Jesse Bannon 2023-09-01 23:20:44 -07:00
parent e2482b2760
commit e1057e0310
7 changed files with 117 additions and 7 deletions

View file

@ -8,6 +8,8 @@ from ytdl_sub.config.preset_options import OptionsDictValidator
from ytdl_sub.downloaders.ytdl_options_builder import YTDLOptionsBuilder
from ytdl_sub.entries.entry import Entry
from ytdl_sub.utils.exceptions import FileNotDownloadedException
from ytdl_sub.utils.file_handler import FileMetadata
from ytdl_sub.validators.audo_codec_validator import AUDIO_CODEC_EXTS
from ytdl_sub.validators.audo_codec_validator import AUDIO_CODEC_TYPES_EXTENSION_MAPPING
from ytdl_sub.validators.audo_codec_validator import AudioTypeValidator
from ytdl_sub.validators.validators import FloatValidator
@ -105,12 +107,39 @@ class AudioExtractPlugin(Plugin[AudioExtractOptions]):
FileNotDownloadedException
If the audio file is not found
"""
new_ext = AUDIO_CODEC_TYPES_EXTENSION_MAPPING[self.plugin_options.codec]
extracted_audio_file = entry.get_download_file_path().removesuffix(entry.ext) + new_ext
extracted_audio_file = entry.get_download_file_path()
# yt-dlp doesn't record which ext is used, so try to find it
if self.plugin_options.codec == "best":
new_ext = "m4a"
for possible_ext in AUDIO_CODEC_EXTS:
extracted_audio_file = (
entry.get_download_file_path().removesuffix(entry.ext) + possible_ext
)
if os.path.isfile(extracted_audio_file):
new_ext = possible_ext
break
else:
new_ext = AUDIO_CODEC_TYPES_EXTENSION_MAPPING[self.plugin_options.codec]
extracted_audio_file = entry.get_download_file_path().removesuffix(entry.ext) + new_ext
entry.add_kwargs({"ext": new_ext})
if not self.is_dry_run:
if not os.path.isfile(extracted_audio_file):
raise FileNotDownloadedException("Failed to find the extracted audio file")
entry.add_kwargs({"ext": new_ext})
return entry
def post_process_entry(self, entry: Entry) -> Optional[FileMetadata]:
"""
Warn the user that best cannot infer the format that will be used at run-time.
"""
if self.plugin_options.codec == "best" and self.is_dry_run:
return FileMetadata(
"Caution: extracted audio with 'best' format is not known during dry-run. "
"Defaulting to m4a."
)
return None

View file

@ -21,7 +21,7 @@ VIDEO_CODEC_EXTS: Set[str] = {"avi", "flv", "mkv", "mov", "mp4", "webm"}
class AudioTypeValidator(StringSelectValidator):
_expected_value_type_name = "codec"
_select_values = AUDIO_CODEC_TYPES
_select_values = AUDIO_CODEC_TYPES.union({"best"}) # support 'best' in the audio extract plugin
class FileTypeValidator(StringSelectValidator):

View file

@ -43,6 +43,11 @@ def single_song_preset_dict(output_directory):
}
@pytest.fixture
def single_song_best_format_preset_dict(single_song_preset_dict):
return dict(single_song_preset_dict, **{"audio_extract": {"codec": "best"}})
@pytest.fixture
def multiple_songs_preset_dict(output_directory):
return {
@ -88,7 +93,7 @@ class TestAudioExtract:
)
@pytest.mark.parametrize("dry_run", [True, False])
def test_audio_extract_single_song_new_format(
def test_audio_extract_single_song(
self,
music_audio_config,
single_song_preset_dict,
@ -113,6 +118,32 @@ class TestAudioExtract:
expected_download_summary_file_name="plugins/test_audio_extract_single.json",
)
@pytest.mark.parametrize("dry_run", [True, False])
def test_audio_extract_single_song_best_format(
self,
music_audio_config,
single_song_best_format_preset_dict,
output_directory,
dry_run,
):
subscription = Subscription.from_dict(
config=music_audio_config,
preset_name="single_song_best_test",
preset_dict=single_song_best_format_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=f"plugins/test_audio_extract_single_best{'_dry_run' if dry_run else ''}.txt",
)
assert_expected_downloads(
output_directory=output_directory,
dry_run=dry_run,
expected_download_summary_file_name=f"plugins/test_audio_extract_single_best{'_dry_run' if dry_run else ''}.json",
)
@pytest.mark.parametrize("dry_run", [True, False])
def test_audio_extract_multiple_songs(
self,

View file

@ -1,7 +1,7 @@
import shutil
from pathlib import Path
REGENERATE_FIXTURES: bool = False
REGENERATE_FIXTURES: bool = True
RESOURCE_PATH: Path = Path("tests") / "resources"
_FILE_FIXTURE_PATH: Path = RESOURCE_PATH / "file_fixtures"

View file

@ -0,0 +1,5 @@
{
".ytdl-sub-single_song_best_test-download-archive.json": "f179ccfe0a9b3a76ae62122a3ccb58fd",
"YouTube/[2019] YouTube Rewind 2019 For the Record #YouTubeRewind/01 - YouTube Rewind 2019 For the Record #YouTubeRewind.m4a": "4b03133e9422a9ce196d271beb15ceef",
"YouTube/[2019] YouTube Rewind 2019 For the Record #YouTubeRewind/folder.jpg": "50ee47c80f679029f5d3503bb91b045a"
}

View file

@ -0,0 +1,22 @@
Files created:
----------------------------------------
{output_directory}
.ytdl-sub-single_song_best_test-download-archive.json
{output_directory}/YouTube/[2019] YouTube Rewind 2019 For the Record #YouTubeRewind
01 - YouTube Rewind 2019 For the Record #YouTubeRewind.m4a
Music Tags:
album: YouTube Rewind 2019: For the Record | #YouTubeRewind
albumartist: YouTube
albumartists: YouTube
artist: YouTube
artists: YouTube
genre: Unset
genres:
- multi_tag_1
- multi_tag_2
title: YouTube Rewind 2019: For the Record | #YouTubeRewind
track: 1
tracktotal: 1
year: 2019
Embedded thumbnail
folder.jpg

View file

@ -0,0 +1,23 @@
Files created:
----------------------------------------
{output_directory}
.ytdl-sub-single_song_best_test-download-archive.json
{output_directory}/YouTube/[2019] YouTube Rewind 2019 For the Record #YouTubeRewind
01 - YouTube Rewind 2019 For the Record #YouTubeRewind.m4a
Caution: extracted audio with 'best' format is not known during dry-run. Defaulting to m4a.
Music Tags:
album: YouTube Rewind 2019: For the Record | #YouTubeRewind
albumartist: YouTube
albumartists: YouTube
artist: YouTube
artists: YouTube
genre: Unset
genres:
- multi_tag_1
- multi_tag_2
title: YouTube Rewind 2019: For the Record | #YouTubeRewind
track: 1
tracktotal: 1
year: 2019
Embedded thumbnail
folder.jpg