* set proper extension for `HI_RES_LOSSLESS` tracks

* add `convertFileExtension` function

* convert `HI_RES_LOSSLESS` tracks to .flac
This commit is contained in:
Oskar Dudziński
2025-01-30 23:12:51 +01:00
committed by GitHub
parent dc040ab170
commit 75a2d06e35
3 changed files with 53 additions and 2 deletions
+13 -1
View File
@@ -10,7 +10,12 @@ from ..ctx import Context, passContext
from typing import List, Union, Literal
from tiddl.download import downloadTrackStream
from tiddl.utils import formatTrack, trackExists, TidalResource
from tiddl.utils import (
formatTrack,
trackExists,
TidalResource,
convertFileExtension,
)
from tiddl.metadata import addMetadata, Cover
from tiddl.exceptions import ApiError, AuthError
from tiddl.models.constants import TrackArg, ARG_TO_QUALITY
@@ -92,6 +97,13 @@ def DownloadCommand(
with full_path.open("wb") as f:
f.write(stream_data)
# extract flac from m4a container
if track_stream.audioQuality == "HI_RES_LOSSLESS":
full_path = convertFileExtension(
full_path, ".flac", remove_source=True
)
# TODO: add track credits fetching to fill more metadata
if not cover_data and track.album.cover:
+2
View File
@@ -76,6 +76,8 @@ def downloadTrackStream(stream: TrackStream) -> tuple[bytes, str]:
if codecs == "flac":
file_extension = ".flac"
if stream.audioQuality == "HI_RES_LOSSLESS":
file_extension = ".m4a"
elif codecs.startswith("mp4"):
file_extension = ".m4a"
else:
+38 -1
View File
@@ -1,4 +1,7 @@
import re
import os
import ffmpeg
import logging
from pydantic import BaseModel
from urllib.parse import urlparse
@@ -51,7 +54,11 @@ def sanitizeString(string: str) -> str:
def formatTrack(
template: str, track: Track, album_artist="", playlist_title="", playlist_index=0
template: str,
track: Track,
album_artist="",
playlist_title="",
playlist_index=0,
) -> str:
artist = sanitizeString(track.artist.name) if track.artist else ""
features = [
@@ -110,3 +117,33 @@ def trackExists(
full_file_name = file_name.with_suffix(extension)
return full_file_name.exists()
def convertFileExtension(
source_file: Path, extension: str, remove_source=False
) -> Path:
"""
Converts `source_file` extension and returns `Path` of file with new `extension`.
Removes `source_file` when `remove_source` is truthy.
"""
try:
output_file = source_file.with_suffix(extension)
except ValueError as e:
logging.error(e)
return source_file
logging.debug((source_file, output_file, extension))
if extension == source_file.suffix:
return source_file
ffmpeg.input(str(source_file)).output(
str(output_file), **{"c:a": "copy", "loglevel": "error"}
).run(overwrite_output=1)
if remove_source:
os.remove(source_file)
return output_file