1 from .common
import InfoExtractor
9 from ..utils
.traversal
import traverse_obj
12 class SBSCoKrIE(InfoExtractor
):
14 _VALID_URL
= [r
'https?://allvod\.sbs\.co\.kr/allvod/vod(?:Package)?EndPage\.do\?(?:[^#]+&)?mdaId=(?P<id>\d+)',
15 r
'https?://programs\.sbs\.co\.kr/(?:enter|drama|culture|sports|plus|mtv|kth)/[a-z0-9]+/(?:vod|clip|movie)/\d+/(?P<id>(?:OC)?\d+)']
18 'url': 'https://programs.sbs.co.kr/enter/dongsang2/clip/52007/OC467706746?div=main_pop_clip',
19 'md5': 'c3f6d45e1fb5682039d94cda23c36f19',
23 'title': '‘아슬아슬’ 박군♥한영의 새 집 인테리어 대첩♨',
24 'description': 'md5:6a71eb1979ee4a94ea380310068ccab4',
25 'thumbnail': 'https://img2.sbs.co.kr/ops_clip_img/2023/10/10/34c4c0f9-a9a5-4ff6-a92e-9bb4b5f6fa65915w1280.jpg',
26 'release_timestamp': 1696889400,
27 'release_date': '20231009',
32 'series': '동상이몽2_너는 내 운명',
33 'episode': '레이디제인, ‘혼전임신설’ ‘3개월’ 앞당긴 결혼식 비하인드 스토리 최초 공개!',
34 'episode_number': 311,
37 'url': 'https://allvod.sbs.co.kr/allvod/vodPackageEndPage.do?mdaId=22000489324&combiId=PA000000284&packageType=A&isFreeYN=',
38 'md5': 'bf46b2e89fda7ae7de01f5743cef7236',
42 'title': '[다시보기] 트롤리 15회',
43 'description': 'md5:0e55d74bef1ac55c61ae90c73ac485f4',
44 'thumbnail': 'https://img2.sbs.co.kr/img/sbs_cms/WE/2023/02/14/arC1676333794938-1280-720.jpg',
45 'release_timestamp': 1676325600,
46 'release_date': '20230213',
52 'episode': '이거 다 거짓말이야',
56 'url': 'https://programs.sbs.co.kr/enter/fourman/vod/69625/22000508948',
57 'md5': '41e8ae4cc6c8424f4e4d76661a4becbf',
61 'title': '[다시보기] 신발 벗고 돌싱포맨 104회',
62 'description': 'md5:c6a247383c4dd661e4b956bf4d3b586e',
63 'thumbnail': 'https://img2.sbs.co.kr/img/sbs_cms/WE/2023/08/30/2vb1693355446261-1280-720.jpg',
64 'release_timestamp': 1693342800,
65 'release_date': '20230829',
70 'series': '신발 벗고 돌싱포맨',
71 'episode': '돌싱포맨 저격수들 등장!',
72 'episode_number': 104,
76 def _call_api(self
, video_id
, rscuse
=''):
77 return self
._download
_json
(
78 f
'https://api.play.sbs.co.kr/1.0/sbs_vodall/{video_id}', video_id
,
79 note
=f
'Downloading m3u8 information {rscuse}',
82 'protocol': 'download',
89 def _real_extract(self
, url
):
90 video_id
= self
._match
_id
(url
)
92 details
= self
._call
_api
(video_id
)
93 source
= traverse_obj(details
, ('vod', 'source', 'mediasource', {dict}
)) or {}
96 for stream
in traverse_obj(details
, (
97 'vod', 'source', 'mediasourcelist', lambda _
, v
: v
['mediaurl'] or v
['mediarscuse'],
99 if not stream
.get('mediaurl'):
100 new_source
= traverse_obj(
101 self
._call
_api
(video_id
, rscuse
=stream
['mediarscuse']),
102 ('vod', 'source', 'mediasource', {dict}
)) or {}
103 if new_source
.get('mediarscuse') == source
.get('mediarscuse') or not new_source
.get('mediaurl'):
107 'url': stream
['mediaurl'],
108 'format_id': stream
.get('mediarscuse'),
109 'format_note': stream
.get('medianame'),
110 **parse_resolution(stream
.get('quality')),
111 'preference': int_or_none(stream
.get('mediarscuse')),
114 caption_url
= traverse_obj(details
, ('vod', 'source', 'subtitle', {url_or_none}
))
118 **traverse_obj(details
, ('vod', {
119 'title': ('info', 'title'),
120 'duration': ('info', 'duration', {int_or_none}
),
121 'view_count': ('info', 'viewcount', {int_or_none}
),
122 'like_count': ('info', 'likecount', {int_or_none}
),
123 'description': ('info', 'synopsis', {clean_html}
),
124 'episode': ('info', 'content', ('contenttitle', 'title')),
125 'episode_number': ('info', 'content', 'number', {int_or_none}
),
126 'series': ('info', 'program', 'programtitle'),
127 'age_limit': ('info', 'targetage', {int_or_none}
),
128 'release_timestamp': ('info', 'broaddate', {parse_iso8601}
),
129 'thumbnail': ('source', 'thumbnail', 'origin', {url_or_none}
),
132 'subtitles': {'ko': [{'url': caption_url
}]} if caption_url
else None,
136 class SBSCoKrAllvodProgramIE(InfoExtractor
):
137 IE_NAME
= 'sbs.co.kr:allvod_program'
138 _VALID_URL
= r
'https?://allvod\.sbs\.co\.kr/allvod/vod(?:Free)?ProgramDetail\.do\?(?:[^#]+&)?pgmId=(?P<id>P?\d+)'
141 'url': 'https://allvod.sbs.co.kr/allvod/vodFreeProgramDetail.do?type=legend&pgmId=22000010159&listOrder=vodCntAsc',
146 'playlist_count': 18,
148 'url': 'https://allvod.sbs.co.kr/allvod/vodProgramDetail.do?pgmId=P460810577',
153 'playlist_count': 13,
156 def _real_extract(self
, url
):
157 program_id
= self
._match
_id
(url
)
159 details
= self
._download
_json
(
160 'https://allvod.sbs.co.kr/allvod/vodProgramDetail/vodProgramDetailAjax.do',
161 program_id
, note
='Downloading program details',
164 'currentCount': '10000',
167 return self
.playlist_result(
168 [self
.url_result(f
'https://allvod.sbs.co.kr/allvod/vodEndPage.do?mdaId={video_id}', SBSCoKrIE
)
169 for video_id
in traverse_obj(details
, ('list', ..., 'mdaId'))], program_id
)
172 class SBSCoKrProgramsVodIE(InfoExtractor
):
173 IE_NAME
= 'sbs.co.kr:programs_vod'
174 _VALID_URL
= r
'https?://programs\.sbs\.co\.kr/(?:enter|drama|culture|sports|plus|mtv)/(?P<id>[a-z0-9]+)/vods'
177 'url': 'https://programs.sbs.co.kr/culture/morningwide/vods/65007',
182 'playlist_mincount': 9782,
184 'url': 'https://programs.sbs.co.kr/enter/dongsang2/vods/52006',
189 'playlist_mincount': 312,
192 def _real_extract(self
, url
):
193 program_slug
= self
._match
_id
(url
)
195 program_id
= self
._download
_json
(
196 f
'https://static.apis.sbs.co.kr/program-api/1.0/menu/{program_slug}', program_slug
,
197 note
='Downloading program menu data')['program']['programid']
199 return self
.url_result(
200 f
'https://allvod.sbs.co.kr/allvod/vodProgramDetail.do?pgmId={program_id}', SBSCoKrAllvodProgramIE
)