Skip to content

Latest commit

 

History

History
98 lines (84 loc) · 2.78 KB

README.md

File metadata and controls

98 lines (84 loc) · 2.78 KB

Crunpyroll


Features 🔥

  • Python 3.7+ support
  • Clean and modern code
  • Updated to latest Crunchyroll API

Installation ⚙️

# Using Git
pip install -U git+https://github.com/stefanodvx/crunpyroll

# Using PyPi (Recommended)
pip install -U crunpyroll

Documentation 📄

The documentation page undergoes automatic updates with each push. To access the latest documentation page, kindly refer to our Read the Docs project.


Example Code ❓

import crunpyroll
import asyncio

client = crunpyroll.Client(
    email="email",
    password="password",
    locale="it-IT"
)
def main():
    # Start client and login
    client.start()
    # Search for Attack on Titan
    query = client.search("Attack On Titan")
    series_id = query.items[0].id
    print(series_id)
    # Retrieve all seasons of the series
    seasons = client.get_seasons(series_id)
    print(seasons)

main()

Downloading content 🔑

Crunchyroll has recently implemented the Widevine and PlayReady Digital Rights Management (DRM) systems, which has led to challenges for certain users attempting to download content from the platform.

Subsequently, the following code provides an illustrative example of obtaining decryption keys through the utilities of the pywidevine library and an L3 Content Decryption Module (CDM).

from pywidevine.cdm import Cdm
from pywidevine.pssh import PSSH
from pywidevine.device import Device
...
device = Device.load("l3cdm.wvd")
cdm = Cdm.from_device(device)
# Get streams of the episode/movie
streams = client.get_streams("GRVDQ1G4R")
# Get manifest of the format you prefer
manifest = client.get_manifest(streams.hardsubs[0].url)
# print(manifest)
# Get Widevine PSSH from manifest
pssh = PSSH(manifest.content_protection.widevine.pssh)
session_id = cdm.open()
challenge = cdm.get_license_challenge(session_id, pssh)
license = client.get_license(
    streams.media_id,
    challenge=challenge,
    token=streams.token
)
cdm.parse_license(session_id, license)
for key in cdm.get_keys(session_id, "CONTENT"):
    print(f"{key.kid.hex}:{key.key.hex()}")
cdm.close(session_id)
# Deleting active streams will prevent Crunchyroll HTTP 420 (too_many_queued_streams) error.
client.delete_active_stream(
    streams.media_id,
    token=streams.token
)

Output:

056ec1ca849e350181753cacc9bd404b:2307a188ecd8de3859b71b30791f171d

Tip

Decryption keys are universally applicable to both video and audio streams, maintaining consistency across all available formats.