Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Epidemic Sound] Add new extractor #32628

Merged
merged 7 commits into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions youtube_dl/extractor/epidemicsound.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# coding: utf-8
from __future__ import unicode_literals

from .common import InfoExtractor
from ..utils import (
ExtractorError,
float_or_none,
txt_or_none,
unified_timestamp,
url_or_none,
traverse_obj,
str_or_none,
T,
)


class EpidemicSoundIE(InfoExtractor):
_VALID_URL = r'https?://(?:www\.)?epidemicsound\.com/track/(?P<id>[0-9a-zA-Z]+)'
_TESTS = [{
'url': 'https://www.epidemicsound.com/track/yFfQVRpSPz/',
'md5': 'd98ff2ddb49e8acab9716541cbc9dfac',
'info_dict': {
'id': 'yFfQVRpSPz',
'ext': 'mp3',
'tags': ['foley', 'door', 'knock', 'glass', 'window', 'glass door knock'],
'title': 'Door Knock Door 1',
'duration': 1,
'thumbnail': 'https://cdn.epidemicsound.com/curation-assets/commercial-release-cover-images/default-sfx/3000x3000.jpg',
'timestamp': 1415320353,
'upload_date': '20141107',
},
}, {
'url': 'https://www.epidemicsound.com/track/mj8GTTwsZd/',
'md5': 'c82b745890f9baf18dc2f8d568ee3830',
realRobotix marked this conversation as resolved.
Show resolved Hide resolved
'info_dict': {
'id': 'mj8GTTwsZd',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now you prompted me to look at the JSON!

Should id be the id from the JSON? If so return the video_id as display_id.

Also:

  • isExplicit could be used to set age_limit
  • releaseDate could be used to set release_timestamp
  • genres could be used to set categories
  • cover could be a fallback for imageUrl.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why a user would want the id of the json. I'd just leave it out for now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ID is meant to be a unique value that specifies the video (1-1 mapping). We can't really tell if the slug in the URL is going to be unique, but the numeric ID in the JSON looks like an internal index that ought to be unique. Putting the slug as display_id is consistent with the way other extractors work.

Here's another thing, though. Will people normally want the full version only, or the whole set of instrumental tracks? If the latter, the extractor should return all the formats as a playlist, and then the user would have to use --no-playlist to force the current behaviour. Or with the current behaviour, you can get multiple formats with comma-separated formats, like -f "full,drums", but the user has to list the formats explicitly as there's no -f all.

'ext': 'mp3',
'tags': ['liquid drum n bass', 'energetic'],
'title': 'Noplace',
'duration': 237,
'thumbnail': 'https://cdn.epidemicsound.com/curation-assets/commercial-release-cover-images/11138/3000x3000.jpg',
'timestamp': 1694426482,
'upload_date': '20230911',
realRobotix marked this conversation as resolved.
Show resolved Hide resolved
},
}]

def _real_extract(self, url):
video_id = self._match_id(url)
json_data = self._download_json('https://www.epidemicsound.com/json/track/' + video_id, video_id)

if not traverse_obj(json_data, ('stems', Ellipsis)):
raise ExtractorError('No downloadable content found')

formats = list(reversed([
{
'format_id': str_or_none(key),
'url': url_or_none(value.get('lqMp3Url'))
} for key, value in json_data.get('stems').items()
]))

for f in formats:
for key, value in f.items():
if value is None or key is None:
del f

if len(formats) == 0:
raise ExtractorError('No downloadable content found')
realRobotix marked this conversation as resolved.
Show resolved Hide resolved

info = traverse_obj(json_data, {
'tags': ('metadataTags', Ellipsis, T(txt_or_none)),
realRobotix marked this conversation as resolved.
Show resolved Hide resolved
'title': ('title', T(txt_or_none)),
'duration': ('length', T(float_or_none)),
'timestamp': ('added', T(unified_timestamp)),
'thumbnail': ('imageUrl', T(url_or_none))})
realRobotix marked this conversation as resolved.
Show resolved Hide resolved

info['id'] = video_id
info['formats'] = formats

if not info.get('tags'):
del info['tags']
realRobotix marked this conversation as resolved.
Show resolved Hide resolved

if not info.get('title'):
raise ExtractorError('No title found')

return info
1 change: 1 addition & 0 deletions youtube_dl/extractor/extractors.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@
from .elpais import ElPaisIE
from .embedly import EmbedlyIE
from .engadget import EngadgetIE
from .epidemicsound import EpidemicSoundIE
from .eporner import EpornerIE
from .eroprofile import EroProfileIE
from .escapist import EscapistIE
Expand Down