Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ie/niconico] Add support for DMS server; use robust info extraction logic; allow empty danmaku #9282

Merged
merged 20 commits into from Feb 29, 2024

Conversation

pzhlkj6612
Copy link
Contributor

IMPORTANT: PRs without the template will be CLOSED

Description of your pull request and other information

This PR cannot be finished without @xpadev-net's work. See #8685 for more details.

Fixes #8389, resolves #8758, fixes #9254

Because of the download method, using DMS may help us avoid the speed throttle of DMC (#7365).

The DMS service is still in the test stage. Test videos:

Call for help

How to make sure the output dict from traverse_obj() must contain all specified keys? Then I can get values from the dict without testing each key.

        data = traverse_obj(api_data, ({
            'foo': (...),
            'bar': (...),
        }, {
            lambda data: data if all(key in data for key in [
                'foo', 'bar',
            ]) else None
        }))

        if data:
            data['foo'] * data['bar'] == 42
Template

Before submitting a pull request make sure you have:

In order to be accepted and merged into yt-dlp each piece of code must be in public domain or released under Unlicense. Check all of the following options that apply:

  • I am the original author of this code and I am willing to release it under Unlicense
  • I am not the original author of this code but it is in public domain or released under Unlicense (provide reliable evidence)

What is the purpose of your pull request?

pzhlkj6612 and others added 7 commits February 24, 2024 04:37
This commit cannot be finished without @xpadev-net's work.

Co-authored-by: XPA <96982836+xpadev-net@users.noreply.github.com>
We are not able to check if the video is behind a paywall, login
  required or geo-restricted.
For comments' download, we don't need to care about if the video is
  members-only. No comments means no comments.
test_download.py:239: self.assertTrue(tc_filename in finished_hook_called)

How to solve it?
@pzhlkj6612
Copy link
Contributor Author

I cannot make those tests complete (522d9d1):

[niconico_dmc] Heartbeat with 40 second interval ... 
[debug] File locking is not supported. Proceeding without locking[download] Destination: test_....mp4 
[download] 100% of   10.00KiB in 00:00:00 at 21.72KiB/s
F
======================================================================
FAIL: test_Niconico_all (__main__.TestDownload):
----------------------------------------------------------------------
Traceback (most recent call last):
  File ".../yt-dlp/test/test_download.py", line 298, in test_template
    getattr(self, test_name)()
  File ".../yt-dlp/test/test_download.py", line 239, in test_template
    self.assertTrue(tc_filename in finished_hook_called)
AssertionError: False is not true

@pzhlkj6612
Copy link
Contributor Author

For thumbnails, have both "ext" and "preference" been removed?

'ext': 'jpg',
'preference': thumb_prefs(key),

@pukkandan pukkandan added site-enhancement Feature request for some website site-bug Issue with a specific website labels Feb 24, 2024
@Dioxaz
Copy link

Dioxaz commented Feb 24, 2024

Small correction about sm43110779 (34') - 【高画質版】ヒジリーリ・リーリリEx【東方MMD】 - ニコニコ. It looks like resolutions above 480p are available to guests as well, as I've just checked. Either I made a mistake when trying to review it the first time (apologizes) or they updated something that made that video available to unregistered and non-premium users as well.

This is a video longer than 30 minutes. Please someone confirm for other recent videos over 30 minutes in duration and being available in formats above 480p.

yt_dlp/extractor/niconico.py Outdated Show resolved Hide resolved
yt_dlp/extractor/niconico.py Outdated Show resolved Hide resolved
yt_dlp/extractor/niconico.py Outdated Show resolved Hide resolved
yt_dlp/extractor/niconico.py Outdated Show resolved Hide resolved
yt_dlp/extractor/niconico.py Outdated Show resolved Hide resolved
Comment on lines 460 to 467
'audios': ('media', 'domand', 'audios', ..., {
lambda item: (item['id'], {
'format_id': str(parse_bitrate(item['id'])),
'abr': float_or_none(item['bitRate'], scale=1000),
'asr': item['samplingRate'],
'acodec': 'aac',
'ext': 'm4a',
}) if item['isAvailable'] else None
Copy link
Member

@bashonly bashonly Feb 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think once you have to use a transformation to construct an entire format_dict then it's time to break this up and use separate variables/traversals.

Can you show an example of what the POST data that we send with the API request should look like? Maybe I'm misreading the code, but it looks like we are sending a tuple of the id and the format dict, and that seems wrong

Also, you may have found that the transformation is always called regardless of whether or not the path succeeds up to that point, and that's why you included if item['isAvailable'] else None in the lambda function instead of just filtering. You handled it correctly here, but IMO we should avoid such complexity in transformations to prevent unintended side effects

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you show an example of what the POST data that we send with the API request should look like?

Of course. The POST request is:

curl -fsSL 'https://nvapi.nicovideo.jp/v1/watch/sm.../access-rights/hls?actionTrackId=...' \
  -H 'x-access-right-key: ...' \
  -H 'x-frontend-id: 6' \
  -H 'x-frontend-version: 0' \
  -H 'x-request-with: https://www.nicovideo.jp' \
  --data '{"outputs": [
    ["video-h264-1080p","audio-aac-128kbps"],
    ["video-h264-720p","audio-aac-128kbps"],
    ["video-h264-480p","audio-aac-128kbps"],
    ["video-h264-360p","audio-aac-128kbps"],
    ["video-h264-144p","audio-aac-128kbps"]
  ]}' | jq .

The response is:

{
  "meta": {
    "status": 201
  },
  "data": {
    "contentUrl": "https://delivery.domand.nicovideo.jp/hlsbid/.../playlists/variants/....m3u8?...",
    "createTime": "...",
    "expireTime": "..."
  }
}

Maybe I'm misreading the code, but it looks like we are sending a tuple of the id and the format dict, and that seems wrong

Well, I'm only sending all IDs, not the format dicts.


I've split the extraction, please re-review it if you have free time.

@bashonly bashonly added the pending-fixes PR has had changes requested label Feb 26, 2024
Co-authored-by: bashonly <88596187+bashonly@users.noreply.github.com>
@pzhlkj6612
Copy link
Contributor Author

Hi, @Dioxaz !

Small correction about sm43110779 (34') - 【高画質版】ヒジリーリ・リーリリEx【東方MMD】 - ニコニコ. It looks like resolutions above 480p are available to guests as well, as I've just checked.

I opened sm43110779 in Firefox and Chrome but found both 480p and 720p are Premium only:

20240226-131839-sm43110779-quality

Did you try opening the video in the private mode or incognito mode of your browser?

Co-authored-by: bashonly <88596187+bashonly@users.noreply.github.com>
@Dioxaz
Copy link

Dioxaz commented Feb 26, 2024

@pzhlkj6612

That's interesting. Yes, I did open the video in a private window. I've just tried a few minutes ago and this is what I am getting on my side:
sm43110779_resolutionoptions
Can this be due to economy hours? I'm confused. I took the screenshot above in Firefox 123.0 at 8:40PM approx. (20:40) French time, so a few minutes prior to this post I'm writing. And I'm seeing the same thing in Chrome, and am not even logged in there.

pzhlkj6612 and others added 2 commits February 27, 2024 16:57
Labels are "1080p", "720p", "480p", "360p" and "144p", so the
  "extract_video_quality" function will not work.

Co-authored-by: bashonly <88596187+bashonly@users.noreply.github.com>
@pukkandan pukkandan removed the pending-fixes PR has had changes requested label Feb 28, 2024
@pzhlkj6612
Copy link
Contributor Author

@Dioxaz ,

Can this be due to economy hours?

Possible! At Tue Feb 27 05:00:00 PM UTC 2024 and Wed Feb 28 04:00:00 AM UTC 2024 , I'm able to get both 480p and 720p of sm43110779 from DMS and Niconico website, but Wed Feb 28 12:00:00 PM UTC 2024 is not:

  [info] Available formats for sm43110779:
  ID                             EXT RESOLUTION FPS │   FILESIZE   TBR PROTO │ VCODEC        VBR ACODEC      ABR ASR MORE INFO
  ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  64                             m4a audio only     │ ~ 17.12MiB   69k m3u8  │ audio only        aac         69k 48k Main Audio
+ 128                            m4a audio only     │ ~ 28.74MiB  115k m3u8  │ audio only        aac        115k 48k Main Audio
  h264_360p_low-aac_64kbps-hls   mp4 640x360        │ ~ 90.64MiB  364k dmc   │ h264         300k aac         64k 48k DMC Low-Quality HLS
  h264_360p_low-aac_64kbps-http  mp4 640x360        │ ~ 90.64MiB  364k dmc   │ h264         300k aac         64k 48k DMC Low-Quality HTTP
+ h264_360p_low-aac_128kbps-hls  mp4 640x360        │ ~106.58MiB  428k dmc   │ h264         300k aac        128k 48k DMC Low-Quality HLS
+ h264_360p_low-aac_128kbps-http mp4 640x360        │ ~106.58MiB  428k dmc   │ h264         300k aac        128k 48k DMC Low-Quality HTTP
  153                            mp4 256x144     30 │ ~ 38.15MiB  153k m3u8  │ avc1.4d401e  153k video only
  h264_360p-aac_64kbps-hls       mp4 640x360        │ ~165.35MiB  664k dmc   │ h264         600k aac         64k 48k DMC 360p HLS
  h264_360p-aac_64kbps-http      mp4 640x360        │ ~165.35MiB  664k dmc   │ h264         600k aac         64k 48k DMC 360p HTTP
+ h264_360p-aac_128kbps-hls      mp4 640x360        │ ~181.29MiB  728k dmc   │ h264         600k aac        128k 48k DMC 360p HLS
+ h264_360p-aac_128kbps-http     mp4 640x360        │ ~181.29MiB  728k dmc   │ h264         600k aac        128k 48k DMC 360p HTTP
  614                            mp4 640x360     30 │ ~152.95MiB  614k m3u8  │ avc1.4d401e  614k video only
+ 2072                           mp4 854x480     60 │ ~515.90MiB 2072k m3u8  │ avc1.4d4020 2072k video only
+ 2118                           mp4 1280x720    60 │ ~527.51MiB 2118k m3u8  │ avc1.4d4020 2118k video only

This is a video longer than 30 minutes. Please someone confirm for other recent videos over 30 minutes in duration and being available in formats above 480p.

The DMS code also works with sm43318461 (42' 37") - ◆高機動幻想ガンパレード・マーチ 実況プレイ◆がみ千翼長のガンパレ講座② - ニコニコ. The "economy hours" rule of this video is the same as sm43110779.

And I also found that not all videos are affected by that rule. For example, I'm able to get high quality streams (720p & 1080p) from sm43211773 (33' 27") - 【東方手書き劇場】クベラさん家のナズーリン - ニコニコ at ANY time.


Googling "niconico economy mode" will give us more about "Niconico's economy mode hours".

yt_dlp/extractor/niconico.py Outdated Show resolved Hide resolved
yt_dlp/extractor/niconico.py Outdated Show resolved Hide resolved
yt_dlp/extractor/niconico.py Outdated Show resolved Hide resolved
@pzhlkj6612
Copy link
Contributor Author

@bashonly , thanks for your great refactoring work! The new code does work.


Today I learned:

Today I also learned:

  • s/minimal bitrate/lowest bitrate/
  • self._remove_duplicate_formats() ; 🙄 well, it didn't tell me it's there. now I'm going to forget itertools.groupby() ...

.

@bashonly bashonly self-assigned this Feb 29, 2024
@bashonly bashonly merged commit aa13a8e into yt-dlp:master Feb 29, 2024
6 checks passed
@pzhlkj6612 pzhlkj6612 deleted the niconico/domand branch March 1, 2024 00:38
@pzhlkj6612
Copy link
Contributor Author

Yesterday I discovered:


I wrote code to fix "vbr" and "tbr" and those lines have been modified during refactor.

Before:

 # Then, correct the bitrate of all videos by minusing the minimal audio bitrate. 
 min_abr = traverse_obj(min(dms_audio_fmts, key=lambda fmt: fmt['abr']), ('abr'), default=0) 
 for i, fmt in enumerate(dms_video_fmts): 
     vbr = fmt['tbr'] - min_abr 
     dms_video_fmts[i].update({ 
         'format_id': str(round(vbr)), 
         'vbr': vbr,    # <---------------
         'tbr': None,   # <---------------
     }) 

Now:

        # Calculate the true vbr/tbr by subtracting the lowest abr
        min_abr = min(traverse_obj(audios, (..., 'bitRate', {float_or_none})), default=0) / 1000
        for video_fmt in video_fmts:
            video_fmt['tbr'] -= min_abr   # <---------------------------
            video_fmt['format_id'] = f'video-{video_fmt["tbr"]:.0f}'
            yield video_fmt

Leaving "vbr" empty and filling only "tbr" is OK. Our code will calculate bitrates:

yt-dlp/yt_dlp/utils/_utils.py

Lines 5392 to 5402 in aa13a8e

# Determine missing bitrates
if format.get('vcodec') == 'none':
format['vbr'] = 0
if format.get('acodec') == 'none':
format['abr'] = 0
if not format.get('vbr') and format.get('vcodec') != 'none':
format['vbr'] = try_call(lambda: format['tbr'] - format['abr']) or None
if not format.get('abr') and format.get('acodec') != 'none':
format['abr'] = try_call(lambda: format['tbr'] - format['vbr']) or None
if not format.get('tbr'):
format['tbr'] = try_call(lambda: format['vbr'] + format['abr']) or None

.

@betsu0
Copy link

betsu0 commented Mar 2, 2024

I'm Premium user.
I can't download Premium movie.

yt-dlp_master(2024/03/01) = NG

[debug] Command-line config: ['-vU', '-u', 'PRIVATE', '-p', 'PRIVATE', 'https://www.nicovideo.jp/watch/so43452967']
[debug] Encodings: locale cp932, fs utf-8, pref cp932, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2023.12.30 from yt-dlp/yt-dlp [f10589e34]
[debug] Lazy loading extractors is disabled
[debug] Python 3.11.8 (CPython AMD64 64bit) - Windows-10-10.0.22631-SP0 (OpenSSL 3.0.13 30 Jan 2024)
[debug] exe versions: ffmpeg N-113881-gf7545e90df-20240301 (setts)
[debug] Optional libraries: sqlite3-3.43.1
[debug] Proxy map: {}
[debug] Request Handlers: urllib
[debug] Loaded 1834 extractors
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: stable@2023.12.30 from yt-dlp/yt-dlp
yt-dlp is up to date (stable@2023.12.30 from yt-dlp/yt-dlp)
[niconico] Acquiring Login session
[niconico] Logging in
[niconico] Extracting URL: https://www.nicovideo.jp/watch/so43452967
[niconico] so43452967: Downloading webpage
ERROR: [niconico] so43452967: This video is for members only. Use --cookies, --cookies-from-browser, --username and --password, --netrc-cmd, or --netrc (niconico) to provide account credentials
  File "E:\ダウンロード\yt-dlp-master\yt_dlp\extractor\common.py", line 732, in extract
    ie_result = self._real_extract(url)
                ^^^^^^^^^^^^^^^^^^^^^^^
  File "E:\ダウンロード\yt-dlp-master\yt_dlp\extractor\niconico.py", line 489, in _real_extract
    self.raise_login_required('This video is for members only', metadata_available=True)
  File "E:\ダウンロード\yt-dlp-master\yt_dlp\extractor\common.py", line 1192, in raise_login_required
    raise ExtractorError(msg, expected=True)

yt-dlp_master(2024/02/23) + #8685 patch = OK

[debug] Command-line config: ['-vU', '-u', 'PRIVATE', '-p', 'PRIVATE', 'https://www.nicovideo.jp/watch/so43452967']
[debug] Encodings: locale cp932, fs utf-8, pref cp932, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version stable@2023.12.30 from yt-dlp/yt-dlp [f10589e34]
[debug] Lazy loading extractors is disabled
[debug] Python 3.11.8 (CPython AMD64 64bit) - Windows-10-10.0.22631-SP0 (OpenSSL 3.0.13 30 Jan 2024)
[debug] exe versions: ffmpeg N-113881-gf7545e90df-20240301 (setts)
[debug] Optional libraries: sqlite3-3.43.1
[debug] Proxy map: {}
[debug] Request Handlers: urllib
[debug] Loaded 1834 extractors
[debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest
Latest version: stable@2023.12.30 from yt-dlp/yt-dlp
yt-dlp is up to date (stable@2023.12.30 from yt-dlp/yt-dlp)
[niconico] Acquiring Login session
[niconico] Logging in
[niconico] Extracting URL: https://www.nicovideo.jp/watch/so43452967
[niconico] so43452967: Downloading webpage
[debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec:vp9.2(10), channels, acodec, size, br, asr, proto, vext, aext, hasaud, source, id
[debug] Default format spec: bestvideo*+bestaudio/best
[info] so43452967: Downloading 1 format(s): dms-h264-1080p-aac-192kbps-hls
[debug] Invoking niconico_dms downloader on "niconico_dms:so43452967/video-h264-1080p/audio-aac-192kbps"
[niconico_dms] Downloading from DMS
[niconico] so43452967: Requesting Manifest Url
[download] Destination: ダンジョン飯 第9話「テンタクルス⧸シチュー」 [so43452967].mp4
[debug] ffmpeg command line: ffmpeg -y -loglevel verbose -cookies "nicosid=1709377148.612548794; path=/; domain=.nicovideo.jp;
user_session=user_session_9106136_d6e93b7db897d8dea55c9ae56dadc41413b7ebd69a5ac7916e8a4227926d64aa; path=/; domain=.nicovideo.jp;
user_session_secure=OTEwNjEzNjpFVjNKUzVZTVNQMW9tanhjZzR5NFQ4RDEwMWsyMHBDcGFSWk1RN1ZTc3Ro; path=/; domain=.nicovideo.jp;
domand_bid=9106136:96a2ce63d1e1130de3d9d86097c29678f709f1517cda8bb7da132283d4fdde81; path=/; domain=.nicovideo.jp;
" -headers "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.85 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Sec-Fetch-Mode: navigate
Origin: https://www.nicovideo.jp
Referer: https://www.nicovideo.jp/watch/so43452967
" -i "https://delivery.domand.nicovideo.jp/shlsbid/65dbea5cd76609a88f96336b/playlists/variants/c732154a2ff1129a.m3u8?sh=_6wmV3bxfw1kRLaZ7SIgf9mV&session=1e104986088f7e341d06fcd3554eb62dc732154a2ff1129a0000000065e457fcd85c430a23d98d93&Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly9kZWxpdmVyeS5kb21hbmQubmljb3ZpZGVvLmpwL3NobHNiaWQvNjVkYmVhNWNkNzY2MDlhODhmOTYzMzZiL3BsYXlsaXN0cy92YXJpYW50cy9jNzMyMTU0YTJmZjExMjlhLm0zdThcXD8qIiwiQ29uZGl0aW9uIjp7IkRhdGVMZXNzVGhhbiI6eyJBV1M6RXBvY2hUaW1lIjoxNzA5NDYzNTQ4fX19XX0_&Signature=qz-RDVq3HnVLZFpWMfNCdV7tHM8FTv6z0HYRTYo5V16T7K-J5Lt95lQqzjho9ramc32Nlg16od4AIU8Y~oNWac6va6zUJn3qLtKudvLPiMdoHVlG~E4i3UwOU9QRqoCd1wiMwknxjkaIt1tIIkHTN0j0g~3ksL8TOq3R4pn2Vn1M3NNbRyjANfj2AhJhtW5m-ra21K-AmAZ1D6OVL~Wl2GmU67zyjzQzEi4JPTLnHUVkNbK84ciVo8IVW7aY1nOs3LBo1OuAL66sMVFPwo~33L67PBGlZpd5WiMCpa0-f1rsoQB-i7wS0kMWAwFwgVBHczZ~tcI1x-jGhcivAZENuw__&Key-Pair-Id=K11RB80NFXU134" -c copy -f mp4 "file:ダンジョン飯 第9話「テンタクルス⧸シチュー」 [so43452967].mp4.part"
ffmpeg version N-113881-gf7545e90df-20240301 Copyright (c) 2000-2024 the FFmpeg developers
  built with gcc 13.2.0 (crosstool-NG 1.25.0.232_c175b21)
  configuration: --prefix=/ffbuild/prefix --pkg-config-flags=--static --pkg-config=pkg-config --cross-prefix=x86_64-w64-mingw32- --arch=x86_64 --target-os=mingw32 --enable-gpl --enable-version3 --disable-debug --disable-w32threads --enable-pthreads --enable-iconv --enable-libxml2 --enable-zlib --enable-libfreetype --enable-libfribidi --enable-gmp --enable-lzma --enable-fontconfig --enable-libharfbuzz --enable-libvorbis --enable-opencl --disable-libpulse --enable-libvmaf --disable-libxcb --disable-xlib --enable-amf --enable-libaom --enable-libaribb24 --enable-avisynth --enable-chromaprint --enable-libdav1d --enable-libdavs2 --disable-libfdk-aac --enable-ffnvcodec --enable-cuda-llvm --enable-frei0r --enable-libgme --enable-libkvazaar --enable-libaribcaption --enable-libass --enable-libbluray --enable-libjxl --enable-libmp3lame --enable-libopus --enable-librist --enable-libssh --enable-libtheora --enable-libvpx --enable-libwebp --enable-lv2 --enable-libvpl --enable-openal --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenh264 --enable-libopenjpeg --enable-libopenmpt --enable-librav1e --enable-librubberband --enable-schannel --enable-sdl2 --enable-libsoxr --enable-libsrt --enable-libsvtav1 --enable-libtwolame --enable-libuavs3d --disable-libdrm --enable-vaapi --enable-libvidstab --enable-vulkan --enable-libshaderc --enable-libplacebo --enable-libx264 --enable-libx265 --enable-libxavs2 --enable-libxvid --enable-libzimg --enable-libzvbi --extra-cflags=-DLIBTWOLAME_STATIC --extra-cxxflags= --extra-ldflags=-pthread --extra-ldexeflags= --extra-libs=-lgomp --extra-version=20240301
  libavutil      58. 39.100 / 58. 39.100
  libavcodec     60. 40.100 / 60. 40.100
  libavformat    60. 22.101 / 60. 22.101
  libavdevice    60.  4.100 / 60.  4.100
  libavfilter     9. 17.100 /  9. 17.100
  libswscale      7.  6.100 /  7.  6.100
  libswresample   4. 13.100 /  4. 13.100
  libpostproc    57.  4.100 / 57.  4.100
[tcp @ 000001b0fa34b980] Starting connection attempt to 18.65.185.77 port 443
[tcp @ 000001b0fa34b980] Successfully connected to 18.65.185.77 port 443
[hls @ 000001b0fa399f80] Skip ('#EXT-X-VERSION:6')
[hls @ 000001b0fa399f80] Skip ('#EXT-X-INDEPENDENT-SEGMENTS')
[hls @ 000001b0fa399f80] Opening 'https://delivery.domand.nicovideo.jp/shlsbid/65dbea5cd76609a88f96336b/playlists/media/audio-aac-192kbps.m3u8?sh=_6wmV3bxfw1kRLaZ7SIgf9mV&session=1e104986088f7e341d06fcd3554eb62dc732154a2ff1129a0000000065e457fcd85c430a23d98d93&Expires=1709463548&Signature=uajaOJEyuJLBdtMULcoRV0Sb6wgLJxB5-mzSYylSBDI7~zLpgTv7VA0czN3GlFvF72vyqjbq8fIUYxEQorVtmp~NollavjV~MiYqMg2Y~oaAESU~GOodA~IQXdzTl8e5gFTidx0U9uQIj3zkpQkUJtn7B50wC9lQDzDRG-vfkBXIW7vX2488vGhoCt3sPYFLgErk0qOMPkSGQv0noICi3HHv--E3FG6EkVJrD5pza7Vjjgnk2j7ZDlP1OvwwQz0NSCntLe55Ra4878PZlkLsjdPHt0S41PhaqSJDUUDWc-ZvUbe~RPNyn4IkRerhdjs~l5SbHIGQzMfRtfpull9j2w__&Key-Pair-Id=K11RB80NFXU134' for reading
[tcp @ 000001b0fa3944c0] Starting connection attempt to 18.65.185.77 port 443
[tcp @ 000001b0fa3944c0] Successfully connected to 18.65.185.77 port 443
[hls @ 000001b0fa399f80] Skip ('#EXT-X-VERSION:6')
[https @ 000001b0fa3c8a00] Opening 'https://delivery.domand.nicovideo.jp/shlsbid/65dbea5cd76609a88f96336b/playlists/media/video-h264-1080p.m3u8?sh=_6wmV3bxfw1kRLaZ7SIgf9mV&session=1e104986088f7e341d06fcd3554eb62dc732154a2ff1129a0000000065e457fcd85c430a23d98d93&Expires=1709463548&Signature=ee2fUT77ac-Ml~In6wILh5AnmRsxY~yLIrHvMvkHoRZNCSz0Pgr8l~gosmh3TTJ9C~6UuNkNbQ2AOgrfTpU4-w0IIUduHoGZsXuZ7bc8guib~2X~oNr7HfcFEA1nhtTs92W3tHxIUAHejg7CkRUrJhk7p~9ToiwJD8uB1C9ihxVFt6r1QQL7Qq37CIiZSAo54TNHTfZBtCaNrbZ75kd8ryixumMV7dVWDZ~eESWTsccMCZxRkMw~NTM4rf2tLrUcOa50GA8fZ8OtqchEMho2~dk91axtNwBe4bYrupmWMhJxb~5lV6rQ7fLm5IBkStHjjHqlukRDrpdiufAcGRTQjQ__&Key-Pair-Id=K11RB80NFXU134' for reading
[hls @ 000001b0fa399f80] Skip ('#EXT-X-VERSION:6')
[hls @ 000001b0fa399f80] HLS request for url 'https://delivery.domand.nicovideo.jp/shlsbid/65dbea5cd76609a88f96336b/segments/65dbea5cd76609a88f96336b/audio/1/audio-aac-192kbps/init001.cmfa?sh=54hQr9YYjW7xVzGykXDu1sr3S7jLJWhTbuAH4D2-ipM13wRvToqAdRwI6TeJmNMw5NmrHJeJ&session=1e104986088f7e341d06fcd3554eb62dc732154a2ff1129a0000000065e457fcd85c430a23d98d93&Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly9kZWxpdmVyeS5kb21hbmQubmljb3ZpZGVvLmpwL3NobHNiaWQvNjVkYmVhNWNkNzY2MDlhODhmOTYzMzZiL3NlZ21lbnRzLzY1ZGJlYTVjZDc2NjA5YTg4Zjk2MzM2Yi9hdWRpby8xL2F1ZGlvLWFhYy0xOTJrYnBzLyoiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE3MDk0NjM1NDh9fX1dfQ__&Signature=rleH3my-8QjqMRoNyZ4qFGzSXiVCQDQBSpr0pZw7SB1-a9yFFuFBG-cxjJocDBwpiYXhW79lSFT6fYoZRKuYmHBiWD2N8A5yq7aF5Ot1TKgSiWJR72XOIFJXJVicEN6l63pBa4yqp86k-Wspa8gMRQrQC8P9KfeWogtkbVVVmNFHx8kp7Vtzizh~lFldsVN-FSS2fTUTvJNQM2X3W2ZQbNfjc7D2j4gJExad3V9r27hgbTekfsrfbDEF8DpaPVTeUZIbal9XH2GeK7asDiJW6YuyvHDQDAETkVJBhsFzLubasFTKbg8~CARUfomjJcmt90TlM5YwNApiS6~XSlWcCw__&Key-Pair-Id=K11RB80NFXU134', offset 0, playlist 0
[hls @ 000001b0fa399f80] Opening 'https://delivery.domand.nicovideo.jp/shlsbid/65dbea5cd76609a88f96336b/segments/65dbea5cd76609a88f96336b/audio/1/audio-aac-192kbps/init001.cmfa?sh=54hQr9YYjW7xVzGykXDu1sr3S7jLJWhTbuAH4D2-ipM13wRvToqAdRwI6TeJmNMw5NmrHJeJ&session=1e104986088f7e341d06fcd3554eb62dc732154a2ff1129a0000000065e457fcd85c430a23d98d93&Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly9kZWxpdmVyeS5kb21hbmQubmljb3ZpZGVvLmpwL3NobHNiaWQvNjVkYmVhNWNkNzY2MDlhODhmOTYzMzZiL3NlZ21lbnRzLzY1ZGJlYTVjZDc2NjA5YTg4Zjk2MzM2Yi9hdWRpby8xL2F1ZGlvLWFhYy0xOTJrYnBzLyoiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE3MDk0NjM1NDh9fX1dfQ__&Signature=rleH3my-8QjqMRoNyZ4qFGzSXiVCQDQBSpr0pZw7SB1-a9yFFuFBG-cxjJocDBwpiYXhW79lSFT6fYoZRKuYmHBiWD2N8A5yq7aF5Ot1TKgSiWJR72XOIFJXJVicEN6l63pBa4yqp86k-Wspa8gMRQrQC8P9KfeWogtkbVVVmNFHx8kp7Vtzizh~lFldsVN-FSS2fTUTvJNQM2X3W2ZQbNfjc7D2j4gJExad3V9r27hgbTekfsrfbDEF8DpaPVTeUZIbal9XH2GeK7asDiJW6YuyvHDQDAETkVJBhsFzLubasFTKbg8~CARUfomjJcmt90TlM5YwNApiS6~XSlWcCw__&Key-Pair-Id=K11RB80NFXU134' for reading
[tcp @ 000001b0fbeb5540] Starting connection attempt to 18.65.185.77 port 443
[tcp @ 000001b0fbeb5540] Successfully connected to 18.65.185.77 port 443
[AVIOContext @ 000001b0fbeb5e40] Statistics: 728 bytes read, 0 seeks
[hls @ 000001b0fa399f80] HLS request for url 'https://delivery.domand.nicovideo.jp/shlsbid/65dbea5cd76609a88f96336b/segments/65dbea5cd76609a88f96336b/audio/1/audio-aac-192kbps/001.cmfa?sh=54hQr9YYjW7xVzGykXDu1sr3S7jLJWhTbuAH4D2-ipM13wRvToqAdRwI6TeJmNMw5NmrHJeJ&session=1e104986088f7e341d06fcd3554eb62dc732154a2ff1129a0000000065e457fcd85c430a23d98d93&Policy=eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly9kZWxpdmVyeS5kb21hbmQubmljb3ZpZGVvLmpwL3NobHNiaWQvNjVkYmVhNWNkNzY2MDlhODhmOTYzMzZiL3NlZ21lbnRzLzY1ZGJlYTVjZDc2NjA5YTg4Zjk2MzM2Yi9hdWRpby8xL2F1ZGlvLWFhYy0xOTJrYnBzLyoiLCJDb25kaXRpb24iOnsiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE3MDk0NjM1NDh9fX1dfQ__&Signature=rleH3my-8QjqMRoNyZ4qFGzSXiVCQDQBSpr0pZw7SB1-a9yFFuFBG-cxjJocDBwpiYXhW79lSFT6fYoZRKuYmHBiWD2N8A5yq7aF5Ot1TKgSiWJR72XOIFJXJVicEN6l63pBa4yqp86k-Wspa8gMRQrQC8P9KfeWogtkbVVVmNFHx8kp7Vtzizh~lFldsVN-FSS2fTUTvJNQM2X3W2ZQbNfjc7D2j4gJExad3V9r27hgbTekfsrfbDEF8DpaPVTeUZIbal9XH2GeK7asDiJW6YuyvHDQDAETkVJBhsFzLubasFTKbg8~CARUfomjJcmt90TlM5YwNApiS6~XSlWcCw__&Key-Pair-Id=K11RB80NFXU134', offset 0, playlist 0

@pzhlkj6612
Copy link
Contributor Author

Hi, @betsu0 !

I'm Premium user.
I can't download Premium movie.

...
[niconico] Acquiring Login session
[niconico] Logging in
[niconico] Extracting URL: https://www.nicovideo.jp/watch/so43452967
[niconico] so43452967: Downloading webpage
ERROR: [niconico] so43452967: This video is for members only. Use --cookies, --cookies-from-browser, --username and --password, --netrc-cmd, or --netrc (niconico) to provide account credentials
  File "E:\ダウンロード\yt-dlp-master\yt_dlp\extractor\common.py", line 732, in extract
    ie_result = self._real_extract(url)
                ^^^^^^^^^^^^^^^^^^^^^^^
  File "E:\ダウンロード\yt-dlp-master\yt_dlp\extractor\niconico.py", line 489, in _real_extract
    self.raise_login_required('This video is for members only', metadata_available=True)
  File "E:\ダウンロード\yt-dlp-master\yt_dlp\extractor\common.py", line 1192, in raise_login_required
    raise ExtractorError(msg, expected=True)

...

Thanks for your detailed feedback. I'll go find a Niconico Premium account to perform test.

@fireattack
Copy link
Contributor

fireattack commented Mar 2, 2024

club_joined = traverse_obj(api_data, ('channel', 'viewer', 'follow', 'isFollowed', {bool}))
if club_joined is None:
fail_msg = self._html_search_regex(
r'<p[^>]+\bclass="fail-message"[^>]*>(?P<msg>.+?)</p>',
webpage, 'fail message', default=None, group='msg')
if fail_msg:
self.raise_login_required(clean_html(fail_msg), metadata_available=True)
elif not club_joined:
self.raise_login_required('This video is for members only', metadata_available=True)

This part is wrong.

You don't need to join/follow the "club" to watch these videos.

(You don't even need premium account, either; this video can be viewed as a guest as soon as you have legit Japanese IP.)

@pzhlkj6612

@pzhlkj6612
Copy link
Contributor Author

@fireattack

club_joined = traverse_obj(api_data, ('channel', 'viewer', 'follow', 'isFollowed', {bool}))
if club_joined is None:
fail_msg = self._html_search_regex(
r'<p[^>]+\bclass="fail-message"[^>]*>(?P<msg>.+?)</p>',
webpage, 'fail message', default=None, group='msg')
if fail_msg:
self.raise_login_required(clean_html(fail_msg), metadata_available=True)
elif not club_joined:
self.raise_login_required('This video is for members only', metadata_available=True)

This part is wrong.

You don't need to join/follow the "club" to watch these videos.

(You don't even need premium account, either; this video can be viewed as a guest as soon as you have legit Japanese IP.)

Thanks.

IIRC this is the test for members-only videos in niconico fanclub. Do you happen to know the correct way to handle both Premium videos and fanclub's ones?

@fireattack
Copy link
Contributor

Can't we just check if api_data["media"] exists or not?

I cannot find any Premium-only content, but this one https://www.nicovideo.jp/watch/so43461409 is gated for the members.

And it returns

  "media": {
    "domand": null,
    "delivery": null,
    "deliveryLegacy": null
  },

@fireattack
Copy link
Contributor

fireattack commented Mar 2, 2024

image
We can maybe also do some judgement around these "payment" info but I'm not sure if we can be very comprehensive.

Edit: we can also try reverse-engineering https://resource.video.nimg.jp/web/scripts/pages/watch/modern/watch_app_5fd9b82ecc8c93f40019.js if we want to match the reasons given by Nico's official frontend.

aalsuwaidi pushed a commit to aalsuwaidi/yt-dlp that referenced this pull request Apr 21, 2024
Closes yt-dlp#8389, Closes yt-dlp#8758, Closes yt-dlp#9254
Authored by: pzhlkj6612, xpadev-net
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
site-bug Issue with a specific website site-enhancement Feature request for some website
Projects
None yet
7 participants