def METHOD_NAME(self, url):
    mobj = self._match_valid_url(url)
    kind, video_id = mobj.group('kind', 'id')
    webpage = self._download_webpage(url, video_id)
    player_config = self._parse_json(
        self._search_regex(
            r'data-player-conf=(["\'])(?P<data>{.+?})\1', webpage,
            'player config', default='{}', group='data'),
        video_id, transform_source=unescapeHTML, fatal=False)
    if not player_config:
        player_config = self._parse_json(
            self._search_regex(
                r'playerConf\s*=\s*({.+?})\s*;', webpage, 'player config',
                default='{}'),
            video_id, transform_source=js_to_json, fatal=False) or {}
    source = player_config.get('source') or {}
    video_id = compat_str(source.get('videoId') or video_id)
    devapi = self._download_json(
        'http://api.watchbox.de/devapi/id/%s' % video_id, video_id, query={
            'format': 'json',
            'apikey': 'hbbtv',
        }, fatal=False)
    item = try_get(devapi, lambda x: x['items'][0], dict) or {}
    title = item.get('title') or try_get(
        item, lambda x: x['movie']['headline_movie'],
        compat_str) or source['title']
    formats = []
    hls_url = item.get('media_videourl_hls') or source.get('hls')
    if hls_url:
        formats.extend(self._extract_m3u8_formats(
            hls_url, video_id, 'mp4', entry_protocol='m3u8_native',
            m3u8_id='hls', fatal=False))
    dash_url = item.get('media_videourl_wv') or source.get('dash')
    if dash_url:
        formats.extend(self._extract_mpd_formats(
            dash_url, video_id, mpd_id='dash', fatal=False))
    mp4_url = item.get('media_videourl')
    if mp4_url:
        formats.append({
            'url': mp4_url,
            'format_id': 'mp4',
            'width': int_or_none(item.get('width')),
            'height': int_or_none(item.get('height')),
            'tbr': int_or_none(item.get('bitrate')),
        })
    description = strip_or_none(item.get('descr'))
    thumbnail = item.get('media_content_thumbnail_large') or source.get('poster') or item.get('media_thumbnail')
    duration = int_or_none(item.get('media_length') or source.get('length'))
    timestamp = unified_timestamp(item.get('pubDate'))
    view_count = int_or_none(item.get('media_views'))
    age_limit = int_or_none(try_get(item, lambda x: x['movie']['fsk']))
    release_year = int_or_none(try_get(item, lambda x: x['movie']['rel_year']))
    info = {
        'id': video_id,
        'title': title,
        'description': description,
        'thumbnail': thumbnail,
        'duration': duration,
        'timestamp': timestamp,
        'view_count': view_count,
        'age_limit': age_limit,
        'release_year': release_year,
        'formats': formats,
    }
    if kind.lower() == 'serien':
        series = try_get(
            item, lambda x: x['special']['title'],
            compat_str) or source.get('format')
        season_number = int_or_none(self._search_regex(
            r'^S(\d{1,2})\s*E\d{1,2}', title, 'season number',
            default=None) or self._search_regex(
                r'/staffel-(\d+)/', url, 'season number', default=None))
        episode = source.get('title')
        episode_number = int_or_none(self._search_regex(
            r'^S\d{1,2}\s*E(\d{1,2})', title, 'episode number',
            default=None))
        info.update({
            'series': series,
            'season_number': season_number,
            'episode': episode,
            'episode_number': episode_number,
        })
    return info