mirror of
https://github.com/soimort/you-get.git
synced 2025-01-23 21:45:02 +03:00
fix: soundcloud: HTTP Error 401: Unauthorized
feat: soundcloud download playlist
This commit is contained in:
parent
9b6c53d077
commit
5b9b0d878c
@ -1064,6 +1064,20 @@ def download_urls(
|
|||||||
for part in parts:
|
for part in parts:
|
||||||
os.remove(part)
|
os.remove(part)
|
||||||
|
|
||||||
|
elif ext == 'mp3':
|
||||||
|
try:
|
||||||
|
from .processor.ffmpeg import has_ffmpeg_installed
|
||||||
|
|
||||||
|
assert has_ffmpeg_installed()
|
||||||
|
from .processor.ffmpeg import ffmpeg_concat_mp3_to_mp3
|
||||||
|
ffmpeg_concat_mp3_to_mp3(parts, output_filepath)
|
||||||
|
print('Merged into %s' % output_filename)
|
||||||
|
except:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
for part in parts:
|
||||||
|
os.remove(part)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print("Can't merge %s files" % ext)
|
print("Can't merge %s files" % ext)
|
||||||
|
|
||||||
|
@ -1,44 +1,80 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
__all__ = ['soundcloud_download', 'soundcloud_download_by_id']
|
__all__ = ['sndcd_download']
|
||||||
|
|
||||||
from ..common import *
|
from ..common import *
|
||||||
|
import re
|
||||||
import json
|
import json
|
||||||
import urllib.error
|
import urllib.error
|
||||||
|
|
||||||
client_id = 'WKcQQdEZw7Oi01KqtHWxeVSxNyRzgT8M'
|
|
||||||
|
|
||||||
def soundcloud_download_by_id(id, title=None, output_dir='.', merge=True, info_only=False):
|
def get_sndcd_apikey():
|
||||||
assert title
|
home_page = get_content('https://soundcloud.com')
|
||||||
url = 'https://api.soundcloud.com/tracks/{}/{}?client_id={}'.format(id, 'stream', client_id)
|
js_url = re.findall(r'script crossorigin src="(.+?)"></script>', home_page)[-1]
|
||||||
|
|
||||||
type, ext, size = url_info(url)
|
client_id = get_content(js_url)
|
||||||
|
return re.search(r'client_id:"(.+?)"', client_id).group(1)
|
||||||
|
|
||||||
print_info(site_info, title, type, size)
|
|
||||||
|
def get_resource_info(resource_url, client_id):
|
||||||
|
cont = get_content(resource_url, decoded=True)
|
||||||
|
|
||||||
|
x = re.escape('forEach(function(e){n(e)})}catch(t){}})},')
|
||||||
|
x = re.search(r'' + x + r'(.*)\);</script>', cont)
|
||||||
|
|
||||||
|
info = json.loads(x.group(1))[-1]['data'][0]
|
||||||
|
|
||||||
|
info = info['tracks'] if info.get('track_count') else [info]
|
||||||
|
|
||||||
|
ids = [i['id'] for i in info if i.get('comment_count') is None]
|
||||||
|
ids = list(map(str, ids))
|
||||||
|
ids_split = ['%2C'.join(ids[i:i+10]) for i in range(0, len(ids), 10)]
|
||||||
|
api_url = 'https://api-v2.soundcloud.com/tracks?ids={ids}&client_id={client_id}&%5Bobject%20Object%5D=&app_version=1584348206&app_locale=en'
|
||||||
|
|
||||||
|
res = []
|
||||||
|
for ids in ids_split:
|
||||||
|
uri = api_url.format(ids=ids, client_id=client_id)
|
||||||
|
cont = get_content(uri, decoded=True)
|
||||||
|
res += json.loads(cont)
|
||||||
|
|
||||||
|
res = iter(res)
|
||||||
|
info = [next(res) if i.get('comment_count') is None else i for i in info]
|
||||||
|
|
||||||
|
return info
|
||||||
|
|
||||||
|
|
||||||
|
def sndcd_download(url, output_dir='.', merge=True, info_only=False, **kwargs):
|
||||||
|
client_id = get_sndcd_apikey()
|
||||||
|
|
||||||
|
r_info = get_resource_info(url, client_id)
|
||||||
|
|
||||||
|
for info in r_info:
|
||||||
|
title = info['title']
|
||||||
|
metadata = info.get('publisher_metadata')
|
||||||
|
|
||||||
|
transcodings = info['media']['transcodings']
|
||||||
|
sq = [i for i in transcodings if i['quality'] == 'sq']
|
||||||
|
hq = [i for i in transcodings if i['quality'] == 'hq']
|
||||||
|
# source url
|
||||||
|
surl = sq[0] if hq == [] else hq[0]
|
||||||
|
surl = surl['url']
|
||||||
|
|
||||||
|
uri = surl + '?client_id=' + client_id
|
||||||
|
r = get_content(uri)
|
||||||
|
surl = json.loads(r)['url']
|
||||||
|
|
||||||
|
m3u8 = get_content(surl)
|
||||||
|
# url list
|
||||||
|
urll = re.findall(r'http.*?(?=\n)', m3u8)
|
||||||
|
|
||||||
|
size = urls_size(urll)
|
||||||
|
print_info(site_info, title, 'audio/mpeg', size)
|
||||||
|
print(end='', flush=True)
|
||||||
|
|
||||||
if not info_only:
|
if not info_only:
|
||||||
download_urls([url], title, ext, size, output_dir, merge = merge)
|
download_urls(urll, title=title, ext='mp3', total_size=size, output_dir=output_dir, merge=True)
|
||||||
|
|
||||||
def soundcloud_i1_api(track_id):
|
|
||||||
url = 'https://api.soundcloud.com/i1/tracks/{}/streams?client_id={}'.format(track_id, client_id)
|
|
||||||
return json.loads(get_content(url))['http_mp3_128_url']
|
|
||||||
|
|
||||||
def soundcloud_download(url, output_dir='.', merge=True, info_only=False, **kwargs):
|
|
||||||
url = 'https://api.soundcloud.com/resolve.json?url={}&client_id={}'.format(url, client_id)
|
|
||||||
metadata = get_content(url)
|
|
||||||
info = json.loads(metadata)
|
|
||||||
title = info["title"]
|
|
||||||
real_url = info.get('download_url')
|
|
||||||
if real_url is None:
|
|
||||||
real_url = info.get('steram_url')
|
|
||||||
if real_url is None:
|
|
||||||
raise Exception('Cannot get media URI for {}'.format(url))
|
|
||||||
real_url = soundcloud_i1_api(info['id'])
|
|
||||||
mime, ext, size = url_info(real_url)
|
|
||||||
print_info(site_info, title, mime, size)
|
|
||||||
if not info_only:
|
|
||||||
download_urls([real_url], title, ext, size, output_dir, merge=merge)
|
|
||||||
|
|
||||||
site_info = "SoundCloud.com"
|
site_info = "SoundCloud.com"
|
||||||
download = soundcloud_download
|
download = sndcd_download
|
||||||
download_playlist = playlist_not_supported('soundcloud')
|
download_playlist = sndcd_download
|
||||||
|
@ -180,6 +180,18 @@ def ffmpeg_concat_flv_to_mp4(files, output='output.mp4'):
|
|||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
def ffmpeg_concat_mp3_to_mp3(files, output='output.mp3'):
|
||||||
|
print('Merging video parts... ', end="", flush=True)
|
||||||
|
|
||||||
|
files = 'concat:' + '|'.join(files)
|
||||||
|
|
||||||
|
params = [FFMPEG] + LOGLEVEL + ['-y']
|
||||||
|
params += ['-i', files, '-acodec', 'copy', output]
|
||||||
|
|
||||||
|
subprocess.call(params)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def ffmpeg_concat_mp4_to_mp4(files, output='output.mp4'):
|
def ffmpeg_concat_mp4_to_mp4(files, output='output.mp4'):
|
||||||
print('Merging video parts... ', end="", flush=True)
|
print('Merging video parts... ', end="", flush=True)
|
||||||
# Use concat demuxer on FFmpeg >= 1.1
|
# Use concat demuxer on FFmpeg >= 1.1
|
||||||
|
@ -8,7 +8,8 @@ from you_get.extractors import (
|
|||||||
youtube,
|
youtube,
|
||||||
missevan,
|
missevan,
|
||||||
acfun,
|
acfun,
|
||||||
bilibili
|
bilibili,
|
||||||
|
soundcloud
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -45,5 +46,16 @@ class YouGetTests(unittest.TestCase):
|
|||||||
bilibili.download(
|
bilibili.download(
|
||||||
"https://www.bilibili.com/watchlater/#/av74906671/p6", info_only=True
|
"https://www.bilibili.com/watchlater/#/av74906671/p6", info_only=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_soundcloud(self):
|
||||||
|
## single song
|
||||||
|
soundcloud.download(
|
||||||
|
'https://soundcloud.com/keiny-pham/impure-bird', info_only=True
|
||||||
|
)
|
||||||
|
## playlist
|
||||||
|
soundcloud.download(
|
||||||
|
'https://soundcloud.com/anthony-flieger/sets/cytus', info_only=True
|
||||||
|
)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
Loading…
Reference in New Issue
Block a user