Repository: yt-dlp/yt-dlp

Issue:
The afreecatv website has just stopped working. 
### DO NOT REMOVE OR SKIP THE ISSUE TEMPLATE

- [x] I understand that I will be **blocked** if I remove or skip any mandatory\* field

### Checklist

- [X] I'm reporting a broken site
- [X] I've verified that I'm running yt-dlp version **2023.01.06** ([update instructions](https://github.com/yt-dlp/yt-dlp#update)) or later (specify commit)
- [X] I've checked that all provided URLs are playable in a browser with the same IP and same login details
- [X] I've checked that all URLs and arguments with special characters are [properly quoted or escaped](https://github.com/yt-dlp/yt-dlp/wiki/FAQ#video-url-contains-an-ampersand--and-im-getting-some-strange-output-1-2839-or-v-is-not-recognized-as-an-internal-or-external-command)
- [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

korean

### Provide a description that is worded well enough to be understood

The afreecatv website has just stopped working. The following prompt appears:
```
ERROR: [afreecatv] 81669846: Unable to extract station; please report this issue on  https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using  yt-dlp -U
  File "/usr/local/bin/yt-dlp/yt_dlp/extractor/common.py", line 680, in extract
    ie_result = self._real_extract(url)
  File "/usr/local/bin/yt-dlp/yt_dlp/extractor/afreecatv.py", line 232, in _real_extract
    station_id = self._search_regex(
  File "/usr/local/bin/yt-dlp/yt_dlp/extractor/common.py", line 1228, in _search_regex
    raise RegexNotFoundError('Unable to extract %s' % _name)
```

### Provide verbose output that clearly demonstrates the problem

- [X] Run **your** yt-dlp command with **-vU** flag added (`yt-dlp -vU <your command line>`)
- [X] Copy the WHOLE output (starting with `[debug] Command-line config`) and insert it below

### Complete Verbose Output

```shell
# /usr/local/bin/yt-dlp --cookies afreecatv.txt https://vod.afreecatv.com/player/81669846 --concat-playlist never --no-check-certificate -vU

[debug] Command-line config: ['--cookies', 'afreecatv.txt', 'https://vod.afreecatv.com/player/81669846', '--concat-playlist', 'never', '--no-check-certificate', '-vU']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version 2023.01.06 [6becd25] (zip)
[debug] Python 3.8.13 (CPython x86_64 64bit) - Linux-3.10.0-1160.66.1.el7.x86_64-x86_64-with-glibc2.17 (OpenSSL 1.1.1q  5 Jul 2022, glibc 2.17)
[debug] exe versions: ffmpeg 5.0 (setts), rtmpdump 2.4
[debug] Optional libraries: sqlite3-2.6.0
[debug] Proxy map: {}
[debug] Loaded 1760 extractors
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: 2023.01.06, Current version: 2023.01.06
yt-dlp is up to date (2023.01.06)
[afreecatv] Extracting URL: https://vod.afreecatv.com/player/81669846
[afreecatv] 81669846: Downloading webpage
ERROR: [afreecatv] 81669846: Unable to extract station; please report this issue on  https://github.com/yt-dlp/yt-dlp/issues?q= , filling out the appropriate issue template. Confirm you are on the latest version using  yt-dlp -U
  File "/usr/local/bin/yt-dlp/yt_dlp/extractor/common.py", line 680, in extract
    ie_result = self._real_extract(url)
  File "/usr/local/bin/yt-dlp/yt_dlp/extractor/afreecatv.py", line 232, in _real_extract
    station_id = self._search_regex(
  File "/usr/local/bin/yt-dlp/yt_dlp/extractor/common.py", line 1228, in _search_regex
    raise RegexNotFoundError('Unable to extract %s' % _name)
```



Discussion:
You could try adding `--force-generic` to your command as a workaround for now, but it would most likely result in the "restricted" version of this video being downloaded.
@bashonly Thank you for your reply. I tried it `--force-generic` and it  can be downloaded. However, no restricted content can be downloaded. I am waiting for repair. Thank you for your work.
Hi I also tried the workaround provided, it is working somewhat but the download speed is VERY slow
> Hi I also tried the workaround provided, it is working somewhat but the download speed is VERY slow

Until this gets fixed, I found a method that works with good download speed. Download the latest version of ffmpeg, then use the command: 

ffmpeg -headers "Referer: https://vod.afreecatv.com/player/XXXXXXXX" -headers "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36" -i example.m3u8 -c copy output.mp4

Copy and paste your own User-agent into the above example. I get a bunch of these "packet corrupt" sayings while downloading, but the final video turns out perfect. Also, many Afreecatv VODs are split up into multiple .m3u8 files. So make sure you are getting each one, then stitch them all together with a program like LosslessCut.
> > Hi I also tried the workaround provided, it is working somewhat but the download speed is VERY slow
> 
> Until this gets fixed, I found a method that works with good download speed. Download the latest version of ffmpeg, then use the command:
> 
> ffmpeg -headers "Referer: https://vod.afreecatv.com/player/XXXXXXXX" -headers "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36" -i example.m3u8 -c copy output.mp4
> 
> Copy and paste your own User-agent into the above example. I get a bunch of these "packet corrupt" sayings while downloading, but the final video turns out perfect. Also, many Afreecatv VODs are split up into multiple .m3u8 files. So make sure you are getting each one, then stitch them all together with a program like LosslessCut.

It's possible to use yt-dlp with the m3u8 urls, no need to use --force-generic even, and it works like before, the speed is better, alas there is some missing funcionality like proper video filename. While we wait for a fix this works fine, it's just the extra step-issue of getting the m3u8 urls.
It seems AfreecaTV modified:
1) The VOD pages to not include Station/BBS ID -- which is what the extractor is tripping over, but this is seemingly inconsequential as they can be stubbed with dummy values e.g. "99999999"
2) The http://afbbs.afreecatv.com:8080/api/video/get_video_info.php API which the extractor relies on to no longer include the video segments/playlist url in the XML response -- this is the killer that would force the use of a generic m3u8 discovery method, unless someone discovers an alternate API that continues to publish the video XML data.

I'm a noob so I'm hoping I'm wrong and expert contributors here can fix it in no time!
[http://afbbs.afreecatv.com:8080/api/video/get_video_info.php](http://afbbs.afreecatv.com:8080/api/video/get_video_info.php) still works if you crawl bbs and station ID from other points like vod overview. 
This proves only as a manual workaround though, but at least allows login/restricted content options.
Hmm is it broken maybe or can someone help me what I do wrong? It is restricted content because the stream was flagged 19+ for some segments.


```
yt-dlp --cookies cookies2.txt https://vod.afreecatv.com/player/98054524 --concat-playlist never --no-check-certificate -vU --force-generic                                                                                 1 ✘  8s  
[debug] Command-line config: ['--cookies', 'cookies2.txt', 'https://vod.afreecatv.com/player/98054524', '--concat-playlist', 'never', '--no-check-certificate', '-vU', '--force-generic']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version 2023.01.06 [6becd25]
[debug] Python 3.10.9 (CPython x86_64 64bit) - Linux-6.1.9-1-MANJARO-x86_64-with-glibc2.36 (OpenSSL 3.0.7 1 Nov 2022, glibc 2.36)
[debug] exe versions: ffmpeg 5.1.2 (setts), ffprobe 5.1.2, rtmpdump 2.4
[debug] Optional libraries: Crypto-3.17, certifi-2022.12.07, mutagen-1.46.0, sqlite3-2.6.0
[debug] Proxy map: {}
[debug] Loaded 1760 extractors
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: 2023.01.06, Current version: 2023.01.06
yt-dlp is up to date (2023.01.06)
[generic] Extracting URL: https://vod.afreecatv.com/player/98054524
[generic] 98054524: Downloading webpage
WARNING: [generic] Forcing generic information extractor
[generic] 98054524: Extracting information
[debug] Looking for embeds
ERROR: Unsupported URL: https://vod.afreecatv.com/player/98054524
Traceback (most recent call last):
  File "/usr/lib/python3.10/site-packages/yt_dlp/YoutubeDL.py", line 1502, in wrapper
    return func(self, *args, **kwargs)
  File "/usr/lib/python3.10/site-packages/yt_dlp/YoutubeDL.py", line 1578, in __extract_info
    ie_result = ie.extract(url)
  File "/usr/lib/python3.10/site-packages/yt_dlp/extractor/common.py", line 680, in extract
    ie_result = self._real_extract(url)
  File "/usr/lib/python3.10/site-packages/yt_dlp/extractor/generic.py", line 2523, in _real_extract
    raise UnsupportedError(url)
yt_dlp.utils.UnsupportedError: Unsupported URL: https://vod.afreecatv.com/player/98054524

```
#4514
#4514 is not related to this at all
Right, #4514 is specifically tracking age-restricted videos not extracting properly, and this issue is tracking the extractor being completely broken. Reopened
It doesn't work for me at all now even for videos with no age restricted content. 

```
yt-dlp --cookies cookies2.txt https://vod.afreecatv.com/player/98469676 --concat-playlist never --no-check-certificate -vU --force-generic
[debug] Command-line config: ['--cookies', 'cookies2.txt', 'https://vod.afreecatv.com/player/98469676', '--concat-playlist', 'never', '--no-check-certificate', '-vU', '--force-generic']
[debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version 2023.01.06 [6becd25]
[debug] Python 3.10.9 (CPython x86_64 64bit) - Linux-6.1.11-1-MANJARO-x86_64-with-glibc2.37 (OpenSSL 3.0.8 7 Feb 2023, glibc 2.37)
[debug] exe versions: ffmpeg 5.1.2 (setts), ffprobe 5.1.2, rtmpdump 2.4
[debug] Optional libraries: Crypto-3.17, certifi-2022.12.07, mutagen-1.46.0, sqlite3-2.6.0
[debug] Proxy map: {}
[debug] Loaded 1760 extractors
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: 2023.01.06, Current version: 2023.01.06
yt-dlp is up to date (2023.01.06)
[generic] Extracting URL: https://vod.afreecatv.com/player/98469676
[generic] 98469676: Downloading webpage
WARNING: [generic] Forcing generic information extractor
[generic] 98469676: Extracting information
[debug] Looking for embeds
ERROR: Unsupported URL: https://vod.afreecatv.com/player/98469676
Traceback (most recent call last):
  File "/usr/lib/python3.10/site-packages/yt_dlp/YoutubeDL.py", line 1502, in wrapper
    return func(self, *args, **kwargs)
  File "/usr/lib/python3.10/site-packages/yt_dlp/YoutubeDL.py", line 1578, in __extract_info
    ie_result = ie.extract(url)
  File "/usr/lib/python3.10/site-packages/yt_dlp/extractor/common.py", line 680, in extract
    ie_result = self._real_extract(url)
  File "/usr/lib/python3.10/site-packages/yt_dlp/extractor/generic.py", line 2523, in _real_extract
    raise UnsupportedError(url)
yt_dlp.utils.UnsupportedError: Unsupported URL: https://vod.afreecatv.com/player/98469676
```

Same here. Seems something else might have changed, as I was able to download vods with `--force-generic` until just now.

Resolving patch:
diff --git a/yt_dlp/extractor/afreecatv.py b/yt_dlp/extractor/afreecatv.py
--- a/yt_dlp/extractor/afreecatv.py
+++ b/yt_dlp/extractor/afreecatv.py
@@ -76,59 +76,6 @@ class AfreecaTVIE(InfoExtractor):
             },
         }],
         'skip': 'Video is gone',
-    }, {
-        'url': 'http://vod.afreecatv.com/PLAYER/STATION/18650793',
-        'info_dict': {
-            'id': '18650793',
-            'ext': 'mp4',
-            'title': '오늘은 다르다! 쏘님의 우월한 위아래~ 댄스리액션!',
-            'thumbnail': r're:^https?://.*\.jpg$',
-            'uploader': '윈아디',
-            'uploader_id': 'badkids',
-            'duration': 107,
-        },
-        'params': {
-            'skip_download': True,
-        },
-    }, {
-        'url': 'http://vod.afreecatv.com/PLAYER/STATION/10481652',
-        'info_dict': {
-            'id': '10481652',
-            'title': "BJ유트루와 함께하는 '팅커벨 메이크업!'",
-            'thumbnail': 're:^https?://(?:video|st)img.afreecatv.com/.*$',
-            'uploader': 'dailyapril',
-            'uploader_id': 'dailyapril',
-            'duration': 6492,
-        },
-        'playlist_count': 2,
-        'playlist': [{
-            'md5': 'd8b7c174568da61d774ef0203159bf97',
-            'info_dict': {
-                'id': '20160502_c4c62b9d_174361386_1',
-                'ext': 'mp4',
-                'title': "BJ유트루와 함께하는 '팅커벨 메이크업!' (part 1)",
-                'thumbnail': 're:^https?://(?:video|st)img.afreecatv.com/.*$',
-                'uploader': 'dailyapril',
-                'uploader_id': 'dailyapril',
-                'upload_date': '20160502',
-                'duration': 3601,
-            },
-        }, {
-            'md5': '58f2ce7f6044e34439ab2d50612ab02b',
-            'info_dict': {
-                'id': '20160502_39e739bb_174361386_2',
-                'ext': 'mp4',
-                'title': "BJ유트루와 함께하는 '팅커벨 메이크업!' (part 2)",
-                'thumbnail': 're:^https?://(?:video|st)img.afreecatv.com/.*$',
-                'uploader': 'dailyapril',
-                'uploader_id': 'dailyapril',
-                'upload_date': '20160502',
-                'duration': 2891,
-            },
-        }],
-        'params': {
-            'skip_download': True,
-        },
     }, {
         # non standard key
         'url': 'http://vod.afreecatv.com/PLAYER/STATION/20515605',
@@ -146,8 +93,8 @@ class AfreecaTVIE(InfoExtractor):
             'skip_download': True,
         },
     }, {
-        # PARTIAL_ADULT
-        'url': 'http://vod.afreecatv.com/PLAYER/STATION/32028439',
+        # adult content
+        'url': 'https://vod.afreecatv.com/player/97267690',
         'info_dict': {
             'id': '20180327_27901457_202289533_1',
             'ext': 'mp4',
@@ -161,16 +108,25 @@ class AfreecaTVIE(InfoExtractor):
         'params': {
             'skip_download': True,
         },
-        'expected_warnings': ['adult content'],
+        'skip': 'The VOD does not exist',
     }, {
         'url': 'http://www.afreecatv.com/player/Player.swf?szType=szBjId=djleegoon&nStationNo=11273158&nBbsNo=13161095&nTitleNo=36327652',
         'only_matching': True,
     }, {
-        'url': 'http://vod.afreecatv.com/PLAYER/STATION/15055030',
-        'only_matching': True,
-    }, {
-        'url': 'http://vod.afreecatv.com/player/15055030',
-        'only_matching': True,
+        'url': 'https://vod.afreecatv.com/player/96753363',
+        'info_dict': {
+            'id': '20230108_9FF5BEE1_244432674_1',
+            'ext': 'mp4',
+            'uploader_id': 'rlantnghks',
+            'uploader': '페이즈으',
+            'duration': 10840,
+            'thumbnail': 'http://videoimg.afreecatv.com/php/SnapshotLoad.php?rowKey=20230108_9FF5BEE1_244432674_1_r',
+            'upload_date': '20230108',
+            'title': '젠지 페이즈',
+        },
+        'params': {
+            'skip_download': True,
+        },
     }]
 
     @staticmethod
@@ -223,26 +179,21 @@ def _perform_login(self, username, password):
     def _real_extract(self, url):
         video_id = self._match_id(url)
 
-        webpage = self._download_webpage(url, video_id)
-
-        if re.search(r'alert\(["\']This video has been deleted', webpage):
-            raise ExtractorError(
-                'Video %s has been deleted' % video_id, expected=True)
-
-        station_id = self._search_regex(
-            r'nStationNo\s*=\s*(\d+)', webpage, 'station')
-        bbs_id = self._search_regex(
-            r'nBbsNo\s*=\s*(\d+)', webpage, 'bbs')
-        video_id = self._search_regex(
-            r'nTitleNo\s*=\s*(\d+)', webpage, 'title', default=video_id)
-
         partial_view = False
         adult_view = False
         for _ in range(2):
+            data = self._download_json(
+                'https://api.m.afreecatv.com/station/video/a/view',
+                video_id, headers={'Referer': url}, data=urlencode_postdata({
+                    'nTitleNo': video_id,
+                    'nApiLevel': 10,
+                }))['data']
+            if traverse_obj(data, ('code', {int})) == -6221:
+                raise ExtractorError('The VOD does not exist', expected=True)
             query = {
                 'nTitleNo': video_id,
-                'nStationNo': station_id,
-                'nBbsNo': bbs_id,
+                'nStationNo': data['station_no'],
+                'nBbsNo': data['bbs_no'],
             }
             if partial_view:
                 query['partialView'] = 'SKIP_ADULT'


Test patch: