mirror of
https://github.com/glomatico/gamdl.git
synced 2026-06-13 20:25:13 +03:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 527dd9935a | |||
| 06d5c10725 | |||
| 58a8e3944d | |||
| 4c7e563d4c | |||
| f05dace5c1 | |||
| eb81728475 | |||
| 96c90e1716 | |||
| 7459d95df0 | |||
| b2521e2933 | |||
| f87bee7732 | |||
| 3aa36c1323 | |||
| 7c60b2cd31 | |||
| 68ff155a9e | |||
| 0d41ef0895 | |||
| 575f652813 | |||
| 11db7154a1 |
@@ -85,6 +85,7 @@ options:
|
||||
* 1080p AVC 10mbps / AAC 256kbps
|
||||
* 1080p AVC 6.5bps / AAC 256kbps
|
||||
* 720p AVC 4mbps / AAC 256kbps
|
||||
* 480p AVC 2mbps / AAC 256kbps
|
||||
* 480p AVC 1.5mbps / AAC 256kbps
|
||||
* 360p AVC 1mbps / AAC 256kbps
|
||||
|
||||
|
||||
+3
-5
@@ -3,7 +3,7 @@ import argparse
|
||||
import traceback
|
||||
from .gamdl import Gamdl
|
||||
|
||||
__version__ = '1.2'
|
||||
__version__ = '1.6'
|
||||
|
||||
|
||||
def main():
|
||||
@@ -124,7 +124,7 @@ def main():
|
||||
exit(1)
|
||||
except:
|
||||
error_count += 1
|
||||
print(f'* Failed to check URL {i + 1}.')
|
||||
print(f'Failed to check URL {i + 1}/{len(args.url)}')
|
||||
if args.print_exceptions:
|
||||
traceback.print_exc()
|
||||
for i, url in enumerate(download_queue):
|
||||
@@ -140,14 +140,12 @@ def main():
|
||||
final_location = dl.get_final_location('.m4v', tags)
|
||||
if dl.check_exists(final_location) and not args.overwrite:
|
||||
continue
|
||||
playlist = dl.get_playlist_music_video(webplayback)
|
||||
stream_url_audio = dl.get_stream_url_music_video_audio(playlist)
|
||||
stream_url_video, stream_url_audio = dl.get_stream_url_music_video(webplayback)
|
||||
decryption_keys_audio = dl.get_decryption_keys_music_video(stream_url_audio, track_id)
|
||||
encrypted_location_audio = dl.get_encrypted_location_audio(track_id)
|
||||
dl.download(encrypted_location_audio, stream_url_audio)
|
||||
decrypted_location_audio = dl.get_decrypted_location_audio(track_id)
|
||||
dl.decrypt(encrypted_location_audio, decrypted_location_audio, decryption_keys_audio)
|
||||
stream_url_video = dl.get_stream_url_music_video_video(playlist)
|
||||
decryption_keys_video = dl.get_decryption_keys_music_video(stream_url_video, track_id)
|
||||
encrypted_location_video = dl.get_encrypted_location_video(track_id)
|
||||
dl.download(encrypted_location_video, stream_url_video)
|
||||
|
||||
+33
-35
@@ -9,13 +9,10 @@ import functools
|
||||
import subprocess
|
||||
import shutil
|
||||
import gamdl.storefront_ids
|
||||
from pywidevine import Cdm
|
||||
from pywidevine import Device
|
||||
from pywidevine import Cdm, Device, PSSH, WidevinePsshData
|
||||
import requests
|
||||
import m3u8
|
||||
from yt_dlp import YoutubeDL
|
||||
from pywidevine.pssh import PSSH
|
||||
from pywidevine.license_protocol_pb2 import WidevinePsshData
|
||||
from mutagen.mp4 import MP4, MP4Cover
|
||||
|
||||
|
||||
@@ -90,23 +87,23 @@ class Gamdl:
|
||||
return response
|
||||
|
||||
|
||||
def get_playlist_music_video(self, webplayback):
|
||||
return m3u8.load(webplayback['hls-playlist-url'])
|
||||
|
||||
|
||||
def get_stream_url_song(self, webplayback):
|
||||
return next(i for i in webplayback["assets"] if i["flavor"] == "28:ctrp256")['URL']
|
||||
|
||||
|
||||
def get_stream_url_music_video_audio(self, playlist):
|
||||
return [i for i in playlist.media if i.type == "AUDIO"][-1].uri
|
||||
|
||||
|
||||
def get_stream_url_music_video_video(self, playlist):
|
||||
def get_stream_url_music_video(self, webplayback):
|
||||
with YoutubeDL({
|
||||
'allow_unplayable_formats': True,
|
||||
'quiet': True,
|
||||
'no_warnings': True,
|
||||
}) as ydl:
|
||||
playlist = ydl.extract_info(webplayback['hls-playlist-url'], download = False)
|
||||
if self.prefer_hevc:
|
||||
return playlist.playlists[-1].uri
|
||||
stream_url_video = playlist['formats'][-1]['url']
|
||||
else:
|
||||
return [i for i in playlist.playlists if 'avc' in i.stream_info.codecs][-1].uri
|
||||
stream_url_video = [i['url'] for i in playlist['formats'] if i['vcodec'] is not None and 'avc1' in i['vcodec']][-1]
|
||||
stream_url_audio = next(i['url'] for i in playlist['formats'] if 'audio-stereo-256' in i['format_id'])
|
||||
return stream_url_video, stream_url_audio
|
||||
|
||||
|
||||
def check_exists(self, final_location):
|
||||
@@ -193,25 +190,23 @@ class Gamdl:
|
||||
],
|
||||
check = True
|
||||
)
|
||||
|
||||
|
||||
|
||||
def get_synced_lyrics_formated_time(self, unformatted_time):
|
||||
if 's' in unformatted_time:
|
||||
unformatted_time = unformatted_time.replace('s', '')
|
||||
if '.' not in unformatted_time:
|
||||
unformatted_time += '.0'
|
||||
s = int(unformatted_time.split('.')[-2].split(':')[-1]) * 1000
|
||||
try:
|
||||
m = int(unformatted_time.split('.')[-2].split(':')[-2]) * 60000
|
||||
except:
|
||||
m = 0
|
||||
ms = f'{int(unformatted_time.split(".")[-1]):03d}'
|
||||
if int(ms[2]) >= 5:
|
||||
ms = int(f'{int(ms[:2]) + 1}') * 10
|
||||
else:
|
||||
ms = int(ms)
|
||||
formated_time = datetime.datetime.fromtimestamp((s + m + ms)/1000.0)
|
||||
return formated_time.strftime('%M:%S.%f')[:-4]
|
||||
unformatted_time = unformatted_time.replace('m', '').replace('s', '').replace(':', '.')
|
||||
unformatted_time = unformatted_time.split('.')
|
||||
m, s, ms = 0, 0, 0
|
||||
ms = int(unformatted_time[-1])
|
||||
if len(unformatted_time) >= 2:
|
||||
s = int(unformatted_time[-2]) * 1000
|
||||
if len(unformatted_time) >= 3:
|
||||
m = int(unformatted_time[-3]) * 60000
|
||||
unformatted_time = datetime.datetime.fromtimestamp((ms + s + m)/1000.0)
|
||||
ms_new = f'{int(str(unformatted_time.microsecond)[:3]):03d}'
|
||||
if int(ms_new[2]) >= 5:
|
||||
ms = int(f'{int(ms_new[:2]) + 1}') * 10
|
||||
unformatted_time += datetime.timedelta(milliseconds=ms) - datetime.timedelta(microseconds=unformatted_time.microsecond)
|
||||
return unformatted_time.strftime('%M:%S.%f')[:-4]
|
||||
|
||||
|
||||
def get_lyrics(self, track_id):
|
||||
@@ -279,13 +274,12 @@ class Gamdl:
|
||||
|
||||
|
||||
def get_tags_music_video(self, track_id):
|
||||
metadata = requests.get(f'https://itunes.apple.com/lookup?id={track_id}&entity=album&limit=200&country={self.country}&lang=en_US').json()['results']
|
||||
metadata = requests.get(f'https://itunes.apple.com/lookup?id={track_id}&entity=album&country={self.country}&lang=en_US').json()['results']
|
||||
extra_metadata = requests.get(f'https://music.apple.com/music-video/{metadata[0]["trackId"]}', headers = {'X-Apple-Store-Front': f'{self.storefront} t:music31'}).json()['storePlatformData']['product-dv']['results'][str(metadata[0]['trackId'])]
|
||||
tags = {
|
||||
'\xa9ART': [metadata[0]["artistName"]],
|
||||
'\xa9nam': [metadata[0]["trackCensoredName"]],
|
||||
'\xa9day': [metadata[0]["releaseDate"]],
|
||||
'cprt': [extra_metadata['copyright']],
|
||||
'\xa9gen': [metadata[0]['primaryGenreName']],
|
||||
'stik': [6],
|
||||
'atID': [metadata[0]['artistId']],
|
||||
@@ -294,6 +288,8 @@ class Gamdl:
|
||||
'sfID': [int(self.storefront.split('-')[0])],
|
||||
'covr': [MP4Cover(self.get_cover(metadata[0]["artworkUrl30"].replace('30x30bb.jpg', '600x600bb.jpg')), MP4Cover.FORMAT_JPEG)]
|
||||
}
|
||||
if 'copyright' in extra_metadata:
|
||||
tags['cprt'] = [extra_metadata['copyright']]
|
||||
if metadata[0]['trackExplicitness'] == 'notExplicit':
|
||||
tags['rtng'] = [0]
|
||||
elif metadata[0]['trackExplicitness'] == 'explicit':
|
||||
@@ -346,7 +342,7 @@ class Gamdl:
|
||||
final_location /= f'{self.get_sanizated_string(tags["©ART"][0], True)}/Unknown Album/'
|
||||
final_location /= f'{file_name}{file_extension}'
|
||||
try:
|
||||
if file_extension == '.m4v' and final_location.exists() and MP4(final_location).tags['cnID'][0] != tags['cnID'][0]:
|
||||
if file_extension == '.m4v' and final_location.exists() and MP4(final_location)['cnID'][0] != tags['cnID'][0]:
|
||||
final_location = self.get_final_location_overwrite_prevented_music_video(final_location)
|
||||
except:
|
||||
pass
|
||||
@@ -364,6 +360,7 @@ class Gamdl:
|
||||
decrypted_location_video,
|
||||
'-itags',
|
||||
'artist=placeholder',
|
||||
'-new',
|
||||
fixed_location
|
||||
],
|
||||
check = True
|
||||
@@ -379,6 +376,7 @@ class Gamdl:
|
||||
decrypted_location,
|
||||
'-itags',
|
||||
'artist=placeholder',
|
||||
'-new',
|
||||
fixed_location
|
||||
],
|
||||
check = True
|
||||
|
||||
Reference in New Issue
Block a user