youtube-dl

Another place where youtube-dl lives on
git clone git://git.oshgnacknak.de/youtube-dl.git
Log | Files | Refs | README | LICENSE

peertube.py (28591B)


      1 # coding: utf-8
      2 from __future__ import unicode_literals
      3 
      4 import re
      5 
      6 from .common import InfoExtractor
      7 from ..compat import compat_str
      8 from ..utils import (
      9     int_or_none,
     10     parse_resolution,
     11     str_or_none,
     12     try_get,
     13     unified_timestamp,
     14     url_or_none,
     15     urljoin,
     16 )
     17 
     18 
     19 class PeerTubeIE(InfoExtractor):
     20     _INSTANCES_RE = r'''(?:
     21                             # Taken from https://instances.joinpeertube.org/instances
     22                             peertube\.rainbowswingers\.net|
     23                             tube\.stanisic\.nl|
     24                             peer\.suiri\.us|
     25                             medias\.libox\.fr|
     26                             videomensoif\.ynh\.fr|
     27                             peertube\.travelpandas\.eu|
     28                             peertube\.rachetjay\.fr|
     29                             peertube\.montecsys\.fr|
     30                             tube\.eskuero\.me|
     31                             peer\.tube|
     32                             peertube\.umeahackerspace\.se|
     33                             tube\.nx-pod\.de|
     34                             video\.monsieurbidouille\.fr|
     35                             tube\.openalgeria\.org|
     36                             vid\.lelux\.fi|
     37                             video\.anormallostpod\.ovh|
     38                             tube\.crapaud-fou\.org|
     39                             peertube\.stemy\.me|
     40                             lostpod\.space|
     41                             exode\.me|
     42                             peertube\.snargol\.com|
     43                             vis\.ion\.ovh|
     44                             videosdulib\.re|
     45                             v\.mbius\.io|
     46                             videos\.judrey\.eu|
     47                             peertube\.osureplayviewer\.xyz|
     48                             peertube\.mathieufamily\.ovh|
     49                             www\.videos-libr\.es|
     50                             fightforinfo\.com|
     51                             peertube\.fediverse\.ru|
     52                             peertube\.oiseauroch\.fr|
     53                             video\.nesven\.eu|
     54                             v\.bearvideo\.win|
     55                             video\.qoto\.org|
     56                             justporn\.cc|
     57                             video\.vny\.fr|
     58                             peervideo\.club|
     59                             tube\.taker\.fr|
     60                             peertube\.chantierlibre\.org|
     61                             tube\.ipfixe\.info|
     62                             tube\.kicou\.info|
     63                             tube\.dodsorf\.as|
     64                             videobit\.cc|
     65                             video\.yukari\.moe|
     66                             videos\.elbinario\.net|
     67                             hkvideo\.live|
     68                             pt\.tux\.tf|
     69                             www\.hkvideo\.live|
     70                             FIGHTFORINFO\.com|
     71                             pt\.765racing\.com|
     72                             peertube\.gnumeria\.eu\.org|
     73                             nordenmedia\.com|
     74                             peertube\.co\.uk|
     75                             tube\.darfweb\.eu|
     76                             tube\.kalah-france\.org|
     77                             0ch\.in|
     78                             vod\.mochi\.academy|
     79                             film\.node9\.org|
     80                             peertube\.hatthieves\.es|
     81                             video\.fitchfamily\.org|
     82                             peertube\.ddns\.net|
     83                             video\.ifuncle\.kr|
     84                             video\.fdlibre\.eu|
     85                             tube\.22decembre\.eu|
     86                             peertube\.harmoniescreatives\.com|
     87                             tube\.fabrigli\.fr|
     88                             video\.thedwyers\.co|
     89                             video\.bruitbruit\.com|
     90                             peertube\.foxfam\.club|
     91                             peer\.philoxweb\.be|
     92                             videos\.bugs\.social|
     93                             peertube\.malbert\.xyz|
     94                             peertube\.bilange\.ca|
     95                             libretube\.net|
     96                             diytelevision\.com|
     97                             peertube\.fedilab\.app|
     98                             libre\.video|
     99                             video\.mstddntfdn\.online|
    100                             us\.tv|
    101                             peertube\.sl-network\.fr|
    102                             peertube\.dynlinux\.io|
    103                             peertube\.david\.durieux\.family|
    104                             peertube\.linuxrocks\.online|
    105                             peerwatch\.xyz|
    106                             v\.kretschmann\.social|
    107                             tube\.otter\.sh|
    108                             yt\.is\.nota\.live|
    109                             tube\.dragonpsi\.xyz|
    110                             peertube\.boneheadmedia\.com|
    111                             videos\.funkwhale\.audio|
    112                             watch\.44con\.com|
    113                             peertube\.gcaillaut\.fr|
    114                             peertube\.icu|
    115                             pony\.tube|
    116                             spacepub\.space|
    117                             tube\.stbr\.io|
    118                             v\.mom-gay\.faith|
    119                             tube\.port0\.xyz|
    120                             peertube\.simounet\.net|
    121                             play\.jergefelt\.se|
    122                             peertube\.zeteo\.me|
    123                             tube\.danq\.me|
    124                             peertube\.kerenon\.com|
    125                             tube\.fab-l3\.org|
    126                             tube\.calculate\.social|
    127                             peertube\.mckillop\.org|
    128                             tube\.netzspielplatz\.de|
    129                             vod\.ksite\.de|
    130                             peertube\.laas\.fr|
    131                             tube\.govital\.net|
    132                             peertube\.stephenson\.cc|
    133                             bistule\.nohost\.me|
    134                             peertube\.kajalinifi\.de|
    135                             video\.ploud\.jp|
    136                             video\.omniatv\.com|
    137                             peertube\.ffs2play\.fr|
    138                             peertube\.leboulaire\.ovh|
    139                             peertube\.tronic-studio\.com|
    140                             peertube\.public\.cat|
    141                             peertube\.metalbanana\.net|
    142                             video\.1000i100\.fr|
    143                             peertube\.alter-nativ-voll\.de|
    144                             tube\.pasa\.tf|
    145                             tube\.worldofhauru\.xyz|
    146                             pt\.kamp\.site|
    147                             peertube\.teleassist\.fr|
    148                             videos\.mleduc\.xyz|
    149                             conf\.tube|
    150                             media\.privacyinternational\.org|
    151                             pt\.forty-two\.nl|
    152                             video\.halle-leaks\.de|
    153                             video\.grosskopfgames\.de|
    154                             peertube\.schaeferit\.de|
    155                             peertube\.jackbot\.fr|
    156                             tube\.extinctionrebellion\.fr|
    157                             peertube\.f-si\.org|
    158                             video\.subak\.ovh|
    159                             videos\.koweb\.fr|
    160                             peertube\.zergy\.net|
    161                             peertube\.roflcopter\.fr|
    162                             peertube\.floss-marketing-school\.com|
    163                             vloggers\.social|
    164                             peertube\.iriseden\.eu|
    165                             videos\.ubuntu-paris\.org|
    166                             peertube\.mastodon\.host|
    167                             armstube\.com|
    168                             peertube\.s2s\.video|
    169                             peertube\.lol|
    170                             tube\.open-plug\.eu|
    171                             open\.tube|
    172                             peertube\.ch|
    173                             peertube\.normandie-libre\.fr|
    174                             peertube\.slat\.org|
    175                             video\.lacaveatonton\.ovh|
    176                             peertube\.uno|
    177                             peertube\.servebeer\.com|
    178                             peertube\.fedi\.quebec|
    179                             tube\.h3z\.jp|
    180                             tube\.plus200\.com|
    181                             peertube\.eric\.ovh|
    182                             tube\.metadocs\.cc|
    183                             tube\.unmondemeilleur\.eu|
    184                             gouttedeau\.space|
    185                             video\.antirep\.net|
    186                             nrop\.cant\.at|
    187                             tube\.ksl-bmx\.de|
    188                             tube\.plaf\.fr|
    189                             tube\.tchncs\.de|
    190                             video\.devinberg\.com|
    191                             hitchtube\.fr|
    192                             peertube\.kosebamse\.com|
    193                             yunopeertube\.myddns\.me|
    194                             peertube\.varney\.fr|
    195                             peertube\.anon-kenkai\.com|
    196                             tube\.maiti\.info|
    197                             tubee\.fr|
    198                             videos\.dinofly\.com|
    199                             toobnix\.org|
    200                             videotape\.me|
    201                             voca\.tube|
    202                             video\.heromuster\.com|
    203                             video\.lemediatv\.fr|
    204                             video\.up\.edu\.ph|
    205                             balafon\.video|
    206                             video\.ivel\.fr|
    207                             thickrips\.cloud|
    208                             pt\.laurentkruger\.fr|
    209                             video\.monarch-pass\.net|
    210                             peertube\.artica\.center|
    211                             video\.alternanet\.fr|
    212                             indymotion\.fr|
    213                             fanvid\.stopthatimp\.net|
    214                             video\.farci\.org|
    215                             v\.lesterpig\.com|
    216                             video\.okaris\.de|
    217                             tube\.pawelko\.net|
    218                             peertube\.mablr\.org|
    219                             tube\.fede\.re|
    220                             pytu\.be|
    221                             evertron\.tv|
    222                             devtube\.dev-wiki\.de|
    223                             raptube\.antipub\.org|
    224                             video\.selea\.se|
    225                             peertube\.mygaia\.org|
    226                             video\.oh14\.de|
    227                             peertube\.livingutopia\.org|
    228                             peertube\.the-penguin\.de|
    229                             tube\.thechangebook\.org|
    230                             tube\.anjara\.eu|
    231                             pt\.pube\.tk|
    232                             video\.samedi\.pm|
    233                             mplayer\.demouliere\.eu|
    234                             widemus\.de|
    235                             peertube\.me|
    236                             peertube\.zapashcanon\.fr|
    237                             video\.latavernedejohnjohn\.fr|
    238                             peertube\.pcservice46\.fr|
    239                             peertube\.mazzonetto\.eu|
    240                             video\.irem\.univ-paris-diderot\.fr|
    241                             video\.livecchi\.cloud|
    242                             alttube\.fr|
    243                             video\.coop\.tools|
    244                             video\.cabane-libre\.org|
    245                             peertube\.openstreetmap\.fr|
    246                             videos\.alolise\.org|
    247                             irrsinn\.video|
    248                             video\.antopie\.org|
    249                             scitech\.video|
    250                             tube2\.nemsia\.org|
    251                             video\.amic37\.fr|
    252                             peertube\.freeforge\.eu|
    253                             video\.arbitrarion\.com|
    254                             video\.datsemultimedia\.com|
    255                             stoptrackingus\.tv|
    256                             peertube\.ricostrongxxx\.com|
    257                             docker\.videos\.lecygnenoir\.info|
    258                             peertube\.togart\.de|
    259                             tube\.postblue\.info|
    260                             videos\.domainepublic\.net|
    261                             peertube\.cyber-tribal\.com|
    262                             video\.gresille\.org|
    263                             peertube\.dsmouse\.net|
    264                             cinema\.yunohost\.support|
    265                             tube\.theocevaer\.fr|
    266                             repro\.video|
    267                             tube\.4aem\.com|
    268                             quaziinc\.com|
    269                             peertube\.metawurst\.space|
    270                             videos\.wakapo\.com|
    271                             video\.ploud\.fr|
    272                             video\.freeradical\.zone|
    273                             tube\.valinor\.fr|
    274                             refuznik\.video|
    275                             pt\.kircheneuenburg\.de|
    276                             peertube\.asrun\.eu|
    277                             peertube\.lagob\.fr|
    278                             videos\.side-ways\.net|
    279                             91video\.online|
    280                             video\.valme\.io|
    281                             video\.taboulisme\.com|
    282                             videos-libr\.es|
    283                             tv\.mooh\.fr|
    284                             nuage\.acostey\.fr|
    285                             video\.monsieur-a\.fr|
    286                             peertube\.librelois\.fr|
    287                             videos\.pair2jeux\.tube|
    288                             videos\.pueseso\.club|
    289                             peer\.mathdacloud\.ovh|
    290                             media\.assassinate-you\.net|
    291                             vidcommons\.org|
    292                             ptube\.rousset\.nom\.fr|
    293                             tube\.cyano\.at|
    294                             videos\.squat\.net|
    295                             video\.iphodase\.fr|
    296                             peertube\.makotoworkshop\.org|
    297                             peertube\.serveur\.slv-valbonne\.fr|
    298                             vault\.mle\.party|
    299                             hostyour\.tv|
    300                             videos\.hack2g2\.fr|
    301                             libre\.tube|
    302                             pire\.artisanlogiciel\.net|
    303                             videos\.numerique-en-commun\.fr|
    304                             video\.netsyms\.com|
    305                             video\.die-partei\.social|
    306                             video\.writeas\.org|
    307                             peertube\.swarm\.solvingmaz\.es|
    308                             tube\.pericoloso\.ovh|
    309                             watching\.cypherpunk\.observer|
    310                             videos\.adhocmusic\.com|
    311                             tube\.rfc1149\.net|
    312                             peertube\.librelabucm\.org|
    313                             videos\.numericoop\.fr|
    314                             peertube\.koehn\.com|
    315                             peertube\.anarchmusicall\.net|
    316                             tube\.kampftoast\.de|
    317                             vid\.y-y\.li|
    318                             peertube\.xtenz\.xyz|
    319                             diode\.zone|
    320                             tube\.egf\.mn|
    321                             peertube\.nomagic\.uk|
    322                             visionon\.tv|
    323                             videos\.koumoul\.com|
    324                             video\.rastapuls\.com|
    325                             video\.mantlepro\.com|
    326                             video\.deadsuperhero\.com|
    327                             peertube\.musicstudio\.pro|
    328                             peertube\.we-keys\.fr|
    329                             artitube\.artifaille\.fr|
    330                             peertube\.ethernia\.net|
    331                             tube\.midov\.pl|
    332                             peertube\.fr|
    333                             watch\.snoot\.tube|
    334                             peertube\.donnadieu\.fr|
    335                             argos\.aquilenet\.fr|
    336                             tube\.nemsia\.org|
    337                             tube\.bruniau\.net|
    338                             videos\.darckoune\.moe|
    339                             tube\.traydent\.info|
    340                             dev\.videos\.lecygnenoir\.info|
    341                             peertube\.nayya\.org|
    342                             peertube\.live|
    343                             peertube\.mofgao\.space|
    344                             video\.lequerrec\.eu|
    345                             peertube\.amicale\.net|
    346                             aperi\.tube|
    347                             tube\.ac-lyon\.fr|
    348                             video\.lw1\.at|
    349                             www\.yiny\.org|
    350                             videos\.pofilo\.fr|
    351                             tube\.lou\.lt|
    352                             choob\.h\.etbus\.ch|
    353                             tube\.hoga\.fr|
    354                             peertube\.heberge\.fr|
    355                             video\.obermui\.de|
    356                             videos\.cloudfrancois\.fr|
    357                             betamax\.video|
    358                             video\.typica\.us|
    359                             tube\.piweb\.be|
    360                             video\.blender\.org|
    361                             peertube\.cat|
    362                             tube\.kdy\.ch|
    363                             pe\.ertu\.be|
    364                             peertube\.social|
    365                             videos\.lescommuns\.org|
    366                             tv\.datamol\.org|
    367                             videonaute\.fr|
    368                             dialup\.express|
    369                             peertube\.nogafa\.org|
    370                             megatube\.lilomoino\.fr|
    371                             peertube\.tamanoir\.foucry\.net|
    372                             peertube\.devosi\.org|
    373                             peertube\.1312\.media|
    374                             tube\.bootlicker\.party|
    375                             skeptikon\.fr|
    376                             video\.blueline\.mg|
    377                             tube\.homecomputing\.fr|
    378                             tube\.ouahpiti\.info|
    379                             video\.tedomum\.net|
    380                             video\.g3l\.org|
    381                             fontube\.fr|
    382                             peertube\.gaialabs\.ch|
    383                             tube\.kher\.nl|
    384                             peertube\.qtg\.fr|
    385                             video\.migennes\.net|
    386                             tube\.p2p\.legal|
    387                             troll\.tv|
    388                             videos\.iut-orsay\.fr|
    389                             peertube\.solidev\.net|
    390                             videos\.cemea\.org|
    391                             video\.passageenseine\.fr|
    392                             videos\.festivalparminous\.org|
    393                             peertube\.touhoppai\.moe|
    394                             sikke\.fi|
    395                             peer\.hostux\.social|
    396                             share\.tube|
    397                             peertube\.walkingmountains\.fr|
    398                             videos\.benpro\.fr|
    399                             peertube\.parleur\.net|
    400                             peertube\.heraut\.eu|
    401                             tube\.aquilenet\.fr|
    402                             peertube\.gegeweb\.eu|
    403                             framatube\.org|
    404                             thinkerview\.video|
    405                             tube\.conferences-gesticulees\.net|
    406                             peertube\.datagueule\.tv|
    407                             video\.lqdn\.fr|
    408                             tube\.mochi\.academy|
    409                             media\.zat\.im|
    410                             video\.colibris-outilslibres\.org|
    411                             tube\.svnet\.fr|
    412                             peertube\.video|
    413                             peertube3\.cpy\.re|
    414                             peertube2\.cpy\.re|
    415                             videos\.tcit\.fr|
    416                             peertube\.cpy\.re|
    417                             canard\.tube
    418                         )'''
    419     _UUID_RE = r'[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}'
    420     _API_BASE = 'https://%s/api/v1/videos/%s/%s'
    421     _VALID_URL = r'''(?x)
    422                     (?:
    423                         peertube:(?P<host>[^:]+):|
    424                         https?://(?P<host_2>%s)/(?:videos/(?:watch|embed)|api/v\d/videos)/
    425                     )
    426                     (?P<id>%s)
    427                     ''' % (_INSTANCES_RE, _UUID_RE)
    428     _TESTS = [{
    429         'url': 'https://framatube.org/videos/watch/9c9de5e8-0a1e-484a-b099-e80766180a6d',
    430         'md5': '9bed8c0137913e17b86334e5885aacff',
    431         'info_dict': {
    432             'id': '9c9de5e8-0a1e-484a-b099-e80766180a6d',
    433             'ext': 'mp4',
    434             'title': 'What is PeerTube?',
    435             'description': 'md5:3fefb8dde2b189186ce0719fda6f7b10',
    436             'thumbnail': r're:https?://.*\.(?:jpg|png)',
    437             'timestamp': 1538391166,
    438             'upload_date': '20181001',
    439             'uploader': 'Framasoft',
    440             'uploader_id': '3',
    441             'uploader_url': 'https://framatube.org/accounts/framasoft',
    442             'channel': 'Les vidéos de Framasoft',
    443             'channel_id': '2',
    444             'channel_url': 'https://framatube.org/video-channels/bf54d359-cfad-4935-9d45-9d6be93f63e8',
    445             'language': 'en',
    446             'license': 'Attribution - Share Alike',
    447             'duration': 113,
    448             'view_count': int,
    449             'like_count': int,
    450             'dislike_count': int,
    451             'tags': ['framasoft', 'peertube'],
    452             'categories': ['Science & Technology'],
    453         }
    454     }, {
    455         # Issue #26002
    456         'url': 'peertube:spacepub.space:d8943b2d-8280-497b-85ec-bc282ec2afdc',
    457         'info_dict': {
    458             'id': 'd8943b2d-8280-497b-85ec-bc282ec2afdc',
    459             'ext': 'mp4',
    460             'title': 'Dot matrix printer shell demo',
    461             'uploader_id': '3',
    462             'timestamp': 1587401293,
    463             'upload_date': '20200420',
    464             'uploader': 'Drew DeVault',
    465         }
    466     }, {
    467         'url': 'https://peertube.tamanoir.foucry.net/videos/watch/0b04f13d-1e18-4f1d-814e-4979aa7c9c44',
    468         'only_matching': True,
    469     }, {
    470         # nsfw
    471         'url': 'https://tube.22decembre.eu/videos/watch/9bb88cd3-9959-46d9-9ab9-33d2bb704c39',
    472         'only_matching': True,
    473     }, {
    474         'url': 'https://tube.22decembre.eu/videos/embed/fed67262-6edb-4d1c-833b-daa9085c71d7',
    475         'only_matching': True,
    476     }, {
    477         'url': 'https://tube.openalgeria.org/api/v1/videos/c1875674-97d0-4c94-a058-3f7e64c962e8',
    478         'only_matching': True,
    479     }, {
    480         'url': 'peertube:video.blender.org:b37a5b9f-e6b5-415c-b700-04a5cd6ec205',
    481         'only_matching': True,
    482     }]
    483 
    484     @staticmethod
    485     def _extract_peertube_url(webpage, source_url):
    486         mobj = re.match(
    487             r'https?://(?P<host>[^/]+)/videos/(?:watch|embed)/(?P<id>%s)'
    488             % PeerTubeIE._UUID_RE, source_url)
    489         if mobj and any(p in webpage for p in (
    490                 '<title>PeerTube<',
    491                 'There will be other non JS-based clients to access PeerTube',
    492                 '>We are sorry but it seems that PeerTube is not compatible with your web browser.<')):
    493             return 'peertube:%s:%s' % mobj.group('host', 'id')
    494 
    495     @staticmethod
    496     def _extract_urls(webpage, source_url):
    497         entries = re.findall(
    498             r'''(?x)<iframe[^>]+\bsrc=["\'](?P<url>(?:https?:)?//%s/videos/embed/%s)'''
    499             % (PeerTubeIE._INSTANCES_RE, PeerTubeIE._UUID_RE), webpage)
    500         if not entries:
    501             peertube_url = PeerTubeIE._extract_peertube_url(webpage, source_url)
    502             if peertube_url:
    503                 entries = [peertube_url]
    504         return entries
    505 
    506     def _call_api(self, host, video_id, path, note=None, errnote=None, fatal=True):
    507         return self._download_json(
    508             self._API_BASE % (host, video_id, path), video_id,
    509             note=note, errnote=errnote, fatal=fatal)
    510 
    511     def _get_subtitles(self, host, video_id):
    512         captions = self._call_api(
    513             host, video_id, 'captions', note='Downloading captions JSON',
    514             fatal=False)
    515         if not isinstance(captions, dict):
    516             return
    517         data = captions.get('data')
    518         if not isinstance(data, list):
    519             return
    520         subtitles = {}
    521         for e in data:
    522             language_id = try_get(e, lambda x: x['language']['id'], compat_str)
    523             caption_url = urljoin('https://%s' % host, e.get('captionPath'))
    524             if not caption_url:
    525                 continue
    526             subtitles.setdefault(language_id or 'en', []).append({
    527                 'url': caption_url,
    528             })
    529         return subtitles
    530 
    531     def _real_extract(self, url):
    532         mobj = re.match(self._VALID_URL, url)
    533         host = mobj.group('host') or mobj.group('host_2')
    534         video_id = mobj.group('id')
    535 
    536         video = self._call_api(
    537             host, video_id, '', note='Downloading video JSON')
    538 
    539         title = video['name']
    540 
    541         formats = []
    542         files = video.get('files') or []
    543         for playlist in (video.get('streamingPlaylists') or []):
    544             if not isinstance(playlist, dict):
    545                 continue
    546             playlist_files = playlist.get('files')
    547             if not (playlist_files and isinstance(playlist_files, list)):
    548                 continue
    549             files.extend(playlist_files)
    550         for file_ in files:
    551             if not isinstance(file_, dict):
    552                 continue
    553             file_url = url_or_none(file_.get('fileUrl'))
    554             if not file_url:
    555                 continue
    556             file_size = int_or_none(file_.get('size'))
    557             format_id = try_get(
    558                 file_, lambda x: x['resolution']['label'], compat_str)
    559             f = parse_resolution(format_id)
    560             f.update({
    561                 'url': file_url,
    562                 'format_id': format_id,
    563                 'filesize': file_size,
    564             })
    565             if format_id == '0p':
    566                 f['vcodec'] = 'none'
    567             else:
    568                 f['fps'] = int_or_none(file_.get('fps'))
    569             formats.append(f)
    570         self._sort_formats(formats)
    571 
    572         description = video.get('description')
    573         if len(description) >= 250:
    574             # description is shortened
    575             full_description = self._call_api(
    576                 host, video_id, 'description', note='Downloading description JSON',
    577                 fatal=False)
    578 
    579             if isinstance(full_description, dict):
    580                 description = str_or_none(full_description.get('description')) or description
    581 
    582         subtitles = self.extract_subtitles(host, video_id)
    583 
    584         def data(section, field, type_):
    585             return try_get(video, lambda x: x[section][field], type_)
    586 
    587         def account_data(field, type_):
    588             return data('account', field, type_)
    589 
    590         def channel_data(field, type_):
    591             return data('channel', field, type_)
    592 
    593         category = data('category', 'label', compat_str)
    594         categories = [category] if category else None
    595 
    596         nsfw = video.get('nsfw')
    597         if nsfw is bool:
    598             age_limit = 18 if nsfw else 0
    599         else:
    600             age_limit = None
    601 
    602         webpage_url = 'https://%s/videos/watch/%s' % (host, video_id)
    603 
    604         return {
    605             'id': video_id,
    606             'title': title,
    607             'description': description,
    608             'thumbnail': urljoin(webpage_url, video.get('thumbnailPath')),
    609             'timestamp': unified_timestamp(video.get('publishedAt')),
    610             'uploader': account_data('displayName', compat_str),
    611             'uploader_id': str_or_none(account_data('id', int)),
    612             'uploader_url': url_or_none(account_data('url', compat_str)),
    613             'channel': channel_data('displayName', compat_str),
    614             'channel_id': str_or_none(channel_data('id', int)),
    615             'channel_url': url_or_none(channel_data('url', compat_str)),
    616             'language': data('language', 'id', compat_str),
    617             'license': data('licence', 'label', compat_str),
    618             'duration': int_or_none(video.get('duration')),
    619             'view_count': int_or_none(video.get('views')),
    620             'like_count': int_or_none(video.get('likes')),
    621             'dislike_count': int_or_none(video.get('dislikes')),
    622             'age_limit': age_limit,
    623             'tags': try_get(video, lambda x: x['tags'], list),
    624             'categories': categories,
    625             'formats': formats,
    626             'subtitles': subtitles,
    627             'webpage_url': webpage_url,
    628         }