Ben преди 11 месеца
родител
ревизия
e8c7be5236
променени са 6 файла, в които са добавени 1557 реда и са изтрити 1700 реда
  1. 0 77
      data.json
  2. 0 1623
      format.json
  3. 250 0
      js/format-utils.js
  4. 524 0
      js/formats.js
  5. 497 0
      js/info.js
  6. 286 0
      js/utils.js

Файловите разлики са ограничени, защото са твърде много
+ 0 - 77
data.json


+ 0 - 1623
format.json

@@ -1,1623 +0,0 @@
-[
-  {
-    "format_id": "sb3",
-    "format_note": "storyboard",
-    "ext": "mhtml",
-    "protocol": "mhtml",
-    "acodec": "none",
-    "vcodec": "none",
-    "url": "https://i.ytimg.com/sb/5dPXGzyZqI8/storyboard3_L0/default.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgiBlayxBg==&sigh=rs$AOn4CLDeb5SJmvBfhsVa8buaCi3_4NeJ6g",
-    "width": 48,
-    "height": 27,
-    "fps": 1.7857142857142858,
-    "rows": 10,
-    "columns": 10,
-    "fragments": [
-      {
-        "url": "https://i.ytimg.com/sb/5dPXGzyZqI8/storyboard3_L0/default.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgiBlayxBg==&sigh=rs$AOn4CLDeb5SJmvBfhsVa8buaCi3_4NeJ6g",
-        "duration": 56.0
-      }
-    ],
-    "resolution": "48x27",
-    "aspect_ratio": 1.78,
-    "filesize_approx": null,
-    "http_headers": {},
-    "audio_ext": "none",
-    "video_ext": "none",
-    "vbr": 0,
-    "abr": 0,
-    "tbr": null,
-    "format": "sb3 - 48x27 (storyboard)"
-  },
-  {
-    "format_id": "sb2",
-    "format_note": "storyboard",
-    "ext": "mhtml",
-    "protocol": "mhtml",
-    "acodec": "none",
-    "vcodec": "none",
-    "url": "https://i.ytimg.com/sb/5dPXGzyZqI8/storyboard3_L1/M$M.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgiBlayxBg==&sigh=rs$AOn4CLCS3BX9-Ryyt5dGi12SGdr99cerhA",
-    "width": 80,
-    "height": 45,
-    "fps": 1.0357142857142858,
-    "rows": 10,
-    "columns": 10,
-    "fragments": [
-      {
-        "url": "https://i.ytimg.com/sb/5dPXGzyZqI8/storyboard3_L1/M0.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgiBlayxBg==&sigh=rs$AOn4CLCS3BX9-Ryyt5dGi12SGdr99cerhA",
-        "duration": 56.0
-      }
-    ],
-    "resolution": "80x45",
-    "aspect_ratio": 1.78,
-    "filesize_approx": null,
-    "http_headers": {},
-    "audio_ext": "none",
-    "video_ext": "none",
-    "vbr": 0,
-    "abr": 0,
-    "tbr": null,
-    "format": "sb2 - 80x45 (storyboard)"
-  },
-  {
-    "format_id": "sb1",
-    "format_note": "storyboard",
-    "ext": "mhtml",
-    "protocol": "mhtml",
-    "acodec": "none",
-    "vcodec": "none",
-    "url": "https://i.ytimg.com/sb/5dPXGzyZqI8/storyboard3_L2/M$M.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgiBlayxBg==&sigh=rs$AOn4CLCB4GTJOOJSG7exJgKjFsSTP3A3IQ",
-    "width": 160,
-    "height": 90,
-    "fps": 1.0357142857142858,
-    "rows": 5,
-    "columns": 5,
-    "fragments": [
-      {
-        "url": "https://i.ytimg.com/sb/5dPXGzyZqI8/storyboard3_L2/M0.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgiBlayxBg==&sigh=rs$AOn4CLCB4GTJOOJSG7exJgKjFsSTP3A3IQ",
-        "duration": 24.13793103448276
-      },
-      {
-        "url": "https://i.ytimg.com/sb/5dPXGzyZqI8/storyboard3_L2/M1.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgiBlayxBg==&sigh=rs$AOn4CLCB4GTJOOJSG7exJgKjFsSTP3A3IQ",
-        "duration": 24.13793103448276
-      },
-      {
-        "url": "https://i.ytimg.com/sb/5dPXGzyZqI8/storyboard3_L2/M2.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgiBlayxBg==&sigh=rs$AOn4CLCB4GTJOOJSG7exJgKjFsSTP3A3IQ",
-        "duration": 7.724137931034477
-      }
-    ],
-    "resolution": "160x90",
-    "aspect_ratio": 1.78,
-    "filesize_approx": null,
-    "http_headers": {},
-    "audio_ext": "none",
-    "video_ext": "none",
-    "vbr": 0,
-    "abr": 0,
-    "tbr": null,
-    "format": "sb1 - 160x90 (storyboard)"
-  },
-  {
-    "format_id": "sb0",
-    "format_note": "storyboard",
-    "ext": "mhtml",
-    "protocol": "mhtml",
-    "acodec": "none",
-    "vcodec": "none",
-    "url": "https://i.ytimg.com/sb/5dPXGzyZqI8/storyboard3_L3/M$M.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgiBlayxBg==&sigh=rs$AOn4CLA7fdYPVNP-V9rfE_0RF2etoWrvgg",
-    "width": 320,
-    "height": 180,
-    "fps": 1.0357142857142858,
-    "rows": 3,
-    "columns": 3,
-    "fragments": [
-      {
-        "url": "https://i.ytimg.com/sb/5dPXGzyZqI8/storyboard3_L3/M0.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgiBlayxBg==&sigh=rs$AOn4CLA7fdYPVNP-V9rfE_0RF2etoWrvgg",
-        "duration": 8.689655172413794
-      },
-      {
-        "url": "https://i.ytimg.com/sb/5dPXGzyZqI8/storyboard3_L3/M1.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgiBlayxBg==&sigh=rs$AOn4CLA7fdYPVNP-V9rfE_0RF2etoWrvgg",
-        "duration": 8.689655172413794
-      },
-      {
-        "url": "https://i.ytimg.com/sb/5dPXGzyZqI8/storyboard3_L3/M2.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgiBlayxBg==&sigh=rs$AOn4CLA7fdYPVNP-V9rfE_0RF2etoWrvgg",
-        "duration": 8.689655172413794
-      },
-      {
-        "url": "https://i.ytimg.com/sb/5dPXGzyZqI8/storyboard3_L3/M3.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgiBlayxBg==&sigh=rs$AOn4CLA7fdYPVNP-V9rfE_0RF2etoWrvgg",
-        "duration": 8.689655172413794
-      },
-      {
-        "url": "https://i.ytimg.com/sb/5dPXGzyZqI8/storyboard3_L3/M4.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgiBlayxBg==&sigh=rs$AOn4CLA7fdYPVNP-V9rfE_0RF2etoWrvgg",
-        "duration": 8.689655172413794
-      },
-      {
-        "url": "https://i.ytimg.com/sb/5dPXGzyZqI8/storyboard3_L3/M5.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgiBlayxBg==&sigh=rs$AOn4CLA7fdYPVNP-V9rfE_0RF2etoWrvgg",
-        "duration": 8.689655172413794
-      },
-      {
-        "url": "https://i.ytimg.com/sb/5dPXGzyZqI8/storyboard3_L3/M6.jpg?sqp=-oaymwENSDfyq4qpAwVwAcABBqLzl_8DBgiBlayxBg==&sigh=rs$AOn4CLA7fdYPVNP-V9rfE_0RF2etoWrvgg",
-        "duration": 3.8620689655172384
-      }
-    ],
-    "resolution": "320x180",
-    "aspect_ratio": 1.78,
-    "filesize_approx": null,
-    "http_headers": {},
-    "audio_ext": "none",
-    "video_ext": "none",
-    "vbr": 0,
-    "abr": 0,
-    "tbr": null,
-    "format": "sb0 - 320x180 (storyboard)"
-  },
-  {
-    "format_id": "233",
-    "format_note": "Default",
-    "format_index": null,
-    "url": "https://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/itag/233/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/goi/133/sgoap/clen%3D345876%3Bdur%3D56.563%3Bgir%3Dyes%3Bitag%3D139%3Blmt%3D1714111912825642/rqh/1/hls_chunk_host/rr3---sn-o097znz7.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/mh/Rz/mm/31,26/mn/sn-o097znz7,sn-a5mekn6d/ms/au,onr/mv/m/mvi/3/pl/15/initcwndbps/787500/vprv/1/playlist_type/DVR/dover/13/txp/5532434/mt/1714407932/fvip/3/short_key/1/keepalive/yes/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,goi,sgoap,rqh,xpc,vprv,playlist_type/sig/AJfQdSswRQIgAtGQ2HT8xxS5fUeRjU390GCMO3uKpklxmFqi21-dN90CIQCMpkHQw3lhQF7Beg4H2wOFGuyQ4EOHtyrowpIHlcFxDg%3D%3D/lsparams/hls_chunk_host,mh,mm,mn,ms,mv,mvi,pl,initcwndbps/lsig/AHWaYeowRQIhANv4d35FKyWwfrIFAwSG4dZhRIsXN0eB073ywO9dFWrLAiB4pLtm4qahAKASdMOvJlpvDj1K4laj142JoqC1J9EM2g%3D%3D/playlist/index.m3u8",
-    "manifest_url": "https://manifest.googlevideo.com/api/manifest/hls_variant/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/source/youtube/requiressl/yes/xpc/EgVo2aDSNQ%3D%3D/playback_host/rr3---sn-o097znz7.googlevideo.com/mh/Rz/mm/31%2C26/mn/sn-o097znz7%2Csn-a5mekn6d/ms/au%2Conr/mv/m/mvi/3/pl/15/hfr/1/demuxed/1/tts_caps/1/maudio/1/initcwndbps/787500/vprv/1/go/1/mt/1714407932/fvip/3/nvgoi/1/short_key/1/ncsapi/1/keepalive/yes/dover/13/itag/0/playlist_type/DVR/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Cxpc%2Chfr%2Cdemuxed%2Ctts_caps%2Cmaudio%2Cvprv%2Cgo%2Citag%2Cplaylist_type/sig/AJfQdSswRQIhALFqr05ljmiJjuzFl2TTMIfRsNuxUP2kmHUc-2MdMjMGAiBkWu4f1qKH421294MKPMeOJz1K-IPag52Ke12rvCMRSg%3D%3D/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AHWaYeowRQIhALsiEdN5q1QSndrAU9jQH39I8gjGoNX5MV5YXAvfgpBSAiBLOcDfuYFTUoyAgV9wmBAB4bljhT6AgSMEN89MGGmywA%3D%3D/file/index.m3u8",
-    "language": "en",
-    "ext": "mp4",
-    "protocol": "m3u8_native",
-    "preference": null,
-    "quality": -1,
-    "has_drm": false,
-    "vcodec": "none",
-    "source_preference": -1,
-    "resolution": "audio only",
-    "aspect_ratio": null,
-    "http_headers": {},
-    "audio_ext": "mp4",
-    "video_ext": "none",
-    "vbr": 0,
-    "abr": null,
-    "tbr": null,
-    "format": "233 - audio only (Default)"
-  },
-  {
-    "format_id": "234",
-    "format_note": "Default",
-    "format_index": null,
-    "url": "https://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/itag/234/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/goi/133/sgoap/clen%3D915089%3Bdur%3D56.494%3Bgir%3Dyes%3Bitag%3D140%3Blmt%3D1714111912835814/rqh/1/hls_chunk_host/rr3---sn-o097znz7.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/mh/Rz/mm/31,26/mn/sn-o097znz7,sn-a5mekn6d/ms/au,onr/mv/m/mvi/3/pl/15/initcwndbps/787500/vprv/1/playlist_type/DVR/dover/13/txp/5532434/mt/1714407932/fvip/3/short_key/1/keepalive/yes/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,goi,sgoap,rqh,xpc,vprv,playlist_type/sig/AJfQdSswRQIgbrozcgQGES10Bscy7NSH5GMkkQJa1fB-lw1Z_BoHydECIQCJWb285cRcbNqbsSRLy8MRD5T7uHf-Dx85r1lA55dj4Q%3D%3D/lsparams/hls_chunk_host,mh,mm,mn,ms,mv,mvi,pl,initcwndbps/lsig/AHWaYeowRgIhAOFpSCCVyJ2PLCTefR1YQpEU_DZQt4V7KOFO58Dqklh8AiEA5nyS8GZdOlbRGS8tte2AHMP7GExzZkL5VUg05olmi3o%3D/playlist/index.m3u8",
-    "manifest_url": "https://manifest.googlevideo.com/api/manifest/hls_variant/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/source/youtube/requiressl/yes/xpc/EgVo2aDSNQ%3D%3D/playback_host/rr3---sn-o097znz7.googlevideo.com/mh/Rz/mm/31%2C26/mn/sn-o097znz7%2Csn-a5mekn6d/ms/au%2Conr/mv/m/mvi/3/pl/15/hfr/1/demuxed/1/tts_caps/1/maudio/1/initcwndbps/787500/vprv/1/go/1/mt/1714407932/fvip/3/nvgoi/1/short_key/1/ncsapi/1/keepalive/yes/dover/13/itag/0/playlist_type/DVR/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Cxpc%2Chfr%2Cdemuxed%2Ctts_caps%2Cmaudio%2Cvprv%2Cgo%2Citag%2Cplaylist_type/sig/AJfQdSswRQIhALFqr05ljmiJjuzFl2TTMIfRsNuxUP2kmHUc-2MdMjMGAiBkWu4f1qKH421294MKPMeOJz1K-IPag52Ke12rvCMRSg%3D%3D/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AHWaYeowRQIhALsiEdN5q1QSndrAU9jQH39I8gjGoNX5MV5YXAvfgpBSAiBLOcDfuYFTUoyAgV9wmBAB4bljhT6AgSMEN89MGGmywA%3D%3D/file/index.m3u8",
-    "language": "en",
-    "ext": "mp4",
-    "protocol": "m3u8_native",
-    "preference": null,
-    "quality": -1,
-    "has_drm": false,
-    "vcodec": "none",
-    "source_preference": -1,
-    "resolution": "audio only",
-    "aspect_ratio": null,
-    "http_headers": {},
-    "audio_ext": "mp4",
-    "video_ext": "none",
-    "vbr": 0,
-    "abr": null,
-    "tbr": null,
-    "format": "234 - audio only (Default)"
-  },
-  {
-    "asr": 22050,
-    "filesize": 218886,
-    "format_id": "599",
-    "format_note": "ultralow",
-    "source_preference": -1,
-    "fps": null,
-    "audio_channels": 2,
-    "height": null,
-    "quality": 1.0,
-    "has_drm": false,
-    "tbr": 30.958,
-    "filesize_approx": 218884,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429871&ei=T8svZrKvKMy9z7sPueaJwAM&ip=16.50.54.218&id=o-APg_O3UHcZWFGLI-9JfIzyLCmvHpOLG74MJMkZnCuINp&itag=599&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=audio%2Fmp4&gir=yes&clen=218886&dur=56.563&lmt=1714111920291977&mt=1714407932&fvip=3&keepalive=yes&c=ANDROID&txp=5532434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIgXgDQuYlvWBg0yKb9zloVKNdWmgbQSxjwLRCLMQuStsoCIQCe81G3zKd2-MKf5zrXHBBCZ59BU-dKTmOVYyJ8TiLLdw%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIgWltg81-E0tWWRHJ2dWsrDl75sMwyMUCZ9XsxmMmtWRsCIQDCqoPdS2tviwzPaJaw6CUzfTd2G7SMVTgEzwjxKWzC0Q%3D%3D",
-    "width": null,
-    "language": "en",
-    "language_preference": -1,
-    "preference": null,
-    "ext": "m4a",
-    "vcodec": "none",
-    "acodec": "mp4a.40.5",
-    "dynamic_range": null,
-    "container": "m4a_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "audio only",
-    "aspect_ratio": null,
-    "http_headers": {},
-    "audio_ext": "m4a",
-    "video_ext": "none",
-    "vbr": 0,
-    "abr": 30.958,
-    "format": "599 - audio only (ultralow)"
-  },
-  {
-    "asr": 48000,
-    "filesize": 255534,
-    "format_id": "600",
-    "format_note": "ultralow",
-    "source_preference": -1,
-    "fps": null,
-    "audio_channels": 2,
-    "height": null,
-    "quality": 1.0,
-    "has_drm": false,
-    "tbr": 36.206,
-    "filesize_approx": 255528,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429871&ei=T8svZrKvKMy9z7sPueaJwAM&ip=16.50.54.218&id=o-APg_O3UHcZWFGLI-9JfIzyLCmvHpOLG74MJMkZnCuINp&itag=600&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=audio%2Fwebm&gir=yes&clen=255534&dur=56.461&lmt=1714111945849563&mt=1714407932&fvip=3&keepalive=yes&c=ANDROID&txp=5532434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIgXuvsVi98oO0TKnyWJlmgba3CAuXv2RRwwQ2sqKE3-nYCIQDcmeyE0E90KdYT3yNmW3SKtXKNJIXq8JwfqkaOyDynlA%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIgWltg81-E0tWWRHJ2dWsrDl75sMwyMUCZ9XsxmMmtWRsCIQDCqoPdS2tviwzPaJaw6CUzfTd2G7SMVTgEzwjxKWzC0Q%3D%3D",
-    "width": null,
-    "language": "en",
-    "language_preference": -1,
-    "preference": null,
-    "ext": "webm",
-    "vcodec": "none",
-    "acodec": "opus",
-    "dynamic_range": null,
-    "container": "webm_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "audio only",
-    "aspect_ratio": null,
-    "http_headers": {},
-    "audio_ext": "webm",
-    "video_ext": "none",
-    "vbr": 0,
-    "abr": 36.206,
-    "format": "600 - audio only (ultralow)"
-  },
-  {
-    "asr": 22050,
-    "filesize": 345876,
-    "format_id": "139",
-    "format_note": "low",
-    "source_preference": -1,
-    "fps": null,
-    "audio_channels": 2,
-    "height": null,
-    "quality": 2.0,
-    "has_drm": false,
-    "tbr": 48.919,
-    "filesize_approx": 345875,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429869&ei=TcsvZoTpAcXv4t4PuN6FiAc&ip=16.50.54.218&id=o-AK03sRhPRET_5sIM0phiVbDY2V7AAZFjUuOaDFclcxWF&itag=139&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=audio%2Fmp4&gir=yes&clen=345876&dur=56.563&lmt=1714111912825642&mt=1714407932&fvip=3&keepalive=yes&c=IOS&txp=5532434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRgIhAM3LZqtJZInKXulxgvg3WitzKZ0G7e6qtio3LwFAkdiQAiEA1Ud3sFni-LU6aOwOcyfmBDZHjAE7D1twtCibHqusQrM%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIhAPPY-XCEkRTbT3gz0BKlSQthBKh9NzJJv8G50PAilth1AiAFnmj8EolqE7A3bBtduJp8LkvE8AhFysldsKHYb2nSeA%3D%3D",
-    "width": null,
-    "language": "en",
-    "language_preference": -1,
-    "preference": null,
-    "ext": "m4a",
-    "vcodec": "none",
-    "acodec": "mp4a.40.5",
-    "dynamic_range": null,
-    "container": "m4a_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "audio only",
-    "aspect_ratio": null,
-    "http_headers": {},
-    "audio_ext": "m4a",
-    "video_ext": "none",
-    "vbr": 0,
-    "abr": 48.919,
-    "format": "139 - audio only (low)"
-  },
-  {
-    "asr": 48000,
-    "filesize": 375835,
-    "format_id": "249",
-    "format_note": "low",
-    "source_preference": -1,
-    "fps": null,
-    "audio_channels": 2,
-    "height": null,
-    "quality": 2.0,
-    "has_drm": false,
-    "tbr": 53.252,
-    "filesize_approx": 375832,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429871&ei=T8svZrKvKMy9z7sPueaJwAM&ip=16.50.54.218&id=o-APg_O3UHcZWFGLI-9JfIzyLCmvHpOLG74MJMkZnCuINp&itag=249&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=audio%2Fwebm&gir=yes&clen=375835&dur=56.461&lmt=1714111945920737&mt=1714407932&fvip=3&keepalive=yes&c=ANDROID&txp=5532434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIgJ_3Mi6hti_A6aabQq3afpbVuA0pCdleM-AVa5Zzt-agCIQD8Jpir4FWsCaoCoXfToeaxKwUN-yxEdr9fn3QvmjJ-8A%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIgWltg81-E0tWWRHJ2dWsrDl75sMwyMUCZ9XsxmMmtWRsCIQDCqoPdS2tviwzPaJaw6CUzfTd2G7SMVTgEzwjxKWzC0Q%3D%3D",
-    "width": null,
-    "language": "en",
-    "language_preference": -1,
-    "preference": null,
-    "ext": "webm",
-    "vcodec": "none",
-    "acodec": "opus",
-    "dynamic_range": null,
-    "container": "webm_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "audio only",
-    "aspect_ratio": null,
-    "http_headers": {},
-    "audio_ext": "webm",
-    "video_ext": "none",
-    "vbr": 0,
-    "abr": 53.252,
-    "format": "249 - audio only (low)"
-  },
-  {
-    "asr": 48000,
-    "filesize": 492707,
-    "format_id": "250",
-    "format_note": "low",
-    "source_preference": -1,
-    "fps": null,
-    "audio_channels": 2,
-    "height": null,
-    "quality": 2.0,
-    "has_drm": false,
-    "tbr": 69.812,
-    "filesize_approx": 492706,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429871&ei=T8svZrKvKMy9z7sPueaJwAM&ip=16.50.54.218&id=o-APg_O3UHcZWFGLI-9JfIzyLCmvHpOLG74MJMkZnCuINp&itag=250&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=audio%2Fwebm&gir=yes&clen=492707&dur=56.461&lmt=1714111945849690&mt=1714407932&fvip=3&keepalive=yes&c=ANDROID&txp=5532434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIhAO1z0oTVabmKDJermCUwT__zArkkO8wtLS0k9piVnMyZAiB-EPJ6zEZRlPqJDyCGYyWka22_PmJzAT7f3BYfeuX6uA%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIgWltg81-E0tWWRHJ2dWsrDl75sMwyMUCZ9XsxmMmtWRsCIQDCqoPdS2tviwzPaJaw6CUzfTd2G7SMVTgEzwjxKWzC0Q%3D%3D",
-    "width": null,
-    "language": "en",
-    "language_preference": -1,
-    "preference": null,
-    "ext": "webm",
-    "vcodec": "none",
-    "acodec": "opus",
-    "dynamic_range": null,
-    "container": "webm_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "audio only",
-    "aspect_ratio": null,
-    "http_headers": {},
-    "audio_ext": "webm",
-    "video_ext": "none",
-    "vbr": 0,
-    "abr": 69.812,
-    "format": "250 - audio only (low)"
-  },
-  {
-    "asr": 44100,
-    "filesize": 915089,
-    "format_id": "140",
-    "format_note": "medium",
-    "source_preference": -1,
-    "fps": null,
-    "audio_channels": 2,
-    "height": null,
-    "quality": 3.0,
-    "has_drm": false,
-    "tbr": 129.583,
-    "filesize_approx": 915082,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429869&ei=TcsvZoTpAcXv4t4PuN6FiAc&ip=16.50.54.218&id=o-AK03sRhPRET_5sIM0phiVbDY2V7AAZFjUuOaDFclcxWF&itag=140&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=audio%2Fmp4&gir=yes&clen=915089&dur=56.494&lmt=1714111912835814&mt=1714407932&fvip=3&keepalive=yes&c=IOS&txp=5532434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRAIgf7vTR8k7knwnbdZiDfS1OTRuL75lsIG1wYBZyHd5WFoCIEeJmZdWJsg4tggChjY4kWKIpS2TkkOilxamt5NCRxtm&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIhAPPY-XCEkRTbT3gz0BKlSQthBKh9NzJJv8G50PAilth1AiAFnmj8EolqE7A3bBtduJp8LkvE8AhFysldsKHYb2nSeA%3D%3D",
-    "width": null,
-    "language": "en",
-    "language_preference": -1,
-    "preference": null,
-    "ext": "m4a",
-    "vcodec": "none",
-    "acodec": "mp4a.40.2",
-    "dynamic_range": null,
-    "container": "m4a_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "audio only",
-    "aspect_ratio": null,
-    "http_headers": {},
-    "audio_ext": "m4a",
-    "video_ext": "none",
-    "vbr": 0,
-    "abr": 129.583,
-    "format": "140 - audio only (medium)"
-  },
-  {
-    "asr": 48000,
-    "filesize": 966281,
-    "format_id": "251",
-    "format_note": "medium",
-    "source_preference": -1,
-    "fps": null,
-    "audio_channels": 2,
-    "height": null,
-    "quality": 3.0,
-    "has_drm": false,
-    "tbr": 136.913,
-    "filesize_approx": 966280,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429871&ei=T8svZrKvKMy9z7sPueaJwAM&ip=16.50.54.218&id=o-APg_O3UHcZWFGLI-9JfIzyLCmvHpOLG74MJMkZnCuINp&itag=251&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=audio%2Fwebm&gir=yes&clen=966281&dur=56.461&lmt=1714111945865467&mt=1714407932&fvip=3&keepalive=yes&c=ANDROID&txp=5532434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRgIhAI1YEZJhb9VE2yfRDvkvkX6Co3ykKGQv_P1shD42Y2pLAiEA-SndBzdcBLjstrdwGTRV8Si3GVOXwUDXCJH-MjoNsSw%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIgWltg81-E0tWWRHJ2dWsrDl75sMwyMUCZ9XsxmMmtWRsCIQDCqoPdS2tviwzPaJaw6CUzfTd2G7SMVTgEzwjxKWzC0Q%3D%3D",
-    "width": null,
-    "language": "en",
-    "language_preference": -1,
-    "preference": null,
-    "ext": "webm",
-    "vcodec": "none",
-    "acodec": "opus",
-    "dynamic_range": null,
-    "container": "webm_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "audio only",
-    "aspect_ratio": null,
-    "http_headers": {},
-    "audio_ext": "webm",
-    "video_ext": "none",
-    "vbr": 0,
-    "abr": 136.913,
-    "format": "251 - audio only (medium)"
-  },
-  {
-    "asr": null,
-    "filesize": 233570,
-    "format_id": "597",
-    "format_note": "144p",
-    "source_preference": -1,
-    "fps": 12,
-    "audio_channels": null,
-    "height": 144,
-    "quality": 0.0,
-    "has_drm": false,
-    "tbr": 33.136,
-    "filesize_approx": 233563,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429871&ei=T8svZrKvKMy9z7sPueaJwAM&ip=16.50.54.218&id=o-APg_O3UHcZWFGLI-9JfIzyLCmvHpOLG74MJMkZnCuINp&itag=597&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fmp4&gir=yes&clen=233570&dur=56.389&lmt=1714112412758938&mt=1714407932&fvip=3&keepalive=yes&c=ANDROID&txp=5532434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRgIhAMwJxsd86lCVKwSKgbvAvDWzuV_oI7fIVK_U2P6-MR0vAiEAyr0vn3YYGRpP4b9QOp3bVGVreFSeVjPEBnIjWABNd6E%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIgWltg81-E0tWWRHJ2dWsrDl75sMwyMUCZ9XsxmMmtWRsCIQDCqoPdS2tviwzPaJaw6CUzfTd2G7SMVTgEzwjxKWzC0Q%3D%3D",
-    "width": 256,
-    "language": null,
-    "language_preference": -1,
-    "preference": null,
-    "ext": "mp4",
-    "vcodec": "avc1.4d400b",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "container": "mp4_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "256x144",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 33.136,
-    "format": "597 - 256x144 (144p)"
-  },
-  {
-    "format_id": "602",
-    "format_index": null,
-    "url": "https://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/itag/602/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/wft/1/sgovp/clen%3D164215%3Bdur%3D56.431%3Bgir%3Dyes%3Bitag%3D598%3Blmt%3D1714112325827886/rqh/1/hls_chunk_host/rr3---sn-o097znz7.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/mh/Rz/mm/31,26/mn/sn-o097znz7,sn-a5mekn6d/ms/au,onr/mv/m/mvi/3/pl/15/initcwndbps/787500/vprv/1/playlist_type/DVR/dover/13/txp/5532434/mt/1714407932/fvip/3/short_key/1/keepalive/yes/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,wft,sgovp,rqh,xpc,vprv,playlist_type/sig/AJfQdSswRAIgHPKe1D663RVzO9lwBzAHT-iVPL1Ay_Yqo6lKLnnRg7cCIBJ9CioAuhGcjM-BxCwEsw4XhO1aW5g5FFc9RLGKDEJT/lsparams/hls_chunk_host,mh,mm,mn,ms,mv,mvi,pl,initcwndbps/lsig/AHWaYeowRQIhAMm4g38hfwtuy3wfvFCuObVP8KcV_gZQxbqMW4uD6Is8AiAVyONI1MAJjzKO0BXWvzlbf8RGqxAGWqnf8x7PtKUYwg%3D%3D/playlist/index.m3u8",
-    "manifest_url": "https://manifest.googlevideo.com/api/manifest/hls_variant/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/source/youtube/requiressl/yes/xpc/EgVo2aDSNQ%3D%3D/playback_host/rr3---sn-o097znz7.googlevideo.com/mh/Rz/mm/31%2C26/mn/sn-o097znz7%2Csn-a5mekn6d/ms/au%2Conr/mv/m/mvi/3/pl/15/hfr/1/demuxed/1/tts_caps/1/maudio/1/initcwndbps/787500/vprv/1/go/1/mt/1714407932/fvip/3/nvgoi/1/short_key/1/ncsapi/1/keepalive/yes/dover/13/itag/0/playlist_type/DVR/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Cxpc%2Chfr%2Cdemuxed%2Ctts_caps%2Cmaudio%2Cvprv%2Cgo%2Citag%2Cplaylist_type/sig/AJfQdSswRQIhALFqr05ljmiJjuzFl2TTMIfRsNuxUP2kmHUc-2MdMjMGAiBkWu4f1qKH421294MKPMeOJz1K-IPag52Ke12rvCMRSg%3D%3D/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AHWaYeowRQIhALsiEdN5q1QSndrAU9jQH39I8gjGoNX5MV5YXAvfgpBSAiBLOcDfuYFTUoyAgV9wmBAB4bljhT6AgSMEN89MGGmywA%3D%3D/file/index.m3u8",
-    "tbr": 81.481,
-    "ext": "mp4",
-    "fps": 12.0,
-    "protocol": "m3u8_native",
-    "preference": null,
-    "quality": 0,
-    "has_drm": false,
-    "width": 256,
-    "height": 144,
-    "vcodec": "vp09.00.10.08",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "source_preference": -1,
-    "resolution": "256x144",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 81.481,
-    "format": "602 - 256x144"
-  },
-  {
-    "asr": null,
-    "filesize": 164215,
-    "format_id": "598",
-    "format_note": "144p",
-    "source_preference": -1,
-    "fps": 12,
-    "audio_channels": null,
-    "height": 144,
-    "quality": 0.0,
-    "has_drm": false,
-    "tbr": 23.28,
-    "filesize_approx": 164214,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429871&ei=T8svZrKvKMy9z7sPueaJwAM&ip=16.50.54.218&id=o-APg_O3UHcZWFGLI-9JfIzyLCmvHpOLG74MJMkZnCuINp&itag=598&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fwebm&gir=yes&clen=164215&dur=56.431&lmt=1714112325827886&mt=1714407932&fvip=3&keepalive=yes&c=ANDROID&txp=5532434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIhALPAli0fl9V_rPypH2x0HmRPiWPNRi-d84CXivJhGN4aAiBFSOBdiA-KwwDLgY8TPIOfwAEBUZKFO67q0JaQbMHEcQ%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIgWltg81-E0tWWRHJ2dWsrDl75sMwyMUCZ9XsxmMmtWRsCIQDCqoPdS2tviwzPaJaw6CUzfTd2G7SMVTgEzwjxKWzC0Q%3D%3D",
-    "width": 256,
-    "language": null,
-    "language_preference": -1,
-    "preference": null,
-    "ext": "webm",
-    "vcodec": "vp9",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "container": "webm_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "256x144",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "webm",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 23.28,
-    "format": "598 - 256x144 (144p)"
-  },
-  {
-    "asr": null,
-    "filesize": 383421,
-    "format_id": "394",
-    "format_note": "144p",
-    "source_preference": -1,
-    "fps": 24,
-    "audio_channels": null,
-    "height": 144,
-    "quality": 0.0,
-    "has_drm": false,
-    "tbr": 54.356,
-    "filesize_approx": 383420,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429871&ei=T8svZrKvKMy9z7sPueaJwAM&ip=16.50.54.218&id=o-APg_O3UHcZWFGLI-9JfIzyLCmvHpOLG74MJMkZnCuINp&itag=394&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fmp4&gir=yes&clen=383421&dur=56.431&lmt=1714112317403195&mt=1714407932&fvip=3&keepalive=yes&c=ANDROID&txp=5537434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIhAPU0fKRJbz_iuQo7zfHmAUjxWyyL9GdQV4r15bwzOtPwAiBhNGr6HC8X3sitGX2ZDKG-0CDK_QtBs_KRxZRxfQaK3Q%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIgWltg81-E0tWWRHJ2dWsrDl75sMwyMUCZ9XsxmMmtWRsCIQDCqoPdS2tviwzPaJaw6CUzfTd2G7SMVTgEzwjxKWzC0Q%3D%3D",
-    "width": 256,
-    "language": null,
-    "language_preference": -1,
-    "preference": null,
-    "ext": "mp4",
-    "vcodec": "av01.0.00M.08",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "container": "mp4_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "256x144",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 54.356,
-    "format": "394 - 256x144 (144p)"
-  },
-  {
-    "format_id": "269",
-    "format_index": null,
-    "url": "https://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/itag/269/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/sgovp/clen%3D416169%3Bdur%3D56.431%3Bgir%3Dyes%3Bitag%3D160%3Blmt%3D1714113217714058/rqh/1/hls_chunk_host/rr3---sn-o097znz7.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/mh/Rz/mm/31,26/mn/sn-o097znz7,sn-a5mekn6d/ms/au,onr/mv/m/mvi/3/pl/15/initcwndbps/787500/vprv/1/playlist_type/DVR/dover/13/txp/5535434/mt/1714407932/fvip/3/short_key/1/keepalive/yes/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,sgovp,rqh,xpc,vprv,playlist_type/sig/AJfQdSswRgIhANzUjAuW1RAle2rcNtj3wPOxkZQcDBfnP5voltLuMo_yAiEAqReRj1O0i1Vsn7xhPvjDMyIO9UGn2PZNXq5f0TW7fwQ%3D/lsparams/hls_chunk_host,mh,mm,mn,ms,mv,mvi,pl,initcwndbps/lsig/AHWaYeowRQIhAJimL760z0dLo5dEFF9oi6sp2XPuZs0sRtVd-dPoxABTAiAq8QoyAcpWlz_XoR4wgqTIgJ6X6VoHANI69ypQVPWMAQ%3D%3D/playlist/index.m3u8",
-    "manifest_url": "https://manifest.googlevideo.com/api/manifest/hls_variant/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/source/youtube/requiressl/yes/xpc/EgVo2aDSNQ%3D%3D/playback_host/rr3---sn-o097znz7.googlevideo.com/mh/Rz/mm/31%2C26/mn/sn-o097znz7%2Csn-a5mekn6d/ms/au%2Conr/mv/m/mvi/3/pl/15/hfr/1/demuxed/1/tts_caps/1/maudio/1/initcwndbps/787500/vprv/1/go/1/mt/1714407932/fvip/3/nvgoi/1/short_key/1/ncsapi/1/keepalive/yes/dover/13/itag/0/playlist_type/DVR/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Cxpc%2Chfr%2Cdemuxed%2Ctts_caps%2Cmaudio%2Cvprv%2Cgo%2Citag%2Cplaylist_type/sig/AJfQdSswRQIhALFqr05ljmiJjuzFl2TTMIfRsNuxUP2kmHUc-2MdMjMGAiBkWu4f1qKH421294MKPMeOJz1K-IPag52Ke12rvCMRSg%3D%3D/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AHWaYeowRQIhALsiEdN5q1QSndrAU9jQH39I8gjGoNX5MV5YXAvfgpBSAiBLOcDfuYFTUoyAgV9wmBAB4bljhT6AgSMEN89MGGmywA%3D%3D/file/index.m3u8",
-    "tbr": 155.857,
-    "ext": "mp4",
-    "fps": 24.0,
-    "protocol": "m3u8_native",
-    "preference": null,
-    "quality": 0,
-    "has_drm": false,
-    "width": 256,
-    "height": 144,
-    "vcodec": "avc1.4D400C",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "source_preference": -1,
-    "resolution": "256x144",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 155.857,
-    "format": "269 - 256x144"
-  },
-  {
-    "asr": null,
-    "filesize": 416169,
-    "format_id": "160",
-    "format_note": "144p",
-    "source_preference": -1,
-    "fps": 24,
-    "audio_channels": null,
-    "height": 144,
-    "quality": 0.0,
-    "has_drm": false,
-    "tbr": 58.998,
-    "filesize_approx": 416164,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429869&ei=TcsvZoTpAcXv4t4PuN6FiAc&ip=16.50.54.218&id=o-AK03sRhPRET_5sIM0phiVbDY2V7AAZFjUuOaDFclcxWF&itag=160&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fmp4&gir=yes&clen=416169&dur=56.431&lmt=1714113217714058&mt=1714407932&fvip=3&keepalive=yes&c=IOS&txp=5535434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIgPP0mT2HSrFSf6Z4sdmZKDzUnFoDfDM0_fnazazTCB78CIQCCS2xx_w_8kQpYsuKtkJE3Ju_NPCFFOyx3AJQ0mgFe9Q%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIhAPPY-XCEkRTbT3gz0BKlSQthBKh9NzJJv8G50PAilth1AiAFnmj8EolqE7A3bBtduJp8LkvE8AhFysldsKHYb2nSeA%3D%3D",
-    "width": 256,
-    "language": null,
-    "language_preference": -1,
-    "preference": null,
-    "ext": "mp4",
-    "vcodec": "avc1.4D400C",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "container": "mp4_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "256x144",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 58.998,
-    "format": "160 - 256x144 (144p)"
-  },
-  {
-    "format_id": "603",
-    "format_index": null,
-    "url": "https://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/itag/603/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/wft/1/sgovp/clen%3D587948%3Bdur%3D56.431%3Bgir%3Dyes%3Bitag%3D278%3Blmt%3D1714115783888527/rqh/1/hls_chunk_host/rr3---sn-o097znz7.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/mh/Rz/mm/31,26/mn/sn-o097znz7,sn-a5mekn6d/ms/au,onr/mv/m/mvi/3/pl/15/initcwndbps/787500/vprv/1/playlist_type/DVR/dover/13/txp/5535434/mt/1714407932/fvip/3/short_key/1/keepalive/yes/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,wft,sgovp,rqh,xpc,vprv,playlist_type/sig/AJfQdSswRAIgBPFPKvR-mAfF235O4yE8qboXVqexW-gghlx1tKZxhHACIHVs6XXmJAtxCkJMKeXJipVW-LgCqITo92EiYBAZr0XX/lsparams/hls_chunk_host,mh,mm,mn,ms,mv,mvi,pl,initcwndbps/lsig/AHWaYeowRAIgSWcqFPKp1F3wmmcM-noKCr1vAwzWSUi4DovhVPA8aoQCIBa4sUfT-4X1kIkoIhgD_7q4uDSRXUDHjpFnZfnx6bpq/playlist/index.m3u8",
-    "manifest_url": "https://manifest.googlevideo.com/api/manifest/hls_variant/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/source/youtube/requiressl/yes/xpc/EgVo2aDSNQ%3D%3D/playback_host/rr3---sn-o097znz7.googlevideo.com/mh/Rz/mm/31%2C26/mn/sn-o097znz7%2Csn-a5mekn6d/ms/au%2Conr/mv/m/mvi/3/pl/15/hfr/1/demuxed/1/tts_caps/1/maudio/1/initcwndbps/787500/vprv/1/go/1/mt/1714407932/fvip/3/nvgoi/1/short_key/1/ncsapi/1/keepalive/yes/dover/13/itag/0/playlist_type/DVR/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Cxpc%2Chfr%2Cdemuxed%2Ctts_caps%2Cmaudio%2Cvprv%2Cgo%2Citag%2Cplaylist_type/sig/AJfQdSswRQIhALFqr05ljmiJjuzFl2TTMIfRsNuxUP2kmHUc-2MdMjMGAiBkWu4f1qKH421294MKPMeOJz1K-IPag52Ke12rvCMRSg%3D%3D/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AHWaYeowRQIhALsiEdN5q1QSndrAU9jQH39I8gjGoNX5MV5YXAvfgpBSAiBLOcDfuYFTUoyAgV9wmBAB4bljhT6AgSMEN89MGGmywA%3D%3D/file/index.m3u8",
-    "tbr": 152.179,
-    "ext": "mp4",
-    "fps": 24.0,
-    "protocol": "m3u8_native",
-    "preference": null,
-    "quality": 0,
-    "has_drm": false,
-    "width": 256,
-    "height": 144,
-    "vcodec": "vp09.00.11.08",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "source_preference": -1,
-    "resolution": "256x144",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 152.179,
-    "format": "603 - 256x144"
-  },
-  {
-    "asr": null,
-    "filesize": 587948,
-    "format_id": "278",
-    "format_note": "144p",
-    "source_preference": -1,
-    "fps": 24,
-    "audio_channels": null,
-    "height": 144,
-    "quality": 0.0,
-    "has_drm": false,
-    "tbr": 83.351,
-    "filesize_approx": 587947,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429869&ei=TcsvZoTpAcXv4t4PuN6FiAc&ip=16.50.54.218&id=o-AK03sRhPRET_5sIM0phiVbDY2V7AAZFjUuOaDFclcxWF&itag=278&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fwebm&gir=yes&clen=587948&dur=56.431&lmt=1714115783888527&mt=1714407932&fvip=3&keepalive=yes&c=IOS&txp=5535434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRgIhAKydgrVqnZfvCyoNk3F3fggnjCQ2vTNaR5iYoIZRuA8gAiEA8SDQ0tc-9fHAo5qIcdI46Hn2e5GlA-_Ma4RVnjuwQ0A%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIhAPPY-XCEkRTbT3gz0BKlSQthBKh9NzJJv8G50PAilth1AiAFnmj8EolqE7A3bBtduJp8LkvE8AhFysldsKHYb2nSeA%3D%3D",
-    "width": 256,
-    "language": null,
-    "language_preference": -1,
-    "preference": null,
-    "ext": "webm",
-    "vcodec": "vp09.00.11.08",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "container": "webm_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "256x144",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "webm",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 83.351,
-    "format": "278 - 256x144 (144p)"
-  },
-  {
-    "asr": null,
-    "filesize": 508109,
-    "format_id": "395",
-    "format_note": "240p",
-    "source_preference": -1,
-    "fps": 24,
-    "audio_channels": null,
-    "height": 240,
-    "quality": 5.0,
-    "has_drm": false,
-    "tbr": 72.032,
-    "filesize_approx": 508104,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429871&ei=T8svZrKvKMy9z7sPueaJwAM&ip=16.50.54.218&id=o-APg_O3UHcZWFGLI-9JfIzyLCmvHpOLG74MJMkZnCuINp&itag=395&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fmp4&gir=yes&clen=508109&dur=56.431&lmt=1714112505476318&mt=1714407932&fvip=3&keepalive=yes&c=ANDROID&txp=5537434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRgIhAO0xMVmbbInWi8Eg2jzwA9SnpaJUaRA-TZPm4gCjI71qAiEA0WBR_L76uk-pMqidgVJIJzgUTVKeiwExj2j3Z9QFAGU%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIgWltg81-E0tWWRHJ2dWsrDl75sMwyMUCZ9XsxmMmtWRsCIQDCqoPdS2tviwzPaJaw6CUzfTd2G7SMVTgEzwjxKWzC0Q%3D%3D",
-    "width": 426,
-    "language": null,
-    "language_preference": -1,
-    "preference": null,
-    "ext": "mp4",
-    "vcodec": "av01.0.00M.08",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "container": "mp4_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "426x240",
-    "aspect_ratio": 1.77,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 72.032,
-    "format": "395 - 426x240 (240p)"
-  },
-  {
-    "format_id": "229",
-    "format_index": null,
-    "url": "https://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/itag/229/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/sgovp/clen%3D706206%3Bdur%3D56.431%3Bgir%3Dyes%3Bitag%3D133%3Blmt%3D1714113294864297/rqh/1/hls_chunk_host/rr3---sn-o097znz7.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/mh/Rz/mm/31,26/mn/sn-o097znz7,sn-a5mekn6d/ms/au,onr/mv/m/mvi/3/pl/15/initcwndbps/787500/vprv/1/playlist_type/DVR/dover/13/txp/5535434/mt/1714407932/fvip/3/short_key/1/keepalive/yes/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,sgovp,rqh,xpc,vprv,playlist_type/sig/AJfQdSswRQIgEzreCVp1KtssQHLa0qMybPWecFtuOEHznD8T__bOtzUCIQCxrL5xEJrUBGC0lSvqFUfyvV3NlOiJI_qvG0iYJ_m5Bg%3D%3D/lsparams/hls_chunk_host,mh,mm,mn,ms,mv,mvi,pl,initcwndbps/lsig/AHWaYeowRgIhAMj3nsbFbLfsSCmbA8mF9uw6x_2vnEw_4wf3uOO0YQ07AiEAlNkjJGIpHUiTaqcfDooH-OqAa0BdS1Ah3TbJSk0lYw0%3D/playlist/index.m3u8",
-    "manifest_url": "https://manifest.googlevideo.com/api/manifest/hls_variant/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/source/youtube/requiressl/yes/xpc/EgVo2aDSNQ%3D%3D/playback_host/rr3---sn-o097znz7.googlevideo.com/mh/Rz/mm/31%2C26/mn/sn-o097znz7%2Csn-a5mekn6d/ms/au%2Conr/mv/m/mvi/3/pl/15/hfr/1/demuxed/1/tts_caps/1/maudio/1/initcwndbps/787500/vprv/1/go/1/mt/1714407932/fvip/3/nvgoi/1/short_key/1/ncsapi/1/keepalive/yes/dover/13/itag/0/playlist_type/DVR/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Cxpc%2Chfr%2Cdemuxed%2Ctts_caps%2Cmaudio%2Cvprv%2Cgo%2Citag%2Cplaylist_type/sig/AJfQdSswRQIhALFqr05ljmiJjuzFl2TTMIfRsNuxUP2kmHUc-2MdMjMGAiBkWu4f1qKH421294MKPMeOJz1K-IPag52Ke12rvCMRSg%3D%3D/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AHWaYeowRQIhALsiEdN5q1QSndrAU9jQH39I8gjGoNX5MV5YXAvfgpBSAiBLOcDfuYFTUoyAgV9wmBAB4bljhT6AgSMEN89MGGmywA%3D%3D/file/index.m3u8",
-    "tbr": 227.061,
-    "ext": "mp4",
-    "fps": 24.0,
-    "protocol": "m3u8_native",
-    "preference": null,
-    "quality": 5,
-    "has_drm": false,
-    "width": 426,
-    "height": 240,
-    "vcodec": "avc1.4D4015",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "source_preference": -1,
-    "resolution": "426x240",
-    "aspect_ratio": 1.77,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 227.061,
-    "format": "229 - 426x240"
-  },
-  {
-    "asr": null,
-    "filesize": 706206,
-    "format_id": "133",
-    "format_note": "240p",
-    "source_preference": -1,
-    "fps": 24,
-    "audio_channels": null,
-    "height": 240,
-    "quality": 5.0,
-    "has_drm": false,
-    "tbr": 100.116,
-    "filesize_approx": 706205,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429869&ei=TcsvZoTpAcXv4t4PuN6FiAc&ip=16.50.54.218&id=o-AK03sRhPRET_5sIM0phiVbDY2V7AAZFjUuOaDFclcxWF&itag=133&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fmp4&gir=yes&clen=706206&dur=56.431&lmt=1714113294864297&mt=1714407932&fvip=3&keepalive=yes&c=IOS&txp=5535434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRgIhANlBrbNmUXcnFiImw2bFLywzwnIjFFB9XmUqS0ANtILDAiEA_ween-Wm5PzOesBjynBnxgDi00YGs9caETcL6qxoFQM%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIhAPPY-XCEkRTbT3gz0BKlSQthBKh9NzJJv8G50PAilth1AiAFnmj8EolqE7A3bBtduJp8LkvE8AhFysldsKHYb2nSeA%3D%3D",
-    "width": 426,
-    "language": null,
-    "language_preference": -1,
-    "preference": null,
-    "ext": "mp4",
-    "vcodec": "avc1.4D4015",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "container": "mp4_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "426x240",
-    "aspect_ratio": 1.77,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 100.116,
-    "format": "133 - 426x240 (240p)"
-  },
-  {
-    "format_id": "604",
-    "format_index": null,
-    "url": "https://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/itag/604/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/wft/1/sgovp/clen%3D691679%3Bdur%3D56.431%3Bgir%3Dyes%3Bitag%3D242%3Blmt%3D1714115783443400/rqh/1/hls_chunk_host/rr3---sn-o097znz7.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/mh/Rz/mm/31,26/mn/sn-o097znz7,sn-a5mekn6d/ms/au,onr/mv/m/mvi/3/pl/15/initcwndbps/787500/vprv/1/playlist_type/DVR/dover/13/txp/5535434/mt/1714407932/fvip/3/short_key/1/keepalive/yes/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,wft,sgovp,rqh,xpc,vprv,playlist_type/sig/AJfQdSswRAIgS7a-N22jux6T1DiXmSK7OJUJ9iD1mJ6k3NvmaKdwa0oCIHkqczUfhQyY-5i6-EPzJaa4LmZBjc4jwq0qwBAc3g4-/lsparams/hls_chunk_host,mh,mm,mn,ms,mv,mvi,pl,initcwndbps/lsig/AHWaYeowRQIhAJW2-nl6K_1X94m8XsKGmvm_GE3ezdI8nu6ULuSDWcVgAiABbNE-hHlfcjGKK0nDGVpzi_odc1HQ5Joaqhl67LNWWA%3D%3D/playlist/index.m3u8",
-    "manifest_url": "https://manifest.googlevideo.com/api/manifest/hls_variant/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/source/youtube/requiressl/yes/xpc/EgVo2aDSNQ%3D%3D/playback_host/rr3---sn-o097znz7.googlevideo.com/mh/Rz/mm/31%2C26/mn/sn-o097znz7%2Csn-a5mekn6d/ms/au%2Conr/mv/m/mvi/3/pl/15/hfr/1/demuxed/1/tts_caps/1/maudio/1/initcwndbps/787500/vprv/1/go/1/mt/1714407932/fvip/3/nvgoi/1/short_key/1/ncsapi/1/keepalive/yes/dover/13/itag/0/playlist_type/DVR/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Cxpc%2Chfr%2Cdemuxed%2Ctts_caps%2Cmaudio%2Cvprv%2Cgo%2Citag%2Cplaylist_type/sig/AJfQdSswRQIhALFqr05ljmiJjuzFl2TTMIfRsNuxUP2kmHUc-2MdMjMGAiBkWu4f1qKH421294MKPMeOJz1K-IPag52Ke12rvCMRSg%3D%3D/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AHWaYeowRQIhALsiEdN5q1QSndrAU9jQH39I8gjGoNX5MV5YXAvfgpBSAiBLOcDfuYFTUoyAgV9wmBAB4bljhT6AgSMEN89MGGmywA%3D%3D/file/index.m3u8",
-    "tbr": 237.052,
-    "ext": "mp4",
-    "fps": 24.0,
-    "protocol": "m3u8_native",
-    "preference": null,
-    "quality": 5,
-    "has_drm": false,
-    "width": 426,
-    "height": 240,
-    "vcodec": "vp09.00.20.08",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "source_preference": -1,
-    "resolution": "426x240",
-    "aspect_ratio": 1.77,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 237.052,
-    "format": "604 - 426x240"
-  },
-  {
-    "asr": null,
-    "filesize": 691679,
-    "format_id": "242",
-    "format_note": "240p",
-    "source_preference": -1,
-    "fps": 24,
-    "audio_channels": null,
-    "height": 240,
-    "quality": 5.0,
-    "has_drm": false,
-    "tbr": 98.056,
-    "filesize_approx": 691674,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429869&ei=TcsvZoTpAcXv4t4PuN6FiAc&ip=16.50.54.218&id=o-AK03sRhPRET_5sIM0phiVbDY2V7AAZFjUuOaDFclcxWF&itag=242&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fwebm&gir=yes&clen=691679&dur=56.431&lmt=1714115783443400&mt=1714407932&fvip=3&keepalive=yes&c=IOS&txp=5535434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIgTw9Um2uXRdrIwSROlarhhGaCAXNtWXSUZxge2cE3yWwCIQDiXlU7Op2btDfiKzR1VHId4n54IiNuOGCIsDCxVmcY7w%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIhAPPY-XCEkRTbT3gz0BKlSQthBKh9NzJJv8G50PAilth1AiAFnmj8EolqE7A3bBtduJp8LkvE8AhFysldsKHYb2nSeA%3D%3D",
-    "width": 426,
-    "language": null,
-    "language_preference": -1,
-    "preference": null,
-    "ext": "webm",
-    "vcodec": "vp09.00.20.08",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "container": "webm_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "426x240",
-    "aspect_ratio": 1.77,
-    "http_headers": {},
-    "video_ext": "webm",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 98.056,
-    "format": "242 - 426x240 (240p)"
-  },
-  {
-    "asr": null,
-    "filesize": 866629,
-    "format_id": "396",
-    "format_note": "360p",
-    "source_preference": -1,
-    "fps": 24,
-    "audio_channels": null,
-    "height": 360,
-    "quality": 6.0,
-    "has_drm": false,
-    "tbr": 122.858,
-    "filesize_approx": 866624,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429871&ei=T8svZrKvKMy9z7sPueaJwAM&ip=16.50.54.218&id=o-APg_O3UHcZWFGLI-9JfIzyLCmvHpOLG74MJMkZnCuINp&itag=396&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fmp4&gir=yes&clen=866629&dur=56.431&lmt=1714112722474388&mt=1714407932&fvip=3&keepalive=yes&c=ANDROID&txp=5537434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRgIhAPokORxHojootC9cJpLKy2b-y03uB-rP5FdbKu0JSDOzAiEAy5yZG1dWTlgTRwfjr_c0sSAACl9eOaBj9pzRrsuhI5s%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIgWltg81-E0tWWRHJ2dWsrDl75sMwyMUCZ9XsxmMmtWRsCIQDCqoPdS2tviwzPaJaw6CUzfTd2G7SMVTgEzwjxKWzC0Q%3D%3D",
-    "width": 640,
-    "language": null,
-    "language_preference": -1,
-    "preference": null,
-    "ext": "mp4",
-    "vcodec": "av01.0.01M.08",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "container": "mp4_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "640x360",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 122.858,
-    "format": "396 - 640x360 (360p)"
-  },
-  {
-    "format_id": "230",
-    "format_index": null,
-    "url": "https://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/itag/230/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/sgovp/clen%3D1306032%3Bdur%3D56.431%3Bgir%3Dyes%3Bitag%3D134%3Blmt%3D1714113225354024/rqh/1/hls_chunk_host/rr3---sn-o097znz7.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/mh/Rz/mm/31,26/mn/sn-o097znz7,sn-a5mekn6d/ms/au,onr/mv/m/mvi/3/pl/15/initcwndbps/787500/vprv/1/playlist_type/DVR/dover/13/txp/5535434/mt/1714407932/fvip/3/short_key/1/keepalive/yes/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,sgovp,rqh,xpc,vprv,playlist_type/sig/AJfQdSswRAIgYQaBHFXZXYDgGghfjiR6TWKjGfgRfh0T4QQWEqkcA8UCIA0FPPmsGT44peD2h-_9I21w7micyZhp-XBJ4Aik8pwV/lsparams/hls_chunk_host,mh,mm,mn,ms,mv,mvi,pl,initcwndbps/lsig/AHWaYeowRgIhAMUI-pZ2cmKEsOmpjSQlgXEw5zUTeD5cq830vtVf8eDXAiEAxJn4oK9vXZ24ZN0nqXXc-DpOaKP2RT2HhZy05a4ZWto%3D/playlist/index.m3u8",
-    "manifest_url": "https://manifest.googlevideo.com/api/manifest/hls_variant/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/source/youtube/requiressl/yes/xpc/EgVo2aDSNQ%3D%3D/playback_host/rr3---sn-o097znz7.googlevideo.com/mh/Rz/mm/31%2C26/mn/sn-o097znz7%2Csn-a5mekn6d/ms/au%2Conr/mv/m/mvi/3/pl/15/hfr/1/demuxed/1/tts_caps/1/maudio/1/initcwndbps/787500/vprv/1/go/1/mt/1714407932/fvip/3/nvgoi/1/short_key/1/ncsapi/1/keepalive/yes/dover/13/itag/0/playlist_type/DVR/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Cxpc%2Chfr%2Cdemuxed%2Ctts_caps%2Cmaudio%2Cvprv%2Cgo%2Citag%2Cplaylist_type/sig/AJfQdSswRQIhALFqr05ljmiJjuzFl2TTMIfRsNuxUP2kmHUc-2MdMjMGAiBkWu4f1qKH421294MKPMeOJz1K-IPag52Ke12rvCMRSg%3D%3D/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AHWaYeowRQIhALsiEdN5q1QSndrAU9jQH39I8gjGoNX5MV5YXAvfgpBSAiBLOcDfuYFTUoyAgV9wmBAB4bljhT6AgSMEN89MGGmywA%3D%3D/file/index.m3u8",
-    "tbr": 460.173,
-    "ext": "mp4",
-    "fps": 24.0,
-    "protocol": "m3u8_native",
-    "preference": null,
-    "quality": 6,
-    "has_drm": false,
-    "width": 640,
-    "height": 360,
-    "vcodec": "avc1.4D401E",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "source_preference": -1,
-    "resolution": "640x360",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 460.173,
-    "format": "230 - 640x360"
-  },
-  {
-    "asr": null,
-    "filesize": 1306032,
-    "format_id": "134",
-    "format_note": "360p",
-    "source_preference": -1,
-    "fps": 24,
-    "audio_channels": null,
-    "height": 360,
-    "quality": 6.0,
-    "has_drm": false,
-    "tbr": 185.15,
-    "filesize_approx": 1306024,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429869&ei=TcsvZoTpAcXv4t4PuN6FiAc&ip=16.50.54.218&id=o-AK03sRhPRET_5sIM0phiVbDY2V7AAZFjUuOaDFclcxWF&itag=134&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fmp4&gir=yes&clen=1306032&dur=56.431&lmt=1714113225354024&mt=1714407932&fvip=3&keepalive=yes&c=IOS&txp=5535434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIhAK_i4Sno1T0599YT4pZ06TJu28Y2RYEluJnz3JCP5ieyAiAkW8AH4u0XWKOskTRSYx7sIvKPd43C9LUnjx8M4GL7Kw%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIhAPPY-XCEkRTbT3gz0BKlSQthBKh9NzJJv8G50PAilth1AiAFnmj8EolqE7A3bBtduJp8LkvE8AhFysldsKHYb2nSeA%3D%3D",
-    "width": 640,
-    "language": null,
-    "language_preference": -1,
-    "preference": null,
-    "ext": "mp4",
-    "vcodec": "avc1.4D401E",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "container": "mp4_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "640x360",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 185.15,
-    "format": "134 - 640x360 (360p)"
-  },
-  {
-    "asr": 44100,
-    "filesize": 3541733,
-    "format_id": "18",
-    "format_note": "360p",
-    "source_preference": -1,
-    "fps": 24,
-    "audio_channels": 2,
-    "height": 360,
-    "quality": 6.0,
-    "has_drm": false,
-    "tbr": 501.537,
-    "filesize_approx": 3541728,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429871&ei=T8svZrKvKMy9z7sPueaJwAM&ip=16.50.54.218&id=o-APg_O3UHcZWFGLI-9JfIzyLCmvHpOLG74MJMkZnCuINp&itag=18&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fmp4&gir=yes&clen=3541733&ratebypass=yes&dur=56.494&lmt=1714112432998625&mt=1714407932&fvip=3&c=ANDROID&txp=5538434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cratebypass%2Cdur%2Clmt&sig=AJfQdSswRQIgMxgi_qCRhhL8u-TsRwhFGLmuRI63BOMdc15hhMcU058CIQDTks9cSwwwk6ijVyxmp7LGHq5_pT3p23LkKGvgStZo4A%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIgWltg81-E0tWWRHJ2dWsrDl75sMwyMUCZ9XsxmMmtWRsCIQDCqoPdS2tviwzPaJaw6CUzfTd2G7SMVTgEzwjxKWzC0Q%3D%3D",
-    "width": 640,
-    "language": "en",
-    "language_preference": -1,
-    "preference": null,
-    "ext": "mp4",
-    "vcodec": "avc1.42001E",
-    "acodec": "mp4a.40.2",
-    "dynamic_range": "SDR",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "640x360",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "vbr": null,
-    "abr": null,
-    "format": "18 - 640x360 (360p)"
-  },
-  {
-    "format_id": "605",
-    "format_index": null,
-    "url": "https://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/itag/605/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/wft/1/sgovp/clen%3D1150051%3Bdur%3D56.431%3Bgir%3Dyes%3Bitag%3D243%3Blmt%3D1714115783114374/rqh/1/hls_chunk_host/rr3---sn-o097znz7.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/mh/Rz/mm/31,26/mn/sn-o097znz7,sn-a5mekn6d/ms/au,onr/mv/m/mvi/3/pl/15/initcwndbps/787500/vprv/1/playlist_type/DVR/dover/13/txp/5535434/mt/1714407932/fvip/3/short_key/1/keepalive/yes/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,wft,sgovp,rqh,xpc,vprv,playlist_type/sig/AJfQdSswRAIgeWqpWB4U4FOmvOdvLHOTx-thUs5ycPG2nSMMa_HGhucCIGBUbfH4EQEO5DuQF_VM3WAp9B5UxS40Ie10aS7zqIIG/lsparams/hls_chunk_host,mh,mm,mn,ms,mv,mvi,pl,initcwndbps/lsig/AHWaYeowRQIhAN65jd-7PfnzhYzSLUzixEqtLIGERAQFY9GHecSd2cPLAiAyb7VkHEu8Jd6c14A1fN5fx2qFdJtceDsOn79rm6jj1Q%3D%3D/playlist/index.m3u8",
-    "manifest_url": "https://manifest.googlevideo.com/api/manifest/hls_variant/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/source/youtube/requiressl/yes/xpc/EgVo2aDSNQ%3D%3D/playback_host/rr3---sn-o097znz7.googlevideo.com/mh/Rz/mm/31%2C26/mn/sn-o097znz7%2Csn-a5mekn6d/ms/au%2Conr/mv/m/mvi/3/pl/15/hfr/1/demuxed/1/tts_caps/1/maudio/1/initcwndbps/787500/vprv/1/go/1/mt/1714407932/fvip/3/nvgoi/1/short_key/1/ncsapi/1/keepalive/yes/dover/13/itag/0/playlist_type/DVR/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Cxpc%2Chfr%2Cdemuxed%2Ctts_caps%2Cmaudio%2Cvprv%2Cgo%2Citag%2Cplaylist_type/sig/AJfQdSswRQIhALFqr05ljmiJjuzFl2TTMIfRsNuxUP2kmHUc-2MdMjMGAiBkWu4f1qKH421294MKPMeOJz1K-IPag52Ke12rvCMRSg%3D%3D/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AHWaYeowRQIhALsiEdN5q1QSndrAU9jQH39I8gjGoNX5MV5YXAvfgpBSAiBLOcDfuYFTUoyAgV9wmBAB4bljhT6AgSMEN89MGGmywA%3D%3D/file/index.m3u8",
-    "tbr": 442.375,
-    "ext": "mp4",
-    "fps": 24.0,
-    "protocol": "m3u8_native",
-    "preference": null,
-    "quality": 6,
-    "has_drm": false,
-    "width": 640,
-    "height": 360,
-    "vcodec": "vp09.00.21.08",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "source_preference": -1,
-    "resolution": "640x360",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 442.375,
-    "format": "605 - 640x360"
-  },
-  {
-    "asr": null,
-    "filesize": 1150051,
-    "format_id": "243",
-    "format_note": "360p",
-    "source_preference": -1,
-    "fps": 24,
-    "audio_channels": null,
-    "height": 360,
-    "quality": 6.0,
-    "has_drm": false,
-    "tbr": 163.038,
-    "filesize_approx": 1150049,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429869&ei=TcsvZoTpAcXv4t4PuN6FiAc&ip=16.50.54.218&id=o-AK03sRhPRET_5sIM0phiVbDY2V7AAZFjUuOaDFclcxWF&itag=243&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fwebm&gir=yes&clen=1150051&dur=56.431&lmt=1714115783114374&mt=1714407932&fvip=3&keepalive=yes&c=IOS&txp=5535434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIgWny48YvSWlKjihH_cAU7AV_IlgQNPgZ6gUZf3OCPk9ECIQD9ofgKTcyYysfX1mHUQWZuTzl49gsof92AXLB3UrfaVA%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIhAPPY-XCEkRTbT3gz0BKlSQthBKh9NzJJv8G50PAilth1AiAFnmj8EolqE7A3bBtduJp8LkvE8AhFysldsKHYb2nSeA%3D%3D",
-    "width": 640,
-    "language": null,
-    "language_preference": -1,
-    "preference": null,
-    "ext": "webm",
-    "vcodec": "vp09.00.21.08",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "container": "webm_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "640x360",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "webm",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 163.038,
-    "format": "243 - 640x360 (360p)"
-  },
-  {
-    "asr": null,
-    "filesize": 1400333,
-    "format_id": "397",
-    "format_note": "480p",
-    "source_preference": -1,
-    "fps": 24,
-    "audio_channels": null,
-    "height": 480,
-    "quality": 7.0,
-    "has_drm": false,
-    "tbr": 198.519,
-    "filesize_approx": 1400328,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429871&ei=T8svZrKvKMy9z7sPueaJwAM&ip=16.50.54.218&id=o-APg_O3UHcZWFGLI-9JfIzyLCmvHpOLG74MJMkZnCuINp&itag=397&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fmp4&gir=yes&clen=1400333&dur=56.431&lmt=1714113150828164&mt=1714407932&fvip=3&keepalive=yes&c=ANDROID&txp=5537434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRAIgB1GNugrebVVmRCJ1DTOTDD979jrRZ1R8tVTgF9iUpfYCIFQvrnL8v6LIymiDGQ5ckDj-5PoJtHqbcFEdWhmftiNb&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIgWltg81-E0tWWRHJ2dWsrDl75sMwyMUCZ9XsxmMmtWRsCIQDCqoPdS2tviwzPaJaw6CUzfTd2G7SMVTgEzwjxKWzC0Q%3D%3D",
-    "width": 854,
-    "language": null,
-    "language_preference": -1,
-    "preference": null,
-    "ext": "mp4",
-    "vcodec": "av01.0.04M.08",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "container": "mp4_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "854x480",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 198.519,
-    "format": "397 - 854x480 (480p)"
-  },
-  {
-    "format_id": "231",
-    "format_index": null,
-    "url": "https://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/itag/231/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/sgovp/clen%3D2015068%3Bdur%3D56.431%3Bgir%3Dyes%3Bitag%3D135%3Blmt%3D1714113217714066/rqh/1/hls_chunk_host/rr3---sn-o097znz7.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/mh/Rz/mm/31,26/mn/sn-o097znz7,sn-a5mekn6d/ms/au,onr/mv/m/mvi/3/pl/15/initcwndbps/787500/vprv/1/playlist_type/DVR/dover/13/txp/5535434/mt/1714407932/fvip/3/short_key/1/keepalive/yes/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,sgovp,rqh,xpc,vprv,playlist_type/sig/AJfQdSswRgIhAPoW57eTIm-6vIdFE78C9jQqqOSQefohBeG1R7YgUo34AiEAmZJDJJ4X0O0jCE8g1QDz8b1LaQej65ayWxd0XnlZMq4%3D/lsparams/hls_chunk_host,mh,mm,mn,ms,mv,mvi,pl,initcwndbps/lsig/AHWaYeowRAIgTeJ24XjpHueXhxo8ZQ1NeMwAf3JGFCExojRQqZlC4L4CIA8cMo2kfR2o9J7lSFa3syxgoSGXvznjZYKrWtq-x2xX/playlist/index.m3u8",
-    "manifest_url": "https://manifest.googlevideo.com/api/manifest/hls_variant/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/source/youtube/requiressl/yes/xpc/EgVo2aDSNQ%3D%3D/playback_host/rr3---sn-o097znz7.googlevideo.com/mh/Rz/mm/31%2C26/mn/sn-o097znz7%2Csn-a5mekn6d/ms/au%2Conr/mv/m/mvi/3/pl/15/hfr/1/demuxed/1/tts_caps/1/maudio/1/initcwndbps/787500/vprv/1/go/1/mt/1714407932/fvip/3/nvgoi/1/short_key/1/ncsapi/1/keepalive/yes/dover/13/itag/0/playlist_type/DVR/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Cxpc%2Chfr%2Cdemuxed%2Ctts_caps%2Cmaudio%2Cvprv%2Cgo%2Citag%2Cplaylist_type/sig/AJfQdSswRQIhALFqr05ljmiJjuzFl2TTMIfRsNuxUP2kmHUc-2MdMjMGAiBkWu4f1qKH421294MKPMeOJz1K-IPag52Ke12rvCMRSg%3D%3D/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AHWaYeowRQIhALsiEdN5q1QSndrAU9jQH39I8gjGoNX5MV5YXAvfgpBSAiBLOcDfuYFTUoyAgV9wmBAB4bljhT6AgSMEN89MGGmywA%3D%3D/file/index.m3u8",
-    "tbr": 630.977,
-    "ext": "mp4",
-    "fps": 24.0,
-    "protocol": "m3u8_native",
-    "preference": null,
-    "quality": 7,
-    "has_drm": false,
-    "width": 854,
-    "height": 480,
-    "vcodec": "avc1.4D401E",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "source_preference": -1,
-    "resolution": "854x480",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 630.977,
-    "format": "231 - 854x480"
-  },
-  {
-    "asr": null,
-    "filesize": 2015068,
-    "format_id": "135",
-    "format_note": "480p",
-    "source_preference": -1,
-    "fps": 24,
-    "audio_channels": null,
-    "height": 480,
-    "quality": 7.0,
-    "has_drm": false,
-    "tbr": 285.668,
-    "filesize_approx": 2015066,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429869&ei=TcsvZoTpAcXv4t4PuN6FiAc&ip=16.50.54.218&id=o-AK03sRhPRET_5sIM0phiVbDY2V7AAZFjUuOaDFclcxWF&itag=135&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fmp4&gir=yes&clen=2015068&dur=56.431&lmt=1714113217714066&mt=1714407932&fvip=3&keepalive=yes&c=IOS&txp=5535434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRAIgQP-rgjZ0kAM907YBC9N-qSZOHIT_sdU4WTec8KikmgQCIHjZVUaA0-qwsB_nisRCDlv752Nx_5jeDll11yjqs9tF&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIhAPPY-XCEkRTbT3gz0BKlSQthBKh9NzJJv8G50PAilth1AiAFnmj8EolqE7A3bBtduJp8LkvE8AhFysldsKHYb2nSeA%3D%3D",
-    "width": 854,
-    "language": null,
-    "language_preference": -1,
-    "preference": null,
-    "ext": "mp4",
-    "vcodec": "avc1.4D401E",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "container": "mp4_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "854x480",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 285.668,
-    "format": "135 - 854x480 (480p)"
-  },
-  {
-    "format_id": "606",
-    "format_index": null,
-    "url": "https://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/itag/606/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/wft/1/sgovp/clen%3D1592781%3Bdur%3D56.431%3Bgir%3Dyes%3Bitag%3D244%3Blmt%3D1714115782900773/rqh/1/hls_chunk_host/rr3---sn-o097znz7.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/mh/Rz/mm/31,26/mn/sn-o097znz7,sn-a5mekn6d/ms/au,onr/mv/m/mvi/3/pl/15/initcwndbps/787500/vprv/1/playlist_type/DVR/dover/13/txp/5535434/mt/1714407932/fvip/3/short_key/1/keepalive/yes/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,wft,sgovp,rqh,xpc,vprv,playlist_type/sig/AJfQdSswRQIgDjFp2TA7ac489PpOrTno8RL2QWSb8k-ROB3c9on1ksQCIQDZuP3V5-DJ0qBkC4NUpqm72EPmXbtGevSEf-CVhuqIAQ%3D%3D/lsparams/hls_chunk_host,mh,mm,mn,ms,mv,mvi,pl,initcwndbps/lsig/AHWaYeowRQIgdEd3fN6HGdjgi9JEpaDk6qX0jG3DvPhZCc6pixJdfwkCIQDFdS3d23AdBkwPU9bZtyCizx7wv7hs2eotNi9tGfnvCQ%3D%3D/playlist/index.m3u8",
-    "manifest_url": "https://manifest.googlevideo.com/api/manifest/hls_variant/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/source/youtube/requiressl/yes/xpc/EgVo2aDSNQ%3D%3D/playback_host/rr3---sn-o097znz7.googlevideo.com/mh/Rz/mm/31%2C26/mn/sn-o097znz7%2Csn-a5mekn6d/ms/au%2Conr/mv/m/mvi/3/pl/15/hfr/1/demuxed/1/tts_caps/1/maudio/1/initcwndbps/787500/vprv/1/go/1/mt/1714407932/fvip/3/nvgoi/1/short_key/1/ncsapi/1/keepalive/yes/dover/13/itag/0/playlist_type/DVR/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Cxpc%2Chfr%2Cdemuxed%2Ctts_caps%2Cmaudio%2Cvprv%2Cgo%2Citag%2Cplaylist_type/sig/AJfQdSswRQIhALFqr05ljmiJjuzFl2TTMIfRsNuxUP2kmHUc-2MdMjMGAiBkWu4f1qKH421294MKPMeOJz1K-IPag52Ke12rvCMRSg%3D%3D/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AHWaYeowRQIhALsiEdN5q1QSndrAU9jQH39I8gjGoNX5MV5YXAvfgpBSAiBLOcDfuYFTUoyAgV9wmBAB4bljhT6AgSMEN89MGGmywA%3D%3D/file/index.m3u8",
-    "tbr": 571.028,
-    "ext": "mp4",
-    "fps": 24.0,
-    "protocol": "m3u8_native",
-    "preference": null,
-    "quality": 7,
-    "has_drm": false,
-    "width": 854,
-    "height": 480,
-    "vcodec": "vp09.00.30.08",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "source_preference": -1,
-    "resolution": "854x480",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 571.028,
-    "format": "606 - 854x480"
-  },
-  {
-    "asr": null,
-    "filesize": 1592781,
-    "format_id": "244",
-    "format_note": "480p",
-    "source_preference": -1,
-    "fps": 24,
-    "audio_channels": null,
-    "height": 480,
-    "quality": 7.0,
-    "has_drm": false,
-    "tbr": 225.802,
-    "filesize_approx": 1592779,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429869&ei=TcsvZoTpAcXv4t4PuN6FiAc&ip=16.50.54.218&id=o-AK03sRhPRET_5sIM0phiVbDY2V7AAZFjUuOaDFclcxWF&itag=244&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fwebm&gir=yes&clen=1592781&dur=56.431&lmt=1714115782900773&mt=1714407932&fvip=3&keepalive=yes&c=IOS&txp=5535434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIgC5vV4CZ7XGBhUODorw0kC7VQ7dxgcA8vgmWyEatVcosCIQC4gKjOZpsc5YxQchBT-BvRkQ_55NzPhMXegWVAOxlSdw%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIhAPPY-XCEkRTbT3gz0BKlSQthBKh9NzJJv8G50PAilth1AiAFnmj8EolqE7A3bBtduJp8LkvE8AhFysldsKHYb2nSeA%3D%3D",
-    "width": 854,
-    "language": null,
-    "language_preference": -1,
-    "preference": null,
-    "ext": "webm",
-    "vcodec": "vp09.00.30.08",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "container": "webm_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "854x480",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "webm",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 225.802,
-    "format": "244 - 854x480 (480p)"
-  },
-  {
-    "asr": 44100,
-    "filesize": null,
-    "format_id": "22",
-    "format_note": "720p",
-    "source_preference": -5,
-    "fps": 24,
-    "audio_channels": 2,
-    "height": 720,
-    "quality": 8.0,
-    "has_drm": false,
-    "tbr": 672.578,
-    "filesize_approx": 4749577,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429871&ei=T8svZrKvKMy9z7sPueaJwAM&ip=16.50.54.218&id=o-APg_O3UHcZWFGLI-9JfIzyLCmvHpOLG74MJMkZnCuINp&itag=22&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fmp4&cnr=14&ratebypass=yes&dur=56.494&lmt=1714113230380296&mt=1714407932&fvip=3&c=ANDROID&txp=5532434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Ccnr%2Cratebypass%2Cdur%2Clmt&sig=AJfQdSswRgIhAPVFkjhVGxiYVJZtZdyvpPbL1cmd-mnYeAWbzU-eX_6yAiEA1TDv2K1VgieDao2_hJFCUtvUja0tiWT8cHXV6RVmaAo%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIgWltg81-E0tWWRHJ2dWsrDl75sMwyMUCZ9XsxmMmtWRsCIQDCqoPdS2tviwzPaJaw6CUzfTd2G7SMVTgEzwjxKWzC0Q%3D%3D",
-    "width": 1280,
-    "language": "en",
-    "language_preference": -1,
-    "preference": null,
-    "ext": "mp4",
-    "vcodec": "avc1.64001F",
-    "acodec": "mp4a.40.2",
-    "dynamic_range": "SDR",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "1280x720",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "vbr": null,
-    "abr": null,
-    "format": "22 - 1280x720 (720p)"
-  },
-  {
-    "asr": null,
-    "filesize": 2500608,
-    "format_id": "398",
-    "format_note": "720p",
-    "source_preference": -1,
-    "fps": 24,
-    "audio_channels": null,
-    "height": 720,
-    "quality": 8.0,
-    "has_drm": false,
-    "tbr": 354.501,
-    "filesize_approx": 2500605,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429871&ei=T8svZrKvKMy9z7sPueaJwAM&ip=16.50.54.218&id=o-APg_O3UHcZWFGLI-9JfIzyLCmvHpOLG74MJMkZnCuINp&itag=398&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fmp4&gir=yes&clen=2500608&dur=56.431&lmt=1714112926084878&mt=1714407932&fvip=3&keepalive=yes&c=ANDROID&txp=5537434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRAIgWaK1F1DRwzhTJA3_zwTu3jsIc0vUv4dzCp4T1bb2m_oCIG9Hdz6HeKhD2eMoW6Hdy4R-Q6qmbov_6qQL1-g-mEbE&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIgWltg81-E0tWWRHJ2dWsrDl75sMwyMUCZ9XsxmMmtWRsCIQDCqoPdS2tviwzPaJaw6CUzfTd2G7SMVTgEzwjxKWzC0Q%3D%3D",
-    "width": 1280,
-    "language": null,
-    "language_preference": -1,
-    "preference": null,
-    "ext": "mp4",
-    "vcodec": "av01.0.05M.08",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "container": "mp4_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "1280x720",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 354.501,
-    "format": "398 - 1280x720 (720p)"
-  },
-  {
-    "format_id": "232",
-    "format_index": null,
-    "url": "https://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/itag/232/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/sgovp/clen%3D3832794%3Bdur%3D56.431%3Bgir%3Dyes%3Bitag%3D136%3Blmt%3D1714113217489843/rqh/1/hls_chunk_host/rr3---sn-o097znz7.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/mh/Rz/mm/31,26/mn/sn-o097znz7,sn-a5mekn6d/ms/au,onr/mv/m/mvi/3/pl/15/initcwndbps/787500/vprv/1/playlist_type/DVR/dover/13/txp/5535434/mt/1714407932/fvip/3/short_key/1/keepalive/yes/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,sgovp,rqh,xpc,vprv,playlist_type/sig/AJfQdSswRQIhAIo_eI5zlM0AjL8FzSlWd4nloQ-yoS7te4ayM9qIA7OqAiAOtapCkF4wO1xlpG0X1YTtOjHDmfsfR_HmffhRYDLMHQ%3D%3D/lsparams/hls_chunk_host,mh,mm,mn,ms,mv,mvi,pl,initcwndbps/lsig/AHWaYeowRQIhAIwhpr330CqOVpOISbh5Sy1dpu_pxMOxV6GOb7fNL_72AiB2FwWY6hY-7rCfy_R7y0j5O56P00LsEgUQP9pQHnsPNw%3D%3D/playlist/index.m3u8",
-    "manifest_url": "https://manifest.googlevideo.com/api/manifest/hls_variant/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/source/youtube/requiressl/yes/xpc/EgVo2aDSNQ%3D%3D/playback_host/rr3---sn-o097znz7.googlevideo.com/mh/Rz/mm/31%2C26/mn/sn-o097znz7%2Csn-a5mekn6d/ms/au%2Conr/mv/m/mvi/3/pl/15/hfr/1/demuxed/1/tts_caps/1/maudio/1/initcwndbps/787500/vprv/1/go/1/mt/1714407932/fvip/3/nvgoi/1/short_key/1/ncsapi/1/keepalive/yes/dover/13/itag/0/playlist_type/DVR/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Cxpc%2Chfr%2Cdemuxed%2Ctts_caps%2Cmaudio%2Cvprv%2Cgo%2Citag%2Cplaylist_type/sig/AJfQdSswRQIhALFqr05ljmiJjuzFl2TTMIfRsNuxUP2kmHUc-2MdMjMGAiBkWu4f1qKH421294MKPMeOJz1K-IPag52Ke12rvCMRSg%3D%3D/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AHWaYeowRQIhALsiEdN5q1QSndrAU9jQH39I8gjGoNX5MV5YXAvfgpBSAiBLOcDfuYFTUoyAgV9wmBAB4bljhT6AgSMEN89MGGmywA%3D%3D/file/index.m3u8",
-    "tbr": 1060.599,
-    "ext": "mp4",
-    "fps": 24.0,
-    "protocol": "m3u8_native",
-    "preference": null,
-    "quality": 8,
-    "has_drm": false,
-    "width": 1280,
-    "height": 720,
-    "vcodec": "avc1.4D401F",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "source_preference": -1,
-    "resolution": "1280x720",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 1060.599,
-    "format": "232 - 1280x720"
-  },
-  {
-    "asr": null,
-    "filesize": 3832794,
-    "format_id": "136",
-    "format_note": "720p",
-    "source_preference": -1,
-    "fps": 24,
-    "audio_channels": null,
-    "height": 720,
-    "quality": 8.0,
-    "has_drm": false,
-    "tbr": 543.36,
-    "filesize_approx": 3832793,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429869&ei=TcsvZoTpAcXv4t4PuN6FiAc&ip=16.50.54.218&id=o-AK03sRhPRET_5sIM0phiVbDY2V7AAZFjUuOaDFclcxWF&itag=136&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fmp4&gir=yes&clen=3832794&dur=56.431&lmt=1714113217489843&mt=1714407932&fvip=3&keepalive=yes&c=IOS&txp=5535434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIgN94imXAJRfqv9VKqgygV8UQtOO-2yWCXXKCuGY_3bqcCIQCs-isEAZOgluDF1ACPWuJ0AzZVnUyL4bmtph25SxCeQQ%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIhAPPY-XCEkRTbT3gz0BKlSQthBKh9NzJJv8G50PAilth1AiAFnmj8EolqE7A3bBtduJp8LkvE8AhFysldsKHYb2nSeA%3D%3D",
-    "width": 1280,
-    "language": null,
-    "language_preference": -1,
-    "preference": null,
-    "ext": "mp4",
-    "vcodec": "avc1.4D401F",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "container": "mp4_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "1280x720",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 543.36,
-    "format": "136 - 1280x720 (720p)"
-  },
-  {
-    "format_id": "609",
-    "format_index": null,
-    "url": "https://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/itag/609/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/wft/1/sgovp/clen%3D2478443%3Bdur%3D56.431%3Bgir%3Dyes%3Bitag%3D247%3Blmt%3D1714115787883383/rqh/1/hls_chunk_host/rr3---sn-o097znz7.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/mh/Rz/mm/31,26/mn/sn-o097znz7,sn-a5mekn6d/ms/au,onr/mv/m/mvi/3/pl/15/initcwndbps/787500/vprv/1/playlist_type/DVR/dover/13/txp/5535434/mt/1714407932/fvip/3/short_key/1/keepalive/yes/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,wft,sgovp,rqh,xpc,vprv,playlist_type/sig/AJfQdSswRQIhAKzmoqj1CTmPe804ypZwDifw8wV4PBYljGGfQLqiR7YKAiB7e8WtexRcLSAsCNjR3dHvq0UPYTHrbxijT4QcMW3lBg%3D%3D/lsparams/hls_chunk_host,mh,mm,mn,ms,mv,mvi,pl,initcwndbps/lsig/AHWaYeowRQIhAOhKr9xXbG0M9ktpLHn0mO2zlPJ0gjoxj-3XeE12xgcUAiA735qq9mMKdi_m9SRb1hiB-PvDVgLHYV4j3NLgh_tYNA%3D%3D/playlist/index.m3u8",
-    "manifest_url": "https://manifest.googlevideo.com/api/manifest/hls_variant/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/source/youtube/requiressl/yes/xpc/EgVo2aDSNQ%3D%3D/playback_host/rr3---sn-o097znz7.googlevideo.com/mh/Rz/mm/31%2C26/mn/sn-o097znz7%2Csn-a5mekn6d/ms/au%2Conr/mv/m/mvi/3/pl/15/hfr/1/demuxed/1/tts_caps/1/maudio/1/initcwndbps/787500/vprv/1/go/1/mt/1714407932/fvip/3/nvgoi/1/short_key/1/ncsapi/1/keepalive/yes/dover/13/itag/0/playlist_type/DVR/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Cxpc%2Chfr%2Cdemuxed%2Ctts_caps%2Cmaudio%2Cvprv%2Cgo%2Citag%2Cplaylist_type/sig/AJfQdSswRQIhALFqr05ljmiJjuzFl2TTMIfRsNuxUP2kmHUc-2MdMjMGAiBkWu4f1qKH421294MKPMeOJz1K-IPag52Ke12rvCMRSg%3D%3D/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AHWaYeowRQIhALsiEdN5q1QSndrAU9jQH39I8gjGoNX5MV5YXAvfgpBSAiBLOcDfuYFTUoyAgV9wmBAB4bljhT6AgSMEN89MGGmywA%3D%3D/file/index.m3u8",
-    "tbr": 848.558,
-    "ext": "mp4",
-    "fps": 24.0,
-    "protocol": "m3u8_native",
-    "preference": null,
-    "quality": 8,
-    "has_drm": false,
-    "width": 1280,
-    "height": 720,
-    "vcodec": "vp09.00.31.08",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "source_preference": -1,
-    "resolution": "1280x720",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 848.558,
-    "format": "609 - 1280x720"
-  },
-  {
-    "asr": null,
-    "filesize": 2478443,
-    "format_id": "247",
-    "format_note": "720p",
-    "source_preference": -1,
-    "fps": 24,
-    "audio_channels": null,
-    "height": 720,
-    "quality": 8.0,
-    "has_drm": false,
-    "tbr": 351.359,
-    "filesize_approx": 2478442,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429869&ei=TcsvZoTpAcXv4t4PuN6FiAc&ip=16.50.54.218&id=o-AK03sRhPRET_5sIM0phiVbDY2V7AAZFjUuOaDFclcxWF&itag=247&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fwebm&gir=yes&clen=2478443&dur=56.431&lmt=1714115787883383&mt=1714407932&fvip=3&keepalive=yes&c=IOS&txp=5535434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIhAJjfreDLat5Sj9l70EfLaS8d-T3K_-FI11F-xmLuWFOoAiAKzV_04y9WauV7LFM9yNekxC1zwNllhpJCvd1b3Nm2lg%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIhAPPY-XCEkRTbT3gz0BKlSQthBKh9NzJJv8G50PAilth1AiAFnmj8EolqE7A3bBtduJp8LkvE8AhFysldsKHYb2nSeA%3D%3D",
-    "width": 1280,
-    "language": null,
-    "language_preference": -1,
-    "preference": null,
-    "ext": "webm",
-    "vcodec": "vp09.00.31.08",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "container": "webm_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "1280x720",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "webm",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 351.359,
-    "format": "247 - 1280x720 (720p)"
-  },
-  {
-    "asr": null,
-    "filesize": 4280787,
-    "format_id": "399",
-    "format_note": "1080p",
-    "source_preference": -1,
-    "fps": 24,
-    "audio_channels": null,
-    "height": 1080,
-    "quality": 9.0,
-    "has_drm": false,
-    "tbr": 606.87,
-    "filesize_approx": 4280785,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429871&ei=T8svZrKvKMy9z7sPueaJwAM&ip=16.50.54.218&id=o-APg_O3UHcZWFGLI-9JfIzyLCmvHpOLG74MJMkZnCuINp&itag=399&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fmp4&gir=yes&clen=4280787&dur=56.431&lmt=1714113537347498&mt=1714407932&fvip=3&keepalive=yes&c=ANDROID&txp=5537434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIhAMUMyrLTDwffxezj-nZ7R06NcBml_Mx5pvZd7QvNCe9-AiBFSdltpokj9OR3SjrXHzIdhinM_xk7vQ9pDcLr2eEWiQ%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIgWltg81-E0tWWRHJ2dWsrDl75sMwyMUCZ9XsxmMmtWRsCIQDCqoPdS2tviwzPaJaw6CUzfTd2G7SMVTgEzwjxKWzC0Q%3D%3D",
-    "width": 1920,
-    "language": null,
-    "language_preference": -1,
-    "preference": null,
-    "ext": "mp4",
-    "vcodec": "av01.0.08M.08",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "container": "mp4_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "1920x1080",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 606.87,
-    "format": "399 - 1920x1080 (1080p)"
-  },
-  {
-    "format_id": "270",
-    "format_index": null,
-    "url": "https://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/itag/270/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/sgovp/clen%3D13250951%3Bdur%3D56.431%3Bgir%3Dyes%3Bitag%3D137%3Blmt%3D1714113268413770/rqh/1/hls_chunk_host/rr3---sn-o097znz7.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/mh/Rz/mm/31,26/mn/sn-o097znz7,sn-a5mekn6d/ms/au,onr/mv/m/mvi/3/pl/15/initcwndbps/787500/vprv/1/playlist_type/DVR/dover/13/txp/5535434/mt/1714407932/fvip/3/short_key/1/keepalive/yes/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,sgovp,rqh,xpc,vprv,playlist_type/sig/AJfQdSswRgIhAJB6_tREMO4xA6Fvi6PzA_q3b_YddjUHBLKR52qsMamHAiEA367iSfBTV9wX5bFXkanGeCOqFA9sjBiLbVf_zpy7R8g%3D/lsparams/hls_chunk_host,mh,mm,mn,ms,mv,mvi,pl,initcwndbps/lsig/AHWaYeowRQIhAMK7d7moh-nzCvy33u2H1KcQAraIoRNxvDIVXdwlXZIfAiARugGsnwjPHVAVj3HUjkwTM7gN8PKuFSkmOO2FvQm_rQ%3D%3D/playlist/index.m3u8",
-    "manifest_url": "https://manifest.googlevideo.com/api/manifest/hls_variant/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/source/youtube/requiressl/yes/xpc/EgVo2aDSNQ%3D%3D/playback_host/rr3---sn-o097znz7.googlevideo.com/mh/Rz/mm/31%2C26/mn/sn-o097znz7%2Csn-a5mekn6d/ms/au%2Conr/mv/m/mvi/3/pl/15/hfr/1/demuxed/1/tts_caps/1/maudio/1/initcwndbps/787500/vprv/1/go/1/mt/1714407932/fvip/3/nvgoi/1/short_key/1/ncsapi/1/keepalive/yes/dover/13/itag/0/playlist_type/DVR/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Cxpc%2Chfr%2Cdemuxed%2Ctts_caps%2Cmaudio%2Cvprv%2Cgo%2Citag%2Cplaylist_type/sig/AJfQdSswRQIhALFqr05ljmiJjuzFl2TTMIfRsNuxUP2kmHUc-2MdMjMGAiBkWu4f1qKH421294MKPMeOJz1K-IPag52Ke12rvCMRSg%3D%3D/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AHWaYeowRQIhALsiEdN5q1QSndrAU9jQH39I8gjGoNX5MV5YXAvfgpBSAiBLOcDfuYFTUoyAgV9wmBAB4bljhT6AgSMEN89MGGmywA%3D%3D/file/index.m3u8",
-    "tbr": 3174.775,
-    "ext": "mp4",
-    "fps": 24.0,
-    "protocol": "m3u8_native",
-    "preference": null,
-    "quality": 9,
-    "has_drm": false,
-    "width": 1920,
-    "height": 1080,
-    "vcodec": "avc1.640028",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "source_preference": -1,
-    "resolution": "1920x1080",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 3174.775,
-    "format": "270 - 1920x1080"
-  },
-  {
-    "asr": null,
-    "filesize": 13250951,
-    "format_id": "137",
-    "format_note": "1080p",
-    "source_preference": -1,
-    "fps": 24,
-    "audio_channels": null,
-    "height": 1080,
-    "quality": 9.0,
-    "has_drm": false,
-    "tbr": 1878.534,
-    "filesize_approx": 13250944,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429869&ei=TcsvZoTpAcXv4t4PuN6FiAc&ip=16.50.54.218&id=o-AK03sRhPRET_5sIM0phiVbDY2V7AAZFjUuOaDFclcxWF&itag=137&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fmp4&gir=yes&clen=13250951&dur=56.431&lmt=1714113268413770&mt=1714407932&fvip=3&keepalive=yes&c=IOS&txp=5535434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIgC0BNnNKFv7FS2-WOBnlo_zYwlm5w8n0jcpf3WHxD9y0CIQC83e7xzjOdUoGoGLAz8nKOJnRNiNd80ODhGi7bCdcH2g%3D%3D&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIhAPPY-XCEkRTbT3gz0BKlSQthBKh9NzJJv8G50PAilth1AiAFnmj8EolqE7A3bBtduJp8LkvE8AhFysldsKHYb2nSeA%3D%3D",
-    "width": 1920,
-    "language": null,
-    "language_preference": -1,
-    "preference": null,
-    "ext": "mp4",
-    "vcodec": "avc1.640028",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "container": "mp4_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "1920x1080",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 1878.534,
-    "format": "137 - 1920x1080 (1080p)"
-  },
-  {
-    "format_id": "614",
-    "format_index": null,
-    "url": "https://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/itag/614/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/wft/1/sgovp/clen%3D6568850%3Bdur%3D56.431%3Bgir%3Dyes%3Bitag%3D248%3Blmt%3D1714116024840399/rqh/1/hls_chunk_host/rr3---sn-o097znz7.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/mh/Rz/mm/31,26/mn/sn-o097znz7,sn-a5mekn6d/ms/au,onr/mv/m/mvi/3/pl/15/initcwndbps/787500/vprv/1/playlist_type/DVR/dover/13/txp/5535434/mt/1714407932/fvip/3/short_key/1/keepalive/yes/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,wft,sgovp,rqh,xpc,vprv,playlist_type/sig/AJfQdSswRAIgT8vdUA5eQ0zueAgRlZI8G-h6KyUbIIviPBjnMjTd8PgCIEIrlSH-bf-Tbt_6a1VQpWR8lSsje8l2G5p1z8JmJBhO/lsparams/hls_chunk_host,mh,mm,mn,ms,mv,mvi,pl,initcwndbps/lsig/AHWaYeowRgIhAN4iLQOwue3K2Q5X0dbgvGGTFKEeVYayTP_cTaAieLq2AiEAkpm3h-6fk34gn9O8ZORVibF6xKDhdh7icLQG6D4XwQ8%3D/playlist/index.m3u8",
-    "manifest_url": "https://manifest.googlevideo.com/api/manifest/hls_variant/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/source/youtube/requiressl/yes/xpc/EgVo2aDSNQ%3D%3D/playback_host/rr3---sn-o097znz7.googlevideo.com/mh/Rz/mm/31%2C26/mn/sn-o097znz7%2Csn-a5mekn6d/ms/au%2Conr/mv/m/mvi/3/pl/15/hfr/1/demuxed/1/tts_caps/1/maudio/1/initcwndbps/787500/vprv/1/go/1/mt/1714407932/fvip/3/nvgoi/1/short_key/1/ncsapi/1/keepalive/yes/dover/13/itag/0/playlist_type/DVR/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Cxpc%2Chfr%2Cdemuxed%2Ctts_caps%2Cmaudio%2Cvprv%2Cgo%2Citag%2Cplaylist_type/sig/AJfQdSswRQIhALFqr05ljmiJjuzFl2TTMIfRsNuxUP2kmHUc-2MdMjMGAiBkWu4f1qKH421294MKPMeOJz1K-IPag52Ke12rvCMRSg%3D%3D/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AHWaYeowRQIhALsiEdN5q1QSndrAU9jQH39I8gjGoNX5MV5YXAvfgpBSAiBLOcDfuYFTUoyAgV9wmBAB4bljhT6AgSMEN89MGGmywA%3D%3D/file/index.m3u8",
-    "tbr": 1965.343,
-    "ext": "mp4",
-    "fps": 24.0,
-    "protocol": "m3u8_native",
-    "preference": null,
-    "quality": 9,
-    "has_drm": false,
-    "width": 1920,
-    "height": 1080,
-    "vcodec": "vp09.00.40.08",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "source_preference": -1,
-    "resolution": "1920x1080",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 1965.343,
-    "format": "614 - 1920x1080"
-  },
-  {
-    "asr": null,
-    "filesize": 6568850,
-    "format_id": "248",
-    "format_note": "1080p",
-    "source_preference": -1,
-    "fps": 24,
-    "audio_channels": null,
-    "height": 1080,
-    "quality": 9.0,
-    "has_drm": false,
-    "tbr": 931.239,
-    "filesize_approx": 6568843,
-    "url": "https://rr3---sn-o097znz7.googlevideo.com/videoplayback?expire=1714429869&ei=TcsvZoTpAcXv4t4PuN6FiAc&ip=16.50.54.218&id=o-AK03sRhPRET_5sIM0phiVbDY2V7AAZFjUuOaDFclcxWF&itag=248&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&mh=Rz&mm=31%2C26&mn=sn-o097znz7%2Csn-a5mekn6d&ms=au%2Conr&mv=m&mvi=3&pl=15&initcwndbps=787500&vprv=1&svpuc=1&mime=video%2Fwebm&gir=yes&clen=6568850&dur=56.431&lmt=1714116024840399&mt=1714407932&fvip=3&keepalive=yes&c=IOS&txp=5535434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cvprv%2Csvpuc%2Cmime%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRAIgPTr2fC0ln8hDivG5P4EbWXzWA-2wKesUDp9ct1Tn844CIGjXS4iiX1Tndrg-ASr6xT4yixlZvqo_eY4XGrrsJX0Y&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AHWaYeowRQIhAPPY-XCEkRTbT3gz0BKlSQthBKh9NzJJv8G50PAilth1AiAFnmj8EolqE7A3bBtduJp8LkvE8AhFysldsKHYb2nSeA%3D%3D",
-    "width": 1920,
-    "language": null,
-    "language_preference": -1,
-    "preference": null,
-    "ext": "webm",
-    "vcodec": "vp09.00.40.08",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "container": "webm_dash",
-    "downloader_options": {
-      "http_chunk_size": 10485760
-    },
-    "protocol": "https",
-    "resolution": "1920x1080",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "webm",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 931.239,
-    "format": "248 - 1920x1080 (1080p)"
-  },
-  {
-    "format_id": "616",
-    "format_index": null,
-    "url": "https://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/itag/616/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/wft/1/sgovp/clen%3D11699589%3Bdur%3D56.431%3Bgir%3Dyes%3Bitag%3D356%3Blmt%3D1714112432047907/rqh/1/hls_chunk_host/rr3---sn-o097znz7.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/mh/Rz/mm/31,26/mn/sn-o097znz7,sn-a5mekn6d/ms/au,onr/mv/m/mvi/3/pl/15/initcwndbps/787500/vprv/1/playlist_type/DVR/dover/13/txp/5532434/mt/1714407932/fvip/3/short_key/1/keepalive/yes/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,wft,sgovp,rqh,xpc,vprv,playlist_type/sig/AJfQdSswRQIhANlFo51K0nGtM__vtbEUM-F9r9F1dwZn_LiSqVKH5xNmAiA9BdJqOuTbrqyR76UCnqFBw-E66kaGKjYRUORLGVPrhg%3D%3D/lsparams/hls_chunk_host,mh,mm,mn,ms,mv,mvi,pl,initcwndbps/lsig/AHWaYeowRAIgWq4vT5Xdblzzrw7zl_BUtfFvWJBvBTCPyXauUQDmrtwCIEpiuAJWjrljpV5iduGadGLcH7HkIvi6q2pyi9YMmbII/playlist/index.m3u8",
-    "manifest_url": "https://manifest.googlevideo.com/api/manifest/hls_variant/expire/1714429869/ei/TcsvZoTpAcXv4t4PuN6FiAc/ip/16.50.54.218/id/e5d3d71b3c99a88f/source/youtube/requiressl/yes/xpc/EgVo2aDSNQ%3D%3D/playback_host/rr3---sn-o097znz7.googlevideo.com/mh/Rz/mm/31%2C26/mn/sn-o097znz7%2Csn-a5mekn6d/ms/au%2Conr/mv/m/mvi/3/pl/15/hfr/1/demuxed/1/tts_caps/1/maudio/1/initcwndbps/787500/vprv/1/go/1/mt/1714407932/fvip/3/nvgoi/1/short_key/1/ncsapi/1/keepalive/yes/dover/13/itag/0/playlist_type/DVR/sparams/expire%2Cei%2Cip%2Cid%2Csource%2Crequiressl%2Cxpc%2Chfr%2Cdemuxed%2Ctts_caps%2Cmaudio%2Cvprv%2Cgo%2Citag%2Cplaylist_type/sig/AJfQdSswRQIhALFqr05ljmiJjuzFl2TTMIfRsNuxUP2kmHUc-2MdMjMGAiBkWu4f1qKH421294MKPMeOJz1K-IPag52Ke12rvCMRSg%3D%3D/lsparams/playback_host%2Cmh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps/lsig/AHWaYeowRQIhALsiEdN5q1QSndrAU9jQH39I8gjGoNX5MV5YXAvfgpBSAiBLOcDfuYFTUoyAgV9wmBAB4bljhT6AgSMEN89MGGmywA%3D%3D/file/index.m3u8",
-    "tbr": 3192.247,
-    "ext": "mp4",
-    "fps": 24.0,
-    "protocol": "m3u8_native",
-    "preference": null,
-    "quality": 9,
-    "has_drm": false,
-    "width": 1920,
-    "height": 1080,
-    "vcodec": "vp09.00.40.08",
-    "acodec": "none",
-    "dynamic_range": "SDR",
-    "source_preference": 99,
-    "format_note": "Premium",
-    "resolution": "1920x1080",
-    "aspect_ratio": 1.78,
-    "http_headers": {},
-    "video_ext": "mp4",
-    "audio_ext": "none",
-    "abr": 0,
-    "vbr": 3192.247,
-    "format": "616 - 1920x1080 (Premium)"
-  }
-]

+ 250 - 0
js/format-utils.js

@@ -0,0 +1,250 @@
+const utils = require('./utils');
+const FORMATS = require('./formats');
+
+
+// Use these to help sort formats, higher index is better.
+const audioEncodingRanks = [
+  'mp4a',
+  'mp3',
+  'vorbis',
+  'aac',
+  'opus',
+  'flac',
+];
+const videoEncodingRanks = [
+  'mp4v',
+  'avc1',
+  'Sorenson H.283',
+  'MPEG-4 Visual',
+  'VP8',
+  'VP9',
+  'H.264',
+];
+
+const getVideoBitrate = format => format.bitrate || 0;
+const getVideoEncodingRank = format =>
+  videoEncodingRanks.findIndex(enc => format.codecs && format.codecs.includes(enc));
+const getAudioBitrate = format => format.audioBitrate || 0;
+const getAudioEncodingRank = format =>
+  audioEncodingRanks.findIndex(enc => format.codecs && format.codecs.includes(enc));
+
+
+/**
+ * Sort formats by a list of functions.
+ *
+ * @param {Object} a
+ * @param {Object} b
+ * @param {Array.<Function>} sortBy
+ * @returns {number}
+ */
+const sortFormatsBy = (a, b, sortBy) => {
+  let res = 0;
+  for (let fn of sortBy) {
+    res = fn(b) - fn(a);
+    if (res !== 0) {
+      break;
+    }
+  }
+  return res;
+};
+
+
+const sortFormatsByVideo = (a, b) => sortFormatsBy(a, b, [
+  format => parseInt(format.qualityLabel),
+  getVideoBitrate,
+  getVideoEncodingRank,
+]);
+
+
+const sortFormatsByAudio = (a, b) => sortFormatsBy(a, b, [
+  getAudioBitrate,
+  getAudioEncodingRank,
+]);
+
+
+/**
+ * Sort formats from highest quality to lowest.
+ *
+ * @param {Object} a
+ * @param {Object} b
+ * @returns {number}
+ */
+exports.sortFormats = (a, b) => sortFormatsBy(a, b, [
+  // Formats with both video and audio are ranked highest.
+  format => +!!format.isHLS,
+  format => +!!format.isDashMPD,
+  format => +(format.contentLength > 0),
+  format => +(format.hasVideo && format.hasAudio),
+  format => +format.hasVideo,
+  format => parseInt(format.qualityLabel) || 0,
+  getVideoBitrate,
+  getAudioBitrate,
+  getVideoEncodingRank,
+  getAudioEncodingRank,
+]);
+
+
+/**
+ * Choose a format depending on the given options.
+ *
+ * @param {Array.<Object>} formats
+ * @param {Object} options
+ * @returns {Object}
+ * @throws {Error} when no format matches the filter/format rules
+ */
+exports.chooseFormat = (formats, options) => {
+  if (typeof options.format === 'object') {
+    if (!options.format.url) {
+      throw Error('Invalid format given, did you use `ytdl.getInfo()`?');
+    }
+    return options.format;
+  }
+
+  if (options.filter) {
+    formats = exports.filterFormats(formats, options.filter);
+  }
+
+  // We currently only support HLS-Formats for livestreams
+  // So we (now) remove all non-HLS streams
+  if (formats.some(fmt => fmt.isHLS)) {
+    formats = formats.filter(fmt => fmt.isHLS || !fmt.isLive);
+  }
+
+  let format;
+  const quality = options.quality || 'highest';
+  switch (quality) {
+    case 'highest':
+      format = formats[0];
+      break;
+
+    case 'lowest':
+      format = formats[formats.length - 1];
+      break;
+
+    case 'highestaudio': {
+      formats = exports.filterFormats(formats, 'audio');
+      formats.sort(sortFormatsByAudio);
+      // Filter for only the best audio format
+      const bestAudioFormat = formats[0];
+      formats = formats.filter(f => sortFormatsByAudio(bestAudioFormat, f) === 0);
+      // Check for the worst video quality for the best audio quality and pick according
+      // This does not loose default sorting of video encoding and bitrate
+      const worstVideoQuality = formats.map(f => parseInt(f.qualityLabel) || 0).sort((a, b) => a - b)[0];
+      format = formats.find(f => (parseInt(f.qualityLabel) || 0) === worstVideoQuality);
+      break;
+    }
+
+    case 'lowestaudio':
+      formats = exports.filterFormats(formats, 'audio');
+      formats.sort(sortFormatsByAudio);
+      format = formats[formats.length - 1];
+      break;
+
+    case 'highestvideo': {
+      formats = exports.filterFormats(formats, 'video');
+      formats.sort(sortFormatsByVideo);
+      // Filter for only the best video format
+      const bestVideoFormat = formats[0];
+      formats = formats.filter(f => sortFormatsByVideo(bestVideoFormat, f) === 0);
+      // Check for the worst audio quality for the best video quality and pick according
+      // This does not loose default sorting of audio encoding and bitrate
+      const worstAudioQuality = formats.map(f => f.audioBitrate || 0).sort((a, b) => a - b)[0];
+      format = formats.find(f => (f.audioBitrate || 0) === worstAudioQuality);
+      break;
+    }
+
+    case 'lowestvideo':
+      formats = exports.filterFormats(formats, 'video');
+      formats.sort(sortFormatsByVideo);
+      format = formats[formats.length - 1];
+      break;
+
+    default:
+      format = getFormatByQuality(quality, formats);
+      break;
+  }
+
+  if (!format) {
+    throw Error(`No such format found: ${quality}`);
+  }
+  return format;
+};
+
+/**
+ * Gets a format based on quality or array of quality's
+ *
+ * @param {string|[string]} quality
+ * @param {[Object]} formats
+ * @returns {Object}
+ */
+const getFormatByQuality = (quality, formats) => {
+  let getFormat = itag => formats.find(format => `${format.itag}` === `${itag}`);
+  if (Array.isArray(quality)) {
+    return getFormat(quality.find(q => getFormat(q)));
+  } else {
+    return getFormat(quality);
+  }
+};
+
+
+/**
+ * @param {Array.<Object>} formats
+ * @param {Function} filter
+ * @returns {Array.<Object>}
+ */
+exports.filterFormats = (formats, filter) => {
+  let fn;
+  switch (filter) {
+    case 'videoandaudio':
+    case 'audioandvideo':
+      fn = format => format.hasVideo && format.hasAudio;
+      break;
+
+    case 'video':
+      fn = format => format.hasVideo;
+      break;
+
+    case 'videoonly':
+      fn = format => format.hasVideo && !format.hasAudio;
+      break;
+
+    case 'audio':
+      fn = format => format.hasAudio;
+      break;
+
+    case 'audioonly':
+      fn = format => !format.hasVideo && format.hasAudio;
+      break;
+
+    default:
+      if (typeof filter === 'function') {
+        fn = filter;
+      } else {
+        throw TypeError(`Given filter (${filter}) is not supported`);
+      }
+  }
+  return formats.filter(format => !!format.url && fn(format));
+};
+
+
+/**
+ * @param {Object} format
+ * @returns {Object}
+ */
+exports.addFormatMeta = format => {
+  format = Object.assign({}, FORMATS[format.itag], format);
+  format.hasVideo = !!format.qualityLabel;
+  format.hasAudio = !!format.audioBitrate;
+  format.container = format.mimeType ?
+    format.mimeType.split(';')[0].split('/')[1] : null;
+  format.codecs = format.mimeType ?
+    utils.between(format.mimeType, 'codecs="', '"') : null;
+  format.videoCodec = format.hasVideo && format.codecs ?
+    format.codecs.split(', ')[0] : null;
+  format.audioCodec = format.hasAudio && format.codecs ?
+    format.codecs.split(', ').slice(-1)[0] : null;
+  format.isLive = /\bsource[/=]yt_live_broadcast\b/.test(format.url);
+  format.isHLS = /\/manifest\/hls_(variant|playlist)\//.test(format.url);
+  format.isDashMPD = /\/manifest\/dash\//.test(format.url);
+  return format;
+};

+ 524 - 0
js/formats.js

@@ -0,0 +1,524 @@
+/**
+ * http://en.wikipedia.org/wiki/YouTube#Quality_and_formats
+ */
+module.exports = {
+
+  5: {
+    mimeType: 'video/flv; codecs="Sorenson H.283, mp3"',
+    qualityLabel: '240p',
+    bitrate: 250000,
+    audioBitrate: 64,
+  },
+
+  6: {
+    mimeType: 'video/flv; codecs="Sorenson H.263, mp3"',
+    qualityLabel: '270p',
+    bitrate: 800000,
+    audioBitrate: 64,
+  },
+
+  13: {
+    mimeType: 'video/3gp; codecs="MPEG-4 Visual, aac"',
+    qualityLabel: null,
+    bitrate: 500000,
+    audioBitrate: null,
+  },
+
+  17: {
+    mimeType: 'video/3gp; codecs="MPEG-4 Visual, aac"',
+    qualityLabel: '144p',
+    bitrate: 50000,
+    audioBitrate: 24,
+  },
+
+  18: {
+    mimeType: 'video/mp4; codecs="H.264, aac"',
+    qualityLabel: '360p',
+    bitrate: 500000,
+    audioBitrate: 96,
+  },
+
+  22: {
+    mimeType: 'video/mp4; codecs="H.264, aac"',
+    qualityLabel: '720p',
+    bitrate: 2000000,
+    audioBitrate: 192,
+  },
+
+  34: {
+    mimeType: 'video/flv; codecs="H.264, aac"',
+    qualityLabel: '360p',
+    bitrate: 500000,
+    audioBitrate: 128,
+  },
+
+  35: {
+    mimeType: 'video/flv; codecs="H.264, aac"',
+    qualityLabel: '480p',
+    bitrate: 800000,
+    audioBitrate: 128,
+  },
+
+  36: {
+    mimeType: 'video/3gp; codecs="MPEG-4 Visual, aac"',
+    qualityLabel: '240p',
+    bitrate: 175000,
+    audioBitrate: 32,
+  },
+
+  37: {
+    mimeType: 'video/mp4; codecs="H.264, aac"',
+    qualityLabel: '1080p',
+    bitrate: 3000000,
+    audioBitrate: 192,
+  },
+
+  38: {
+    mimeType: 'video/mp4; codecs="H.264, aac"',
+    qualityLabel: '3072p',
+    bitrate: 3500000,
+    audioBitrate: 192,
+  },
+
+  43: {
+    mimeType: 'video/webm; codecs="VP8, vorbis"',
+    qualityLabel: '360p',
+    bitrate: 500000,
+    audioBitrate: 128,
+  },
+
+  44: {
+    mimeType: 'video/webm; codecs="VP8, vorbis"',
+    qualityLabel: '480p',
+    bitrate: 1000000,
+    audioBitrate: 128,
+  },
+
+  45: {
+    mimeType: 'video/webm; codecs="VP8, vorbis"',
+    qualityLabel: '720p',
+    bitrate: 2000000,
+    audioBitrate: 192,
+  },
+
+  46: {
+    mimeType: 'audio/webm; codecs="vp8, vorbis"',
+    qualityLabel: '1080p',
+    bitrate: null,
+    audioBitrate: 192,
+  },
+
+  82: {
+    mimeType: 'video/mp4; codecs="H.264, aac"',
+    qualityLabel: '360p',
+    bitrate: 500000,
+    audioBitrate: 96,
+  },
+
+  83: {
+    mimeType: 'video/mp4; codecs="H.264, aac"',
+    qualityLabel: '240p',
+    bitrate: 500000,
+    audioBitrate: 96,
+  },
+
+  84: {
+    mimeType: 'video/mp4; codecs="H.264, aac"',
+    qualityLabel: '720p',
+    bitrate: 2000000,
+    audioBitrate: 192,
+  },
+
+  85: {
+    mimeType: 'video/mp4; codecs="H.264, aac"',
+    qualityLabel: '1080p',
+    bitrate: 3000000,
+    audioBitrate: 192,
+  },
+
+  91: {
+    mimeType: 'video/ts; codecs="H.264, aac"',
+    qualityLabel: '144p',
+    bitrate: 100000,
+    audioBitrate: 48,
+  },
+
+  92: {
+    mimeType: 'video/ts; codecs="H.264, aac"',
+    qualityLabel: '240p',
+    bitrate: 150000,
+    audioBitrate: 48,
+  },
+
+  93: {
+    mimeType: 'video/ts; codecs="H.264, aac"',
+    qualityLabel: '360p',
+    bitrate: 500000,
+    audioBitrate: 128,
+  },
+
+  94: {
+    mimeType: 'video/ts; codecs="H.264, aac"',
+    qualityLabel: '480p',
+    bitrate: 800000,
+    audioBitrate: 128,
+  },
+
+  95: {
+    mimeType: 'video/ts; codecs="H.264, aac"',
+    qualityLabel: '720p',
+    bitrate: 1500000,
+    audioBitrate: 256,
+  },
+
+  96: {
+    mimeType: 'video/ts; codecs="H.264, aac"',
+    qualityLabel: '1080p',
+    bitrate: 2500000,
+    audioBitrate: 256,
+  },
+
+  100: {
+    mimeType: 'audio/webm; codecs="VP8, vorbis"',
+    qualityLabel: '360p',
+    bitrate: null,
+    audioBitrate: 128,
+  },
+
+  101: {
+    mimeType: 'audio/webm; codecs="VP8, vorbis"',
+    qualityLabel: '360p',
+    bitrate: null,
+    audioBitrate: 192,
+  },
+
+  102: {
+    mimeType: 'audio/webm; codecs="VP8, vorbis"',
+    qualityLabel: '720p',
+    bitrate: null,
+    audioBitrate: 192,
+  },
+
+  120: {
+    mimeType: 'video/flv; codecs="H.264, aac"',
+    qualityLabel: '720p',
+    bitrate: 2000000,
+    audioBitrate: 128,
+  },
+
+  127: {
+    mimeType: 'audio/ts; codecs="aac"',
+    qualityLabel: null,
+    bitrate: null,
+    audioBitrate: 96,
+  },
+
+  128: {
+    mimeType: 'audio/ts; codecs="aac"',
+    qualityLabel: null,
+    bitrate: null,
+    audioBitrate: 96,
+  },
+
+  132: {
+    mimeType: 'video/ts; codecs="H.264, aac"',
+    qualityLabel: '240p',
+    bitrate: 150000,
+    audioBitrate: 48,
+  },
+
+  133: {
+    mimeType: 'video/mp4; codecs="H.264"',
+    qualityLabel: '240p',
+    bitrate: 200000,
+    audioBitrate: null,
+  },
+
+  134: {
+    mimeType: 'video/mp4; codecs="H.264"',
+    qualityLabel: '360p',
+    bitrate: 300000,
+    audioBitrate: null,
+  },
+
+  135: {
+    mimeType: 'video/mp4; codecs="H.264"',
+    qualityLabel: '480p',
+    bitrate: 500000,
+    audioBitrate: null,
+  },
+
+  136: {
+    mimeType: 'video/mp4; codecs="H.264"',
+    qualityLabel: '720p',
+    bitrate: 1000000,
+    audioBitrate: null,
+  },
+
+  137: {
+    mimeType: 'video/mp4; codecs="H.264"',
+    qualityLabel: '1080p',
+    bitrate: 2500000,
+    audioBitrate: null,
+  },
+
+  138: {
+    mimeType: 'video/mp4; codecs="H.264"',
+    qualityLabel: '4320p',
+    bitrate: 13500000,
+    audioBitrate: null,
+  },
+
+  139: {
+    mimeType: 'audio/mp4; codecs="aac"',
+    qualityLabel: null,
+    bitrate: null,
+    audioBitrate: 48,
+  },
+
+  140: {
+    mimeType: 'audio/m4a; codecs="aac"',
+    qualityLabel: null,
+    bitrate: null,
+    audioBitrate: 128,
+  },
+
+  141: {
+    mimeType: 'audio/mp4; codecs="aac"',
+    qualityLabel: null,
+    bitrate: null,
+    audioBitrate: 256,
+  },
+
+  151: {
+    mimeType: 'video/ts; codecs="H.264, aac"',
+    qualityLabel: '720p',
+    bitrate: 50000,
+    audioBitrate: 24,
+  },
+
+  160: {
+    mimeType: 'video/mp4; codecs="H.264"',
+    qualityLabel: '144p',
+    bitrate: 100000,
+    audioBitrate: null,
+  },
+
+  171: {
+    mimeType: 'audio/webm; codecs="vorbis"',
+    qualityLabel: null,
+    bitrate: null,
+    audioBitrate: 128,
+  },
+
+  172: {
+    mimeType: 'audio/webm; codecs="vorbis"',
+    qualityLabel: null,
+    bitrate: null,
+    audioBitrate: 192,
+  },
+
+  242: {
+    mimeType: 'video/webm; codecs="VP9"',
+    qualityLabel: '240p',
+    bitrate: 100000,
+    audioBitrate: null,
+  },
+
+  243: {
+    mimeType: 'video/webm; codecs="VP9"',
+    qualityLabel: '360p',
+    bitrate: 250000,
+    audioBitrate: null,
+  },
+
+  244: {
+    mimeType: 'video/webm; codecs="VP9"',
+    qualityLabel: '480p',
+    bitrate: 500000,
+    audioBitrate: null,
+  },
+
+  247: {
+    mimeType: 'video/webm; codecs="VP9"',
+    qualityLabel: '720p',
+    bitrate: 700000,
+    audioBitrate: null,
+  },
+
+  248: {
+    mimeType: 'video/webm; codecs="VP9"',
+    qualityLabel: '1080p',
+    bitrate: 1500000,
+    audioBitrate: null,
+  },
+
+  249: {
+    mimeType: 'audio/webm; codecs="opus"',
+    qualityLabel: null,
+    bitrate: null,
+    audioBitrate: 48,
+  },
+
+  250: {
+    mimeType: 'audio/webm; codecs="opus"',
+    qualityLabel: null,
+    bitrate: null,
+    audioBitrate: 64,
+  },
+
+  251: {
+    mimeType: 'audio/webm; codecs="opus"',
+    qualityLabel: null,
+    bitrate: null,
+    audioBitrate: 160,
+  },
+
+  264: {
+    mimeType: 'video/mp4; codecs="H.264"',
+    qualityLabel: '1440p',
+    bitrate: 4000000,
+    audioBitrate: null,
+  },
+
+  266: {
+    mimeType: 'video/mp4; codecs="H.264"',
+    qualityLabel: '2160p',
+    bitrate: 12500000,
+    audioBitrate: null,
+  },
+
+  271: {
+    mimeType: 'video/webm; codecs="VP9"',
+    qualityLabel: '1440p',
+    bitrate: 9000000,
+    audioBitrate: null,
+  },
+
+  272: {
+    mimeType: 'video/webm; codecs="VP9"',
+    qualityLabel: '4320p',
+    bitrate: 20000000,
+    audioBitrate: null,
+  },
+
+  278: {
+    mimeType: 'video/webm; codecs="VP9"',
+    qualityLabel: '144p 30fps',
+    bitrate: 80000,
+    audioBitrate: null,
+  },
+
+  298: {
+    mimeType: 'video/mp4; codecs="H.264"',
+    qualityLabel: '720p',
+    bitrate: 3000000,
+    audioBitrate: null,
+  },
+
+  299: {
+    mimeType: 'video/mp4; codecs="H.264"',
+    qualityLabel: '1080p',
+    bitrate: 5500000,
+    audioBitrate: null,
+  },
+
+  300: {
+    mimeType: 'video/ts; codecs="H.264, aac"',
+    qualityLabel: '720p',
+    bitrate: 1318000,
+    audioBitrate: 48,
+  },
+
+  302: {
+    mimeType: 'video/webm; codecs="VP9"',
+    qualityLabel: '720p HFR',
+    bitrate: 2500000,
+    audioBitrate: null,
+  },
+
+  303: {
+    mimeType: 'video/webm; codecs="VP9"',
+    qualityLabel: '1080p HFR',
+    bitrate: 5000000,
+    audioBitrate: null,
+  },
+
+  308: {
+    mimeType: 'video/webm; codecs="VP9"',
+    qualityLabel: '1440p HFR',
+    bitrate: 10000000,
+    audioBitrate: null,
+  },
+
+  313: {
+    mimeType: 'video/webm; codecs="VP9"',
+    qualityLabel: '2160p',
+    bitrate: 13000000,
+    audioBitrate: null,
+  },
+
+  315: {
+    mimeType: 'video/webm; codecs="VP9"',
+    qualityLabel: '2160p HFR',
+    bitrate: 20000000,
+    audioBitrate: null,
+  },
+
+  330: {
+    mimeType: 'video/webm; codecs="VP9"',
+    qualityLabel: '144p HDR, HFR',
+    bitrate: 80000,
+    audioBitrate: null,
+  },
+
+  331: {
+    mimeType: 'video/webm; codecs="VP9"',
+    qualityLabel: '240p HDR, HFR',
+    bitrate: 100000,
+    audioBitrate: null,
+  },
+
+  332: {
+    mimeType: 'video/webm; codecs="VP9"',
+    qualityLabel: '360p HDR, HFR',
+    bitrate: 250000,
+    audioBitrate: null,
+  },
+
+  333: {
+    mimeType: 'video/webm; codecs="VP9"',
+    qualityLabel: '240p HDR, HFR',
+    bitrate: 500000,
+    audioBitrate: null,
+  },
+
+  334: {
+    mimeType: 'video/webm; codecs="VP9"',
+    qualityLabel: '720p HDR, HFR',
+    bitrate: 1000000,
+    audioBitrate: null,
+  },
+
+  335: {
+    mimeType: 'video/webm; codecs="VP9"',
+    qualityLabel: '1080p HDR, HFR',
+    bitrate: 1500000,
+    audioBitrate: null,
+  },
+
+  336: {
+    mimeType: 'video/webm; codecs="VP9"',
+    qualityLabel: '1440p HDR, HFR',
+    bitrate: 5000000,
+    audioBitrate: null,
+  },
+
+  337: {
+    mimeType: 'video/webm; codecs="VP9"',
+    qualityLabel: '2160p HDR, HFR',
+    bitrate: 12000000,
+    audioBitrate: null,
+  },
+
+};

+ 497 - 0
js/info.js

@@ -0,0 +1,497 @@
+const querystring = require('querystring');
+const sax = require('sax');
+const miniget = require('miniget');
+const utils = require('./utils');
+// Forces Node JS version of setTimeout for Electron based applications
+const {setTimeout} = require('timers');
+const formatUtils = require('./format-utils');
+const urlUtils = require('./url-utils');
+const extras = require('./info-extras');
+const sig = require('./sig');
+
+const BASE_URL = 'https://www.youtube.com/watch?v=';
+
+
+// Cache for cver used in getVideoInfoPage
+let cver = '2.20210622.10.00';
+
+
+// Special error class used to determine if an error is unrecoverable,
+// as in, ytdl-core should not try again to fetch the video metadata.
+// In this case, the video is usually unavailable in some way.
+class UnrecoverableError extends Error {
+}
+
+
+// List of URLs that show up in `notice_url` for age restricted videos.
+const AGE_RESTRICTED_URLS = [
+    'support.google.com/youtube/?p=age_restrictions',
+    'youtube.com/t/community_guidelines',
+];
+
+
+/**
+ * Gets info from a video without getting additional formats.
+ *
+ * @param {string} id
+ * @param {Object} options
+ * @returns {Promise<Object>}
+ */
+exports.getBasicInfo = async (id, options) => {
+    if (options.IPv6Block) {
+        options.requestOptions = Object.assign({}, options.requestOptions, {
+            family: 6,
+            localAddress: utils.getRandomIPv6(options.IPv6Block),
+        });
+    }
+    const retryOptions = Object.assign({}, miniget.defaultOptions, options.requestOptions);
+    options.requestOptions = Object.assign({}, options.requestOptions, {});
+    options.requestOptions.headers = Object.assign({},
+        {
+            // eslint-disable-next-line max-len
+            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.101 Safari/537.36',
+        }, options.requestOptions.headers);
+    const validate = info => {
+        let playErr = utils.playError(info.player_response, ['ERROR'], UnrecoverableError);
+        let privateErr = privateVideoError(info.player_response);
+        if (playErr || privateErr) {
+            throw playErr || privateErr;
+        }
+        return info && info.player_response && (
+            info.player_response.streamingData || isRental(info.player_response) || isNotYetBroadcasted(info.player_response)
+        );
+    };
+    let info = await pipeline([id, options], validate, retryOptions, [
+        getWatchHTMLPage,
+        getWatchJSONPage,
+        getVideoInfoPage,
+    ]);
+
+    Object.assign(info, {
+        formats: parseFormats(info.player_response),
+        related_videos: extras.getRelatedVideos(info),
+    });
+
+    // Add additional properties to info.
+    const media = extras.getMedia(info);
+    const additional = {
+        author: extras.getAuthor(info),
+        media,
+        likes: extras.getLikes(info),
+        dislikes: extras.getDislikes(info),
+        age_restricted: !!(media && AGE_RESTRICTED_URLS.some(url =>
+                Object.values(media).some(v => typeof v === 'string' && v.includes(url)))
+        ),
+
+        // Give the standard link to the video.
+        video_url: BASE_URL + id,
+        storyboards: extras.getStoryboards(info),
+        chapters: extras.getChapters(info),
+    };
+
+    info.videoDetails = extras.cleanVideoDetails(Object.assign({},
+        info.player_response && info.player_response.microformat &&
+        info.player_response.microformat.playerMicroformatRenderer,
+        info.player_response && info.player_response.videoDetails, additional), info);
+
+    return info;
+};
+
+const privateVideoError = player_response => {
+    let playability = player_response && player_response.playabilityStatus;
+    if (playability && playability.status === 'LOGIN_REQUIRED' && playability.messages &&
+        playability.messages.filter(m => /This is a private video/.test(m)).length) {
+        return new UnrecoverableError(playability.reason || (playability.messages && playability.messages[0]));
+    } else {
+        return null;
+    }
+};
+
+
+const isRental = player_response => {
+    let playability = player_response.playabilityStatus;
+    return playability && playability.status === 'UNPLAYABLE' &&
+        playability.errorScreen && playability.errorScreen.playerLegacyDesktopYpcOfferRenderer;
+};
+
+
+const isNotYetBroadcasted = player_response => {
+    let playability = player_response.playabilityStatus;
+    return playability && playability.status === 'LIVE_STREAM_OFFLINE';
+};
+
+
+const getWatchHTMLURL = (id, options) => `${BASE_URL + id}&hl=${options.lang || 'en'}`;
+
+const getWatchHTMLPageBody = (id, options) => {
+    const url = getWatchHTMLURL(id, options);
+    return exports.watchPageCache.getOrSet(url, () => utils.exposedMiniget(url, options).text());
+};
+
+
+const EMBED_URL = 'https://www.youtube.com/embed/';
+
+const getEmbedPageBody = (id, options) => {
+    const embedUrl = `${EMBED_URL + id}?hl=${options.lang || 'en'}`;
+    return utils.exposedMiniget(embedUrl, options).text();
+};
+
+const getHTML5player = body => {
+    let html5playerRes =
+        /<script\s+src="([^"]+)"(?:\s+type="text\/javascript")?\s+name="player_ias\/base"\s*>|"jsUrl":"([^"]+)"/
+            .exec(body);
+    return html5playerRes ? html5playerRes[1] || html5playerRes[2] : null;
+};
+
+
+const getIdentityToken = async (id, options, key, throwIfNotFound) => {
+    let page = await getWatchHTMLPageBody(id, options);
+    let match = page.match(/(["'])ID_TOKEN\1[:,]\s?"([^"]+)"/);
+    if (!match && throwIfNotFound) {
+        throw new UnrecoverableError('Cookie header used in request, but unable to find YouTube identity token');
+    }
+    return match && match[2];
+};
+
+/**
+ * Goes through each endpoint in the pipeline, retrying on failure if the error is recoverable.
+ * If unable to succeed with one endpoint, moves onto the next one.
+ *
+ * @param {Array.<Object>} args
+ * @param {Function} validate
+ * @param {Object} retryOptions
+ * @param {Array.<Function>} endpoints
+ * @returns {[Object, Object, Object]}
+ */
+const pipeline = async (args, validate, retryOptions, endpoints) => {
+    let info;
+    for (let func of endpoints) {
+        try {
+            const newInfo = await retryFunc(func, args.concat([info]), retryOptions);
+            if (newInfo.player_response) {
+                newInfo.player_response.videoDetails = assign(
+                    info && info.player_response && info.player_response.videoDetails,
+                    newInfo.player_response.videoDetails);
+                newInfo.player_response = assign(info && info.player_response, newInfo.player_response);
+            }
+            info = assign(info, newInfo);
+            if (validate(info, false)) {
+                break;
+            }
+        } catch (err) {
+            if (err instanceof UnrecoverableError || func === endpoints[endpoints.length - 1]) {
+                throw err;
+            }
+            // Unable to find video metadata... so try next endpoint.
+        }
+    }
+    return info;
+};
+
+
+/**
+ * Like Object.assign(), but ignores `null` and `undefined` from `source`.
+ *
+ * @param {Object} target
+ * @param {Object} source
+ * @returns {Object}
+ */
+const assign = (target, source) => {
+    if (!target || !source) {
+        return target || source;
+    }
+    for (let [key, value] of Object.entries(source)) {
+        if (value !== null && value !== undefined) {
+            target[key] = value;
+        }
+    }
+    return target;
+};
+
+
+/**
+ * Given a function, calls it with `args` until it's successful,
+ * or until it encounters an unrecoverable error.
+ * Currently, any error from miniget is considered unrecoverable. Errors such as
+ * too many redirects, invalid URL, status code 404, status code 502.
+ *
+ * @param {Function} func
+ * @param {Array.<Object>} args
+ * @param {Object} options
+ * @param {number} options.maxRetries
+ * @param {Object} options.backoff
+ * @param {number} options.backoff.inc
+ */
+const retryFunc = async (func, args, options) => {
+    let currentTry = 0, result;
+    while (currentTry <= options.maxRetries) {
+        try {
+            result = await func(...args);
+            break;
+        } catch (err) {
+            if (err instanceof UnrecoverableError ||
+                (err instanceof miniget.MinigetError && err.statusCode < 500) || currentTry >= options.maxRetries) {
+                throw err;
+            }
+            let wait = Math.min(++currentTry * options.backoff.inc, options.backoff.max);
+            await new Promise(resolve => setTimeout(resolve, wait));
+        }
+    }
+    return result;
+};
+
+
+const jsonClosingChars = /^[)\]}'\s]+/;
+
+const parseJSON = (source, varName, json) => {
+    if (!json || typeof json === 'object') {
+        return json;
+    } else {
+        try {
+            json = json.replace(jsonClosingChars, '');
+            return JSON.parse(json);
+        } catch (err) {
+            throw Error(`Error parsing ${varName} in ${source}: ${err.message}`);
+        }
+    }
+};
+
+
+const findJSON = (source, varName, body, left, right, prependJSON) => {
+    let jsonStr = utils.between(body, left, right);
+    if (!jsonStr) {
+        throw Error(`Could not find ${varName} in ${source}`);
+    }
+    return parseJSON(source, varName, utils.cutAfterJS(`${prependJSON}${jsonStr}`));
+};
+
+
+const findPlayerResponse = (source, info) => {
+    const player_response = info && (
+        (info.args && info.args.player_response) ||
+        info.player_response || info.playerResponse || info.embedded_player_response);
+    return parseJSON(source, 'player_response', player_response);
+};
+
+
+const getWatchJSONURL = (id, options) => `${getWatchHTMLURL(id, options)}&pbj=1`;
+const getWatchJSONPage = async (id, options) => {
+    const reqOptions = Object.assign({headers: {}}, options.requestOptions);
+    let cookie = reqOptions.headers.Cookie || reqOptions.headers.cookie;
+    reqOptions.headers = Object.assign({
+        'x-youtube-client-name': '1',
+        'x-youtube-client-version': cver,
+        'x-youtube-identity-token': exports.cookieCache.get(cookie || 'browser') || '',
+    }, reqOptions.headers);
+
+    const setIdentityToken = async (key, throwIfNotFound) => {
+        if (reqOptions.headers['x-youtube-identity-token']) {
+            return;
+        }
+        reqOptions.headers['x-youtube-identity-token'] = await getIdentityToken(id, options, key, throwIfNotFound);
+    };
+
+    if (cookie) {
+        await setIdentityToken(cookie, true);
+    }
+
+    const jsonUrl = getWatchJSONURL(id, options);
+    const body = await utils.exposedMiniget(jsonUrl, options, reqOptions).text();
+    let parsedBody = parseJSON('watch.json', 'body', body);
+    if (parsedBody.reload === 'now') {
+        await setIdentityToken('browser', false);
+    }
+    if (parsedBody.reload === 'now' || !Array.isArray(parsedBody)) {
+        throw Error('Unable to retrieve video metadata in watch.json');
+    }
+    let info = parsedBody.reduce((part, curr) => Object.assign(curr, part), {});
+    info.player_response = findPlayerResponse('watch.json', info);
+    info.html5player = info.player && info.player.assets && info.player.assets.js;
+
+    return info;
+};
+
+
+const getWatchHTMLPage = async (id, options) => {
+    let body = await getWatchHTMLPageBody(id, options);
+    let info = {page: 'watch'};
+    try {
+        cver = utils.between(body, '{"key":"cver","value":"', '"}');
+        info.player_response = findJSON('watch.html', 'player_response',
+            body, /\bytInitialPlayerResponse\s*=\s*\{/i, '</script>', '{');
+    } catch (err) {
+        let args = findJSON('watch.html', 'player_response', body, /\bytplayer\.config\s*=\s*{/, '</script>', '{');
+        info.player_response = findPlayerResponse('watch.html', args);
+    }
+    info.response = findJSON('watch.html', 'response', body, /\bytInitialData("\])?\s*=\s*\{/i, '</script>', '{');
+    info.html5player = getHTML5player(body);
+    return info;
+};
+
+
+const INFO_HOST = 'www.youtube.com';
+const INFO_PATH = '/get_video_info';
+const VIDEO_EURL = 'https://youtube.googleapis.com/v/';
+const getVideoInfoPage = async (id, options) => {
+    const url = new URL(`https://${INFO_HOST}${INFO_PATH}`);
+    url.searchParams.set('video_id', id);
+    url.searchParams.set('c', 'TVHTML5');
+    url.searchParams.set('cver', `7${cver.substr(1)}`);
+    url.searchParams.set('eurl', VIDEO_EURL + id);
+    url.searchParams.set('ps', 'default');
+    url.searchParams.set('gl', 'US');
+    url.searchParams.set('hl', options.lang || 'en');
+    url.searchParams.set('html5', '1');
+    const body = await utils.exposedMiniget(url.toString(), options).text();
+    let info = querystring.parse(body);
+    info.player_response = findPlayerResponse('get_video_info', info);
+    return info;
+};
+
+
+/**
+ * @param {Object} player_response
+ * @returns {Array.<Object>}
+ */
+const parseFormats = player_response => {
+    let formats = [];
+    if (player_response && player_response.streamingData) {
+        formats = formats
+            .concat(player_response.streamingData.formats || [])
+            .concat(player_response.streamingData.adaptiveFormats || []);
+    }
+    return formats;
+};
+
+
+/**
+ * Gets info from a video additional formats and deciphered URLs.
+ *
+ * @param {string} id
+ * @param {Object} options
+ * @returns {Promise<Object>}
+ */
+exports.getInfo = async (id, options) => {
+    let info = await exports.getBasicInfo(id, options);
+    const hasManifest =
+        info.player_response && info.player_response.streamingData && (
+            info.player_response.streamingData.dashManifestUrl ||
+            info.player_response.streamingData.hlsManifestUrl
+        );
+    let funcs = [];
+    if (info.formats.length) {
+        info.html5player = info.html5player ||
+            getHTML5player(await getWatchHTMLPageBody(id, options)) || getHTML5player(await getEmbedPageBody(id, options));
+        if (!info.html5player) {
+            throw Error('Unable to find html5player file');
+        }
+        const html5player = new URL(info.html5player, BASE_URL).toString();
+        funcs.push(sig.decipherFormats(info.formats, html5player, options));
+    }
+    if (hasManifest && info.player_response.streamingData.dashManifestUrl) {
+        let url = info.player_response.streamingData.dashManifestUrl;
+        funcs.push(getDashManifest(url, options));
+    }
+    if (hasManifest && info.player_response.streamingData.hlsManifestUrl) {
+        let url = info.player_response.streamingData.hlsManifestUrl;
+        funcs.push(getM3U8(url, options));
+    }
+
+    let results = await Promise.all(funcs);
+    info.formats = Object.values(Object.assign({}, ...results));
+    info.formats = info.formats.map(formatUtils.addFormatMeta);
+    info.formats.sort(formatUtils.sortFormats);
+    info.full = true;
+    return info;
+};
+
+
+/**
+ * Gets additional DASH formats.
+ *
+ * @param {string} url
+ * @param {Object} options
+ * @returns {Promise<Array.<Object>>}
+ */
+const getDashManifest = (url, options) => new Promise((resolve, reject) => {
+    let formats = {};
+    const parser = sax.parser(false);
+    parser.onerror = reject;
+    let adaptationSet;
+    parser.onopentag = node => {
+        if (node.name === 'ADAPTATIONSET') {
+            adaptationSet = node.attributes;
+        } else if (node.name === 'REPRESENTATION') {
+            const itag = parseInt(node.attributes.ID);
+            if (!isNaN(itag)) {
+                formats[url] = Object.assign({
+                    itag, url,
+                    bitrate: parseInt(node.attributes.BANDWIDTH),
+                    mimeType: `${adaptationSet.MIMETYPE}; codecs="${node.attributes.CODECS}"`,
+                }, node.attributes.HEIGHT ? {
+                    width: parseInt(node.attributes.WIDTH),
+                    height: parseInt(node.attributes.HEIGHT),
+                    fps: parseInt(node.attributes.FRAMERATE),
+                } : {
+                    audioSampleRate: node.attributes.AUDIOSAMPLINGRATE,
+                });
+            }
+        }
+    };
+    parser.onend = () => {
+        resolve(formats);
+    };
+    const req = utils.exposedMiniget(new URL(url, BASE_URL).toString(), options);
+    req.setEncoding('utf8');
+    req.on('error', reject);
+    req.on('data', chunk => {
+        parser.write(chunk);
+    });
+    req.on('end', parser.close.bind(parser));
+});
+
+
+/**
+ * Gets additional formats.
+ *
+ * @param {string} url
+ * @param {Object} options
+ * @returns {Promise<Array.<Object>>}
+ */
+const getM3U8 = async (url, options) => {
+    url = new URL(url, BASE_URL);
+    const body = await utils.exposedMiniget(url.toString(), options).text();
+    let formats = {};
+    body
+        .split('\n')
+        .filter(line => /^https?:\/\//.test(line))
+        .forEach(line => {
+            const itag = parseInt(line.match(/\/itag\/(\d+)\//)[1]);
+            formats[line] = {itag, url: line};
+        });
+    return formats;
+};
+
+
+// Cache get info functions.
+// In case a user wants to get a video's info before downloading.
+for (let funcName of ['getBasicInfo', 'getInfo']) {
+    /**
+     * @param {string} link
+     * @param {Object} options
+     * @returns {Promise<Object>}
+     */
+    const func = exports[funcName];
+    exports[funcName] = async (link, options = {}) => {
+        let id = await urlUtils.getVideoID(link);
+        const key = [funcName, id, options.lang].join('-');
+        return exports.cache.getOrSet(key, () => func(id, options));
+    };
+}
+
+
+// Export a few helpers.
+exports.validateID = urlUtils.validateID;
+exports.validateURL = urlUtils.validateURL;
+exports.getURLVideoID = urlUtils.getURLVideoID;
+exports.getVideoID = urlUtils.getVideoID;

+ 286 - 0
js/utils.js

@@ -0,0 +1,286 @@
+const miniget = require('miniget');
+
+
+/**
+ * Extract string inbetween another.
+ *
+ * @param {string} haystack
+ * @param {string} left
+ * @param {string} right
+ * @returns {string}
+ */
+exports.between = (haystack, left, right) => {
+  let pos;
+  if (left instanceof RegExp) {
+    const match = haystack.match(left);
+    if (!match) { return ''; }
+    pos = match.index + match[0].length;
+  } else {
+    pos = haystack.indexOf(left);
+    if (pos === -1) { return ''; }
+    pos += left.length;
+  }
+  haystack = haystack.slice(pos);
+  pos = haystack.indexOf(right);
+  if (pos === -1) { return ''; }
+  haystack = haystack.slice(0, pos);
+  return haystack;
+};
+
+
+/**
+ * Get a number from an abbreviated number string.
+ *
+ * @param {string} string
+ * @returns {number}
+ */
+exports.parseAbbreviatedNumber = string => {
+  const match = string
+    .replace(',', '.')
+    .replace(' ', '')
+    .match(/([\d,.]+)([MK]?)/);
+  if (match) {
+    let [, num, multi] = match;
+    num = parseFloat(num);
+    return Math.round(multi === 'M' ? num * 1000000 :
+      multi === 'K' ? num * 1000 : num);
+  }
+  return null;
+};
+
+/**
+ * Escape sequences for cutAfterJS
+ * @param {string} start the character string the escape sequence
+ * @param {string} end the character string to stop the escape seequence
+ * @param {undefined|Regex} startPrefix a regex to check against the preceding 10 characters
+ */
+const ESCAPING_SEQUENZES = [
+  // Strings
+  { start: '"', end: '"' },
+  { start: "'", end: "'" },
+  { start: '`', end: '`' },
+  // RegeEx
+  { start: '/', end: '/', startPrefix: /(^|[[{:;,/])\s?$/ },
+];
+
+/**
+ * Match begin and end braces of input JS, return only JS
+ *
+ * @param {string} mixedJson
+ * @returns {string}
+*/
+exports.cutAfterJS = mixedJson => {
+  // Define the general open and closing tag
+  let open, close;
+  if (mixedJson[0] === '[') {
+    open = '[';
+    close = ']';
+  } else if (mixedJson[0] === '{') {
+    open = '{';
+    close = '}';
+  }
+
+  if (!open) {
+    throw new Error(`Can't cut unsupported JSON (need to begin with [ or { ) but got: ${mixedJson[0]}`);
+  }
+
+  // States if the loop is currently inside an escaped js object
+  let isEscapedObject = null;
+
+  // States if the current character is treated as escaped or not
+  let isEscaped = false;
+
+  // Current open brackets to be closed
+  let counter = 0;
+
+  let i;
+  // Go through all characters from the start
+  for (i = 0; i < mixedJson.length; i++) {
+    // End of current escaped object
+    if (!isEscaped && isEscapedObject !== null && mixedJson[i] === isEscapedObject.end) {
+      isEscapedObject = null;
+      continue;
+    // Might be the start of a new escaped object
+    } else if (!isEscaped && isEscapedObject === null) {
+      for (const escaped of ESCAPING_SEQUENZES) {
+        if (mixedJson[i] !== escaped.start) continue;
+        // Test startPrefix against last 10 characters
+        if (!escaped.startPrefix || mixedJson.substring(i - 10, i).match(escaped.startPrefix)) {
+          isEscapedObject = escaped;
+          break;
+        }
+      }
+      // Continue if we found a new escaped object
+      if (isEscapedObject !== null) {
+        continue;
+      }
+    }
+
+    // Toggle the isEscaped boolean for every backslash
+    // Reset for every regular character
+    isEscaped = mixedJson[i] === '\\' && !isEscaped;
+
+    if (isEscapedObject !== null) continue;
+
+    if (mixedJson[i] === open) {
+      counter++;
+    } else if (mixedJson[i] === close) {
+      counter--;
+    }
+
+    // All brackets have been closed, thus end of JSON is reached
+    if (counter === 0) {
+      // Return the cut JSON
+      return mixedJson.substring(0, i + 1);
+    }
+  }
+
+  // We ran through the whole string and ended up with an unclosed bracket
+  throw Error("Can't cut unsupported JSON (no matching closing bracket found)");
+};
+
+
+/**
+ * Checks if there is a playability error.
+ *
+ * @param {Object} player_response
+ * @param {Array.<string>} statuses
+ * @param {Error} ErrorType
+ * @returns {!Error}
+ */
+exports.playError = (player_response, statuses, ErrorType = Error) => {
+  let playability = player_response && player_response.playabilityStatus;
+  if (playability && statuses.includes(playability.status)) {
+    return new ErrorType(playability.reason || (playability.messages && playability.messages[0]));
+  }
+  return null;
+};
+
+/**
+ * Does a miniget request and calls options.requestCallback if present
+ *
+ * @param {string} url the request url
+ * @param {Object} options an object with optional requestOptions and requestCallback parameters
+ * @param {Object} requestOptionsOverwrite overwrite of options.requestOptions
+ * @returns {miniget.Stream}
+ */
+exports.exposedMiniget = (url, options = {}, requestOptionsOverwrite) => {
+  const req = miniget(url, requestOptionsOverwrite || options.requestOptions);
+  if (typeof options.requestCallback === 'function') options.requestCallback(req);
+  return req;
+};
+
+/**
+ * Temporary helper to help deprecating a few properties.
+ *
+ * @param {Object} obj
+ * @param {string} prop
+ * @param {Object} value
+ * @param {string} oldPath
+ * @param {string} newPath
+ */
+exports.deprecate = (obj, prop, value, oldPath, newPath) => {
+  Object.defineProperty(obj, prop, {
+    get: () => {
+      console.warn(`\`${oldPath}\` will be removed in a near future release, ` +
+        `use \`${newPath}\` instead.`);
+      return value;
+    },
+  });
+};
+
+
+// Check for updates.
+const pkg = require('../package.json');
+const UPDATE_INTERVAL = 1000 * 60 * 60 * 12;
+exports.lastUpdateCheck = 0;
+exports.checkForUpdates = () => {
+  if (!process.env.YTDL_NO_UPDATE && !pkg.version.startsWith('0.0.0-') &&
+    Date.now() - exports.lastUpdateCheck >= UPDATE_INTERVAL) {
+    exports.lastUpdateCheck = Date.now();
+    return miniget('https://api.github.com/repos/fent/node-ytdl-core/releases/latest', {
+      headers: { 'User-Agent': 'ytdl-core' },
+    }).text().then(response => {
+      if (JSON.parse(response).tag_name !== `v${pkg.version}`) {
+        console.warn('\x1b[33mWARNING:\x1B[0m ytdl-core is out of date! Update with "npm install ytdl-core@latest".');
+      }
+    }, err => {
+      console.warn('Error checking for updates:', err.message);
+      console.warn('You can disable this check by setting the `YTDL_NO_UPDATE` env variable.');
+    });
+  }
+  return null;
+};
+
+
+/**
+ * Gets random IPv6 Address from a block
+ *
+ * @param {string} ip the IPv6 block in CIDR-Notation
+ * @returns {string}
+ */
+exports.getRandomIPv6 = ip => {
+  // Start with a fast Regex-Check
+  if (!isIPv6(ip)) throw Error('Invalid IPv6 format');
+  // Start by splitting and normalizing addr and mask
+  const [rawAddr, rawMask] = ip.split('/');
+  let base10Mask = parseInt(rawMask);
+  if (!base10Mask || base10Mask > 128 || base10Mask < 24) throw Error('Invalid IPv6 subnet');
+  const base10addr = normalizeIP(rawAddr);
+  // Get random addr to pad with
+  // using Math.random since we're not requiring high level of randomness
+  const randomAddr = new Array(8).fill(1).map(() => Math.floor(Math.random() * 0xffff));
+
+  // Merge base10addr with randomAddr
+  const mergedAddr = randomAddr.map((randomItem, idx) => {
+    // Calculate the amount of static bits
+    const staticBits = Math.min(base10Mask, 16);
+    // Adjust the bitmask with the staticBits
+    base10Mask -= staticBits;
+    // Calculate the bitmask
+    // lsb makes the calculation way more complicated
+    const mask = 0xffff - ((2 ** (16 - staticBits)) - 1);
+    // Combine base10addr and random
+    return (base10addr[idx] & mask) + (randomItem & (mask ^ 0xffff));
+  });
+  // Return new addr
+  return mergedAddr.map(x => x.toString('16')).join(':');
+};
+
+
+// eslint-disable-next-line max-len
+const IPV6_REGEX = /^(([0-9a-f]{1,4}:)(:[0-9a-f]{1,4}){1,6}|([0-9a-f]{1,4}:){1,2}(:[0-9a-f]{1,4}){1,5}|([0-9a-f]{1,4}:){1,3}(:[0-9a-f]{1,4}){1,4}|([0-9a-f]{1,4}:){1,4}(:[0-9a-f]{1,4}){1,3}|([0-9a-f]{1,4}:){1,5}(:[0-9a-f]{1,4}){1,2}|([0-9a-f]{1,4}:){1,6}(:[0-9a-f]{1,4})|([0-9a-f]{1,4}:){1,7}(([0-9a-f]{1,4})|:))\/(1[0-1]\d|12[0-8]|\d{1,2})$/;
+/**
+ * Quick check for a valid IPv6
+ * The Regex only accepts a subset of all IPv6 Addresses
+ *
+ * @param {string} ip the IPv6 block in CIDR-Notation to test
+ * @returns {boolean} true if valid
+ */
+const isIPv6 = exports.isIPv6 = ip => IPV6_REGEX.test(ip);
+
+
+/**
+ * Normalise an IP Address
+ *
+ * @param {string} ip the IPv6 Addr
+ * @returns {number[]} the 8 parts of the IPv6 as Integers
+ */
+const normalizeIP = exports.normalizeIP = ip => {
+  // Split by fill position
+  const parts = ip.split('::').map(x => x.split(':'));
+  // Normalize start and end
+  const partStart = parts[0] || [];
+  const partEnd = parts[1] || [];
+  partEnd.reverse();
+  // Placeholder for full ip
+  const fullIP = new Array(8).fill(0);
+  // Fill in start and end parts
+  for (let i = 0; i < Math.min(partStart.length, 8); i++) {
+    fullIP[i] = parseInt(partStart[i], 16) || 0;
+  }
+  for (let i = 0; i < Math.min(partEnd.length, 8); i++) {
+    fullIP[7 - i] = parseInt(partEnd[i], 16) || 0;
+  }
+  return fullIP;
+};

Някои файлове не бяха показани, защото твърде много файлове са промени