| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 | # coding: utf-8from __future__ import unicode_literalsimport refrom .srgssr import SRGSSRIEfrom ..compat import compat_strfrom ..utils import (    int_or_none,    parse_duration,    parse_iso8601,    unescapeHTML,    determine_ext,)class RTSIE(SRGSSRIE):    IE_DESC = 'RTS.ch'    _VALID_URL = r'rts:(?P<rts_id>\d+)|https?://(?:.+?\.)?rts\.ch/(?:[^/]+/){2,}(?P<id>[0-9]+)-(?P<display_id>.+?)\.html'    _TESTS = [        {            'url': 'http://www.rts.ch/archives/tv/divers/3449373-les-enfants-terribles.html',            'md5': 'ff7f8450a90cf58dacb64e29707b4a8e',            'info_dict': {                'id': '3449373',                'display_id': 'les-enfants-terribles',                'ext': 'mp4',                'duration': 1488,                'title': 'Les Enfants Terribles',                'description': 'France Pommier et sa soeur Luce Feral, les deux filles de ce groupe de 5.',                'uploader': 'Divers',                'upload_date': '19680921',                'timestamp': -40280400,                'thumbnail': 're:^https?://.*\.image',                'view_count': int,            },        },        {            'url': 'http://www.rts.ch/emissions/passe-moi-les-jumelles/5624067-entre-ciel-et-mer.html',            'info_dict': {                'id': '5624065',                'title': 'Passe-moi les jumelles',            },            'playlist_mincount': 4,        },        {            'url': 'http://www.rts.ch/video/sport/hockey/5745975-1-2-kloten-fribourg-5-2-second-but-pour-gotteron-par-kwiatowski.html',            'info_dict': {                'id': '5745975',                'display_id': '1-2-kloten-fribourg-5-2-second-but-pour-gotteron-par-kwiatowski',                'ext': 'mp4',                'duration': 48,                'title': '1/2, Kloten - Fribourg (5-2): second but pour Gottéron par Kwiatowski',                'description': 'Hockey - Playoff',                'uploader': 'Hockey',                'upload_date': '20140403',                'timestamp': 1396556882,                'thumbnail': 're:^https?://.*\.image',                'view_count': int,            },            'params': {                # m3u8 download                'skip_download': True,            },            'skip': 'Blocked outside Switzerland',        },        {            'url': 'http://www.rts.ch/video/info/journal-continu/5745356-londres-cachee-par-un-epais-smog.html',            'md5': '1bae984fe7b1f78e94abc74e802ed99f',            'info_dict': {                'id': '5745356',                'display_id': 'londres-cachee-par-un-epais-smog',                'ext': 'mp4',                'duration': 33,                'title': 'Londres cachée par un épais smog',                'description': 'Un important voile de smog recouvre Londres depuis mercredi, provoqué par la pollution et du sable du Sahara.',                'uploader': 'L\'actu en vidéo',                'upload_date': '20140403',                'timestamp': 1396537322,                'thumbnail': 're:^https?://.*\.image',                'view_count': int,            },        },        {            'url': 'http://www.rts.ch/audio/couleur3/programmes/la-belle-video-de-stephane-laurenceau/5706148-urban-hippie-de-damien-krisl-03-04-2014.html',            'md5': 'dd8ef6a22dff163d063e2a52bc8adcae',            'info_dict': {                'id': '5706148',                'display_id': 'urban-hippie-de-damien-krisl-03-04-2014',                'ext': 'mp3',                'duration': 123,                'title': '"Urban Hippie", de Damien Krisl',                'description': 'Des Hippies super glam.',                'upload_date': '20140403',                'timestamp': 1396551600,            },        },        {            # article with videos on rhs            'url': 'http://www.rts.ch/sport/hockey/6693917-hockey-davos-decroche-son-31e-titre-de-champion-de-suisse.html',            'info_dict': {                'id': '6693917',                'title': 'Hockey: Davos décroche son 31e titre de champion de Suisse',            },            'playlist_mincount': 5,        },        {            'url': 'http://pages.rts.ch/emissions/passe-moi-les-jumelles/5624065-entre-ciel-et-mer.html',            'only_matching': True,        }    ]    def _real_extract(self, url):        m = re.match(self._VALID_URL, url)        media_id = m.group('rts_id') or m.group('id')        display_id = m.group('display_id') or media_id        def download_json(internal_id):            return self._download_json(                'http://www.rts.ch/a/%s.html?f=json/article' % internal_id,                display_id)        all_info = download_json(media_id)        # media_id extracted out of URL is not always a real id        if 'video' not in all_info and 'audio' not in all_info:            entries = []            for item in all_info.get('items', []):                item_url = item.get('url')                if not item_url:                    continue                entries.append(self.url_result(item_url, 'RTS'))            if not entries:                page, urlh = self._download_webpage_handle(url, display_id)                if re.match(self._VALID_URL, urlh.geturl()).group('id') != media_id:                    return self.url_result(urlh.geturl(), 'RTS')                # article with videos on rhs                videos = re.findall(                    r'<article[^>]+class="content-item"[^>]*>\s*<a[^>]+data-video-urn="urn:([^"]+)"',                    page)                if not videos:                    videos = re.findall(                        r'(?s)<iframe[^>]+class="srg-player"[^>]+src="[^"]+urn:([^"]+)"',                        page)                if videos:                    entries = [self.url_result('srgssr:%s' % video_urn, 'SRGSSR') for video_urn in videos]            if entries:                return self.playlist_result(entries, media_id, all_info.get('title'))            internal_id = self._html_search_regex(                r'<(?:video|audio) data-id="([0-9]+)"', page,                'internal video id')            all_info = download_json(internal_id)        media_type = 'video' if 'video' in all_info else 'audio'        # check for errors        self.get_media_data('rts', media_type, media_id)        info = all_info['video']['JSONinfo'] if 'video' in all_info else all_info['audio']        title = info['title']        def extract_bitrate(url):            return int_or_none(self._search_regex(                r'-([0-9]+)k\.', url, 'bitrate', default=None))        formats = []        streams = info.get('streams', {})        for format_id, format_url in streams.items():            if format_id == 'hds_sd' and 'hds' in streams:                continue            if format_id == 'hls_sd' and 'hls' in streams:                continue            ext = determine_ext(format_url)            if ext in ('m3u8', 'f4m'):                format_url = self._get_tokenized_src(format_url, media_id, format_id)                if ext == 'f4m':                    formats.extend(self._extract_f4m_formats(                        format_url + ('?' if '?' not in format_url else '&') + 'hdcore=3.4.0',                        media_id, f4m_id=format_id, fatal=False))                else:                    formats.extend(self._extract_m3u8_formats(                        format_url, media_id, 'mp4', 'm3u8_native', m3u8_id=format_id, fatal=False))            else:                formats.append({                    'format_id': format_id,                    'url': format_url,                    'tbr': extract_bitrate(format_url),                })        for media in info.get('media', []):            media_url = media.get('url')            if not media_url or re.match(r'https?://', media_url):                continue            rate = media.get('rate')            ext = media.get('ext') or determine_ext(media_url, 'mp4')            format_id = ext            if rate:                format_id += '-%dk' % rate            formats.append({                'format_id': format_id,                'url': 'http://download-video.rts.ch/' + media_url,                'tbr': rate or extract_bitrate(media_url),            })        self._check_formats(formats, media_id)        self._sort_formats(formats)        duration = info.get('duration') or info.get('cutout') or info.get('cutduration')        if isinstance(duration, compat_str):            duration = parse_duration(duration)        return {            'id': media_id,            'display_id': display_id,            'formats': formats,            'title': title,            'description': info.get('intro'),            'duration': duration,            'view_count': int_or_none(info.get('plays')),            'uploader': info.get('programName'),            'timestamp': parse_iso8601(info.get('broadcast_date')),            'thumbnail': unescapeHTML(info.get('preview_image_url')),        }
 |