Repository: yt-dlp/yt-dlp

Issue:
【Mixch.tv】 Add support for archived concerts
### Checklist

- [X] I'm reporting a site feature request
- [X] I've verified that I'm running yt-dlp version **2021.12.27**. ([update instructions](https://github.com/yt-dlp/yt-dlp#update))
- [X] I've checked that all provided URLs are alive and playable in a browser
- [X] I've searched the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar issues including closed ones. DO NOT post duplicates
- [X] I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue)
- [X] I've read about [sharing account credentials](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#are-you-willing-to-share-account-details-if-needed) and I'm willing to share it if required

### Region

_No response_

### Example URLs

https://mixch.tv/archive/421

### Description

[Mixch.tv](https://mixch.tv/) _**(be careful while opening the site unless you are into earrape - autoplay, high volume and bad mic)**_ has

> _live shows/streams_

> _videos_

> _live concerts_

> _archived concerts_

Both _live_ and _archived concerts_ require buying a ticket.

**Mixch** extractor (by @Lesmiscore) can download _live shows/streams_ or `https://mixch.tv/u/id` (probably _live concerts_ as well):

`_VALID_URL = r'https?://(?:www\.)?mixch\.tv/u/(?P<id>\d+)'`

**Generic** extractor can download _videos_ or `https://mixch.tv/m/id`

But neither work for archived concerts or `https://mixch.tv/archive/id`. Same log if I try to use `login` or `login & password` or `login & cookies` or `login & password & cookies`. Archive page source code: https://pastebin.com/bK8cQ6xY

Cookies are in _Netscape_ format and from the `mixch.tv`, `google.com` and `myaccount.google.com` via EditTheCookie. After compiling all cookies in a single txt I run `curl -b cookie.txt --cookie-jar newcookiefile.txt 'https://mixch.tv'` (which I think is not necessary, but I tried with and without it anyway). If I try to use `--cookies-from-browser` - I'm getting an error.

Another possible issue is you can login only with SNS - Twitter/LINE(Japanese(actually South Korean) messaging app)/Google/FB/Apple.

Honestly, can't figure out what the issue could be since I have very limited programming knowledge. I can only guess:

1. I use `--cookies` incorrectly

> I used `yt-dlp -Uv --cookies=cookie.txt -u=login@gmail.com -p=password https://mixch.tv/archive/421` Login and password are changed of course. Also I get _"This file is generated by yt-dlp.  Do not edit."_ at the beginning of the cookies.txt after I use it - I'm probably using it the right way.

2. Login issue

> The input command doesn't "see" the video and can't download since there is nothing there (also if you access the archived concert web page and you are not logged in - it redirects you to the main page if it matters). I don't exactly know how it works hence I can't be sure if it does log me in or not. Should I use only login name or add @gmail.com as well? I tried both.

3. SNS-only login

> I don't know if there is a workaround about it.

You can buy a ticket for a live show and it would be archived for some time (the archived concert I'm interested in is available only for a week until 23/01). I bought the ticket, but want the archive forever. I'm on yt-dlp Discord server -  `柚子#2807`.

### Verbose log

```shell
[debug] Command-line config: ['-Uv', '--cookies=cookie.txt', '-u=PRIVATE', '-p=PRIVATE', 'https://mixch.tv/archive/421']
[debug] Encodings: locale UTF-8, fs utf-8, out utf-8, err utf-8, pref UTF-8
[debug] yt-dlp version 2021.12.27 [6223f67a8]
[debug] Lazy loading extractors is disabled
[debug] Python version 3.8.12 (CPython 64bit) - Linux-4.4.0-19041-Microsoft-x86_64-with-glibc2.27
[debug] exe versions: ffmpeg 4.3.2-0york0, ffprobe 4.3.2-0york0, phantomjs 5
[debug] Optional libraries: Cryptodome, secretstorage, mutagen, sqlite, websockets
[debug] Proxy map: {}
Latest version: 2021.12.27, Current version: 2021.12.27
yt-dlp is up to date (2021.12.27)
[debug] [generic] Extracting URL: https://mixch.tv/archive/421
[generic] 421: Requesting header
WARNING: [generic] Could not send HEAD request to https://mixch.tv/archive/421: HTTP Error 405: Method Not Allowed
[generic] 421: Downloading webpage
WARNING: [generic] Falling back on generic information extractor.
[generic] 421: Extracting information
[debug] Looking for video embeds
ERROR: Unsupported URL: https://mixch.tv/archive/421
Traceback (most recent call last):
  File "/home/red/.local/lib/python3.8/site-packages/yt_dlp/YoutubeDL.py", line 1365, in wrapper
    return func(self, *args, **kwargs)
  File "/home/red/.local/lib/python3.8/site-packages/yt_dlp/YoutubeDL.py", line 1435, in __extract_info
    ie_result = ie.extract(url)
  File "/home/red/.local/lib/python3.8/site-packages/yt_dlp/extractor/common.py", line 610, in extract
    ie_result = self._real_extract(url)
  File "/home/red/.local/lib/python3.8/site-packages/yt_dlp/extractor/generic.py", line 3909, in _real_extract
    raise UnsupportedError(url)
yt_dlp.utils.UnsupportedError: Unsupported URL: https://mixch.tv/archive/421
```

【Mixch.tv】 Add support for archived concerts
### Checklist

- [X] I'm reporting a site feature request
- [X] I've verified that I'm running yt-dlp version **2021.12.27**. ([update instructions](https://github.com/yt-dlp/yt-dlp#update))
- [X] I've checked that all provided URLs are alive and playable in a browser
- [X] I've searched the [bugtracker](https://github.com/yt-dlp/yt-dlp/issues?q=) for similar issues including closed ones. DO NOT post duplicates
- [X] I've read the [guidelines for opening an issue](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#opening-an-issue)
- [X] I've read about [sharing account credentials](https://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#are-you-willing-to-share-account-details-if-needed) and I'm willing to share it if required

### Region

_No response_

### Example URLs

https://mixch.tv/archive/421

### Description

[Mixch.tv](https://mixch.tv/) _**(be careful while opening the site unless you are into earrape - autoplay, high volume and bad mic)**_ has

> _live shows/streams_

> _videos_

> _live concerts_

> _archived concerts_

Both _live_ and _archived concerts_ require buying a ticket.

**Mixch** extractor (by @Lesmiscore) can download _live shows/streams_ or `https://mixch.tv/u/id` (probably _live concerts_ as well):

`_VALID_URL = r'https?://(?:www\.)?mixch\.tv/u/(?P<id>\d+)'`

**Generic** extractor can download _videos_ or `https://mixch.tv/m/id`

But neither work for archived concerts or `https://mixch.tv/archive/id`. Same log if I try to use `login` or `login & password` or `login & cookies` or `login & password & cookies`. Archive page source code: https://pastebin.com/bK8cQ6xY

Cookies are in _Netscape_ format and from the `mixch.tv`, `google.com` and `myaccount.google.com` via EditTheCookie. After compiling all cookies in a single txt I run `curl -b cookie.txt --cookie-jar newcookiefile.txt 'https://mixch.tv'` (which I think is not necessary, but I tried with and without it anyway). If I try to use `--cookies-from-browser` - I'm getting an error.

Another possible issue is you can login only with SNS - Twitter/LINE(Japanese(actually South Korean) messaging app)/Google/FB/Apple.

Honestly, can't figure out what the issue could be since I have very limited programming knowledge. I can only guess:

1. I use `--cookies` incorrectly

> I used `yt-dlp -Uv --cookies=cookie.txt -u=login@gmail.com -p=password https://mixch.tv/archive/421` Login and password are changed of course. Also I get _"This file is generated by yt-dlp.  Do not edit."_ at the beginning of the cookies.txt after I use it - I'm probably using it the right way.

2. Login issue

> The input command doesn't "see" the video and can't download since there is nothing there (also if you access the archived concert web page and you are not logged in - it redirects you to the main page if it matters). I don't exactly know how it works hence I can't be sure if it does log me in or not. Should I use only login name or add @gmail.com as well? I tried both.

3. SNS-only login

> I don't know if there is a workaround about it.

You can buy a ticket for a live show and it would be archived for some time (the archived concert I'm interested in is available only for a week until 23/01). I bought the ticket, but want the archive forever. I'm on yt-dlp Discord server -  `柚子#2807`.

### Verbose log

```shell
[debug] Command-line config: ['-Uv', '--cookies=cookie.txt', '-u=PRIVATE', '-p=PRIVATE', 'https://mixch.tv/archive/421']
[debug] Encodings: locale UTF-8, fs utf-8, out utf-8, err utf-8, pref UTF-8
[debug] yt-dlp version 2021.12.27 [6223f67a8]
[debug] Lazy loading extractors is disabled
[debug] Python version 3.8.12 (CPython 64bit) - Linux-4.4.0-19041-Microsoft-x86_64-with-glibc2.27
[debug] exe versions: ffmpeg 4.3.2-0york0, ffprobe 4.3.2-0york0, phantomjs 5
[debug] Optional libraries: Cryptodome, secretstorage, mutagen, sqlite, websockets
[debug] Proxy map: {}
Latest version: 2021.12.27, Current version: 2021.12.27
yt-dlp is up to date (2021.12.27)
[debug] [generic] Extracting URL: https://mixch.tv/archive/421
[generic] 421: Requesting header
WARNING: [generic] Could not send HEAD request to https://mixch.tv/archive/421: HTTP Error 405: Method Not Allowed
[generic] 421: Downloading webpage
WARNING: [generic] Falling back on generic information extractor.
[generic] 421: Extracting information
[debug] Looking for video embeds
ERROR: Unsupported URL: https://mixch.tv/archive/421
Traceback (most recent call last):
  File "/home/red/.local/lib/python3.8/site-packages/yt_dlp/YoutubeDL.py", line 1365, in wrapper
    return func(self, *args, **kwargs)
  File "/home/red/.local/lib/python3.8/site-packages/yt_dlp/YoutubeDL.py", line 1435, in __extract_info
    ie_result = ie.extract(url)
  File "/home/red/.local/lib/python3.8/site-packages/yt_dlp/extractor/common.py", line 610, in extract
    ie_result = self._real_extract(url)
  File "/home/red/.local/lib/python3.8/site-packages/yt_dlp/extractor/generic.py", line 3909, in _real_extract
    raise UnsupportedError(url)
yt_dlp.utils.UnsupportedError: Unsupported URL: https://mixch.tv/archive/421
```



Discussion:
Do you have any example which doesn't require payment to watch? If there's not, PM or email me account details at Reddit or  `nao20010128 at gmail dot com` (replace words appropriately)
Do you have any example which doesn't require payment to watch? If there's not, PM or email me account details at Reddit or  `nao20010128 at gmail dot com` (replace words appropriately)

Resolving patch:
diff --git a/yt_dlp/extractor/extractors.py b/yt_dlp/extractor/extractors.py
--- a/yt_dlp/extractor/extractors.py
+++ b/yt_dlp/extractor/extractors.py
@@ -828,7 +828,10 @@
 )
 from .mit import TechTVMITIE, OCWMITIE
 from .mitele import MiTeleIE
-from .mixch import MixchIE
+from .mixch import (
+    MixchIE,
+    MixchArchiveIE,
+)
 from .mixcloud import (
     MixcloudIE,
     MixcloudUserIE,
diff --git a/yt_dlp/extractor/mixch.py b/yt_dlp/extractor/mixch.py
--- a/yt_dlp/extractor/mixch.py
+++ b/yt_dlp/extractor/mixch.py
@@ -11,7 +11,7 @@ class MixchIE(InfoExtractor):
     IE_NAME = 'mixch'
     _VALID_URL = r'https?://(?:www\.)?mixch\.tv/u/(?P<id>\d+)'
 
-    TESTS = [{
+    _TESTS = [{
         'url': 'https://mixch.tv/u/16236849/live',
         'skip': 'don\'t know if this live persists',
         'info_dict': {
@@ -53,3 +53,33 @@ def _real_extract(self, url):
             }],
             'is_live': True,
         }
+
+
+class MixchArchiveIE(InfoExtractor):
+    IE_NAME = 'mixch:archive'
+    _VALID_URL = r'https?://(?:www\.)?mixch\.tv/archive/(?P<id>\d+)'
+
+    _TESTS = [{
+        'url': 'https://mixch.tv/archive/421',
+        'skip': 'paid video, no DRM. expires at Jan 23',
+        'info_dict': {
+            'id': '421',
+            'title': '96NEKO SHOW TIME',
+        }
+    }]
+
+    def _real_extract(self, url):
+        video_id = self._match_id(url)
+        webpage = self._download_webpage(url, video_id)
+
+        html5_videos = self._parse_html5_media_entries(
+            url, webpage.replace('video-js', 'video'), video_id, 'hls')
+        if not html5_videos:
+            self.raise_login_required(method='cookies')
+        infodict = html5_videos[0]
+        infodict.update({
+            'id': video_id,
+            'title': self._html_search_regex(r'class="archive-title">(.+?)</', webpage, 'title')
+        })
+
+        return infodict


Test patch: