improve m3u format
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -17,3 +17,4 @@ callback.log
|
|||||||
.gitignore
|
.gitignore
|
||||||
deezspot_test.log
|
deezspot_test.log
|
||||||
spotify_downloads
|
spotify_downloads
|
||||||
|
deezer_spo_downloads
|
||||||
|
|||||||
@@ -1223,7 +1223,7 @@ class DW_PLAYLIST:
|
|||||||
if current_track_object:
|
if current_track_object:
|
||||||
tracks.append(current_track_object)
|
tracks.append(current_track_object)
|
||||||
if current_track_object.success and hasattr(current_track_object, 'song_path') and current_track_object.song_path:
|
if current_track_object.success and hasattr(current_track_object, 'song_path') and current_track_object.song_path:
|
||||||
append_track_to_m3u(m3u_path, current_track_object.song_path)
|
append_track_to_m3u(m3u_path, current_track_object)
|
||||||
|
|
||||||
if self.__make_zip:
|
if self.__make_zip:
|
||||||
zip_name = f"{self.__output_dir}/{playlist_obj.title} [playlist {self.__ids}]"
|
zip_name = f"{self.__output_dir}/{playlist_obj.title} [playlist {self.__ids}]"
|
||||||
|
|||||||
@@ -32,14 +32,73 @@ def create_m3u_file(output_dir: str, playlist_name: str) -> str:
|
|||||||
return m3u_path
|
return m3u_path
|
||||||
|
|
||||||
|
|
||||||
def append_track_to_m3u(m3u_path: str, track_path: str) -> None:
|
def _get_track_duration_seconds(track: Track) -> int:
|
||||||
"""
|
"""
|
||||||
Appends a single track path to an existing m3u file.
|
Extract track duration in seconds from track metadata.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
track: Track object
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: Duration in seconds, defaults to 0 if not available
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Try to get duration from tags first
|
||||||
|
if hasattr(track, 'tags') and track.tags:
|
||||||
|
if 'duration' in track.tags:
|
||||||
|
return int(float(track.tags['duration']))
|
||||||
|
elif 'length' in track.tags:
|
||||||
|
return int(float(track.tags['length']))
|
||||||
|
|
||||||
|
# Try to get from song_metadata if available
|
||||||
|
if hasattr(track, 'song_metadata') and hasattr(track.song_metadata, 'duration_ms'):
|
||||||
|
return int(track.song_metadata.duration_ms / 1000)
|
||||||
|
|
||||||
|
# Fallback to 0 if no duration found
|
||||||
|
return 0
|
||||||
|
except (ValueError, AttributeError, TypeError):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def _get_track_info(track: Track) -> tuple:
|
||||||
|
"""
|
||||||
|
Extract artist and title information from track.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
track: Track object
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple: (artist, title) strings
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if hasattr(track, 'tags') and track.tags:
|
||||||
|
artist = track.tags.get('artist', 'Unknown Artist')
|
||||||
|
title = track.tags.get('music', track.tags.get('title', 'Unknown Title'))
|
||||||
|
return artist, title
|
||||||
|
elif hasattr(track, 'song_metadata'):
|
||||||
|
if hasattr(track.song_metadata, 'artists') and track.song_metadata.artists:
|
||||||
|
artist = ', '.join([a.name for a in track.song_metadata.artists])
|
||||||
|
else:
|
||||||
|
artist = 'Unknown Artist'
|
||||||
|
title = getattr(track.song_metadata, 'title', 'Unknown Title')
|
||||||
|
return artist, title
|
||||||
|
else:
|
||||||
|
return 'Unknown Artist', 'Unknown Title'
|
||||||
|
except (AttributeError, TypeError):
|
||||||
|
return 'Unknown Artist', 'Unknown Title'
|
||||||
|
|
||||||
|
|
||||||
|
def append_track_to_m3u(m3u_path: str, track: Union[str, Track]) -> None:
|
||||||
|
"""
|
||||||
|
Appends a single track to an existing m3u file with extended format.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
m3u_path: Full path to the m3u file
|
m3u_path: Full path to the m3u file
|
||||||
track_path: Full path to the track file
|
track: Track object or string path to track file
|
||||||
"""
|
"""
|
||||||
|
if isinstance(track, str):
|
||||||
|
# Legacy support for string paths
|
||||||
|
track_path = track
|
||||||
if not track_path or not os.path.exists(track_path):
|
if not track_path or not os.path.exists(track_path):
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -48,11 +107,30 @@ def append_track_to_m3u(m3u_path: str, track_path: str) -> None:
|
|||||||
|
|
||||||
with open(m3u_path, "a", encoding="utf-8") as m3u_file:
|
with open(m3u_path, "a", encoding="utf-8") as m3u_file:
|
||||||
m3u_file.write(f"{relative_path}\n")
|
m3u_file.write(f"{relative_path}\n")
|
||||||
|
else:
|
||||||
|
# Track object with full metadata
|
||||||
|
if (not isinstance(track, Track) or
|
||||||
|
not track.success or
|
||||||
|
not hasattr(track, 'song_path') or
|
||||||
|
not track.song_path or
|
||||||
|
not os.path.exists(track.song_path)):
|
||||||
|
return
|
||||||
|
|
||||||
|
playlist_m3u_dir = os.path.dirname(m3u_path)
|
||||||
|
relative_path = os.path.relpath(track.song_path, start=playlist_m3u_dir)
|
||||||
|
|
||||||
|
# Get track metadata
|
||||||
|
duration = _get_track_duration_seconds(track)
|
||||||
|
artist, title = _get_track_info(track)
|
||||||
|
|
||||||
|
with open(m3u_path, "a", encoding="utf-8") as m3u_file:
|
||||||
|
m3u_file.write(f"#EXTINF:{duration},{artist} - {title}\n")
|
||||||
|
m3u_file.write(f"{relative_path}\n")
|
||||||
|
|
||||||
|
|
||||||
def write_tracks_to_m3u(output_dir: str, playlist_name: str, tracks: List[Track]) -> str:
|
def write_tracks_to_m3u(output_dir: str, playlist_name: str, tracks: List[Track]) -> str:
|
||||||
"""
|
"""
|
||||||
Creates an m3u file and writes all successful tracks to it at once.
|
Creates an m3u file and writes all successful tracks to it at once using extended format.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
output_dir: Base output directory
|
output_dir: Base output directory
|
||||||
@@ -79,6 +157,13 @@ def write_tracks_to_m3u(output_dir: str, playlist_name: str, tracks: List[Track]
|
|||||||
os.path.exists(track.song_path)):
|
os.path.exists(track.song_path)):
|
||||||
|
|
||||||
relative_song_path = os.path.relpath(track.song_path, start=playlist_m3u_dir)
|
relative_song_path = os.path.relpath(track.song_path, start=playlist_m3u_dir)
|
||||||
|
|
||||||
|
# Get track metadata
|
||||||
|
duration = _get_track_duration_seconds(track)
|
||||||
|
artist, title = _get_track_info(track)
|
||||||
|
|
||||||
|
# Write EXTINF line with duration and metadata
|
||||||
|
m3u_file.write(f"#EXTINF:{duration},{artist} - {title}\n")
|
||||||
m3u_file.write(f"{relative_song_path}\n")
|
m3u_file.write(f"{relative_song_path}\n")
|
||||||
|
|
||||||
logger.info(f"Created m3u playlist file at: {m3u_path}")
|
logger.info(f"Created m3u playlist file at: {m3u_path}")
|
||||||
|
|||||||
@@ -1132,9 +1132,9 @@ class DW_PLAYLIST:
|
|||||||
if track:
|
if track:
|
||||||
tracks.append(track)
|
tracks.append(track)
|
||||||
|
|
||||||
# --- Append the final track path to the m3u file using a relative path ---
|
# --- Append the final track to the m3u file with extended format ---
|
||||||
if track and track.success and hasattr(track, 'song_path') and track.song_path:
|
if track and track.success and hasattr(track, 'song_path') and track.song_path:
|
||||||
append_track_to_m3u(m3u_path, track.song_path)
|
append_track_to_m3u(m3u_path, track)
|
||||||
# ---------------------------------------------------------------------
|
# ---------------------------------------------------------------------
|
||||||
|
|
||||||
if self.__make_zip:
|
if self.__make_zip:
|
||||||
|
|||||||
Reference in New Issue
Block a user