VideoHelp Forum




+ Reply to Thread
Results 1 to 16 of 16
  1. Hi,

    I'm trying to install playready proxy and play ready proxyapi from ThatNotEasy I wonder if any of you have made it wrk successfully please ?
    my PRPApi is launching fine, but my PRP edge plugin don't make any call on the API.

    Here is my PRP plugin screen
    Image
    [Attachment 86164 - Click to enlarge]


    Thanks a lot for any help
    Quote Quote  
  2. Feels Good Man 2nHxWW6GkN1l916N3ayz8HQoi's Avatar
    Join Date
    Jan 2024
    Location
    Pepe Island
    Search Comp PM
    Seems that extension is still kinda buggy. Hope they fix it. Here's what worked for me without bothering too much. There are 2 directories
    - PlayReadyProxy-API-main => the local api
    - PlayReadyProxy-main => the extension

    Unpack them both. In the local api folder:
    - rename the env and config like their git tells you to do
    - copy in that folder (near the app.py) the prd file. Mine is called: "your_prd_file.prd"
    - then go to config.ini and change
    Code:
    [CDM]
    DEVICE_FILE = device/ # DEVICE FILENAME
    DEVICE_NAME = # DEVICE NAME
    to
    Code:
    [CDM]
    DEVICE_FILE = your_prd_file.prd
    DEVICE_NAME = your_prd_file.prd
    - create the file "APIKEY.json" (double check the right extension, do not create "APIKEY.json.txt"). Then in that file paste this content
    Code:
    [{"apikey":"secret"}]
    - start their flask server like their git tells you to do and it runs on
    * Running on http://127.0.0.1:1337
    Now in the other extension folder.
    - go to config folder and open "local.json" . Change
    Code:
    {
        "security_level": "",
        "host": "",
        "secret": "",
        "device_name": ""
    }
    to
    Code:
    {
        "security_level": "",
        "host": "http://127.0.0.1:1337",
        "secret": "secret",
        "device_name": "your_prd_file.prd"
    }
    - then install the extension on edge
    - open the addon menu, make sure "enabled" is checked. Go to remote cdm > choose config and pick the previously edited "local.json" file.

    While testing the addon on
    https://reference.dashif.org/dash.js/v4.4.0/samples/drm/playready.html

    I had to refresh 2 times to get both set of keys (video+audio) and it worked.

    Image
    [Attachment 86173 - Click to enlarge]


    Code:
    N_m3u8DL-RE "https://media.axprod.net/TestVectors/v7-MultiDRM-MultiKey-MultiPeriod/Manifest.mpd" --key 2d6e938760ca4145aec2c40837b4b026:42d0bff1b60f7be49f17d603484d0cb9 --key 8b029e51d56a44bd910fd4b5fd90fba2:c889cca25eb30b3b128eb834ea4da4fa -M format=mkv
    --[----->+<]>.++++++++++++.---.--------.
    [*drm mass downloader: widefrog*]~~~~~~~~~~~[*how to make your own mass downloader: guide*]
    Quote Quote  
  3. Originally Posted by 2nHxWW6GkN1l916N3ayz8HQoi View Post
    Seems that extension is still kinda buggy. Hope they fix it. Here's what worked for me without bothering too much. There are 2 directories
    - PlayReadyProxy-API-main => the local api
    - PlayReadyProxy-main => the extension

    Unpack them both. In the local api folder:
    - rename the env and config like their git tells you to do
    - copy in that folder (near the app.py) the prd file. Mine is called: "your_prd_file.prd"
    - then go to config.ini and change
    Code:
    [CDM]
    DEVICE_FILE = device/ # DEVICE FILENAME
    DEVICE_NAME = # DEVICE NAME
    to
    Code:
    [CDM]
    DEVICE_FILE = your_prd_file.prd
    DEVICE_NAME = your_prd_file.prd
    - create the file "APIKEY.json" (double check the right extension, do not create "APIKEY.json.txt"). Then in that file paste this content
    Code:
    [{"apikey":"secret"}]
    - start their flask server like their git tells you to do and it runs on
    * Running on http://127.0.0.1:1337
    Now in the other extension folder.
    - go to config folder and open "local.json" . Change
    Code:
    {
        "security_level": "",
        "host": "",
        "secret": "",
        "device_name": ""
    }
    to
    Code:
    {
        "security_level": "",
        "host": "http://127.0.0.1:1337",
        "secret": "secret",
        "device_name": "your_prd_file.prd"
    }
    - then install the extension on edge
    - open the addon menu, make sure "enabled" is checked. Go to remote cdm > choose config and pick the previously edited "local.json" file.

    While testing the addon on
    https://reference.dashif.org/dash.js/v4.4.0/samples/drm/playready.html

    I had to refresh 2 times to get both set of keys (video+audio) and it worked.

    Image
    [Attachment 86173 - Click to enlarge]


    Code:
    N_m3u8DL-RE "https://media.axprod.net/TestVectors/v7-MultiDRM-MultiKey-MultiPeriod/Manifest.mpd" --key 2d6e938760ca4145aec2c40837b4b026:42d0bff1b60f7be49f17d603484d0cb9 --key 8b029e51d56a44bd910fd4b5fd90fba2:c889cca25eb30b3b128eb834ea4da4fa -M format=mkv
    May I ask how to use this program?
    https://github.com/ready-dl/csplayready
    Quote Quote  
  4. Originally Posted by 2nHxWW6GkN1l916N3ayz8HQoi View Post
    Seems that extension is still kinda buggy. Hope they fix it. Here's what worked for me without bothering too much. There are 2 directories
    - PlayReadyProxy-API-main => the local api
    - PlayReadyProxy-main => the extension

    Unpack them both. In the local api folder:
    - rename the env and config like their git tells you to do
    - copy in that folder (near the app.py) the prd file. Mine is called: "your_prd_file.prd"
    - then go to config.ini and change
    .........
    Many thx for this tutorial
    Quote Quote  
  5. Feels Good Man 2nHxWW6GkN1l916N3ayz8HQoi's Avatar
    Join Date
    Jan 2024
    Location
    Pepe Island
    Search Comp PM
    Originally Posted by hizbf View Post
    May I ask how to use this program?
    https://github.com/ready-dl/csplayready
    It's a C# implementation. It's not an addon. It even explains you the steps in the readme git section. If you can handle pyplayready, you can handle the C# alternative. If you don't know about scripts, then you can stick only to the addons.

    Originally Posted by evangelle View Post
    Many thx for this tutorial
    No problem
    --[----->+<]>.++++++++++++.---.--------.
    [*drm mass downloader: widefrog*]~~~~~~~~~~~[*how to make your own mass downloader: guide*]
    Quote Quote  
  6. I had done all step
    but It seems not query the api.
    Image
    [Attachment 86198 - Click to enlarge]


    tried under windows and same thing. do anyone have a clue on what I made wrong please ?
    Quote Quote  
  7. Member
    Join Date
    Feb 2024
    Location
    Malaysia
    Search Comp PM
    Please dm me on telegram: https://telegram.me/SurpriseMTFK
    Quote Quote  
  8. Originally Posted by evangelle View Post
    I had done all step
    but It seems not query the api.
    Image
    [Attachment 86198 - Click to enlarge]


    tried under windows and same thing. do anyone have a clue on what I made wrong please ?
    Have you fond solution?
    Quote Quote  
  9. nxhda
    Join Date
    Sep 2022
    Location
    United States
    Search Comp PM
    Code:
    try use local.json
    Last edited by NBA456017; 18th May 2025 at 17:34.
    discord nxhda
    Quote Quote  
  10. Member
    Join Date
    Jun 2025
    Location
    France
    Search Comp PM
    Hello,

    Thanks for this tutorial!
    I've done everything correctly, I don't get any error messages, and yet it's not working. Any ideas?
    Image
    [Attachment 87639 - Click to enlarge]


    My PlayReady-API -> config.ini :
    Code:
    [CDM]
    DEVICE_FILE = device/lg_electronics_inc_lg_webos_tv_msd93xbg_sl3000.prd
    DEVICE_NAME = LG
    My PlayReady-API-> APIKEY.json :
    Code:
    [
        {
            "username": "test",
            "apikey": "test_99c036381a6736de600f61c07a"
        }
    ]
    My PlayReady -> config -> local.json :
    Code:
    {
        "security_level": "3000",
        "host": "http://127.0.0.1:1337",
        "secret": "test_99c036381a6736de600f61c07a",
        "device_name": "LG"
    }
    Did I miss something, please?

    Thanks in advance
    Quote Quote  
  11. larley the king of video decryption! thank you so much mate for your work. amazing

    just little tip: from PR github page on chrome section you write 'download zip'
    we have just xpi file, for FF. anyway it's easy to extract all content with wrar or 7zip

    loaded extension on chromium browser i get this error 'background.scripts' requires manifest version of 2 or lower
    Quote Quote  
  12. Originally Posted by whs912km View Post
    loaded extension on chromium browser i get this error 'background.scripts' requires manifest version of 2 or lower
    just ignore it
    Bypass HMACs, One-time-tokens and Lic.Wrapping: https://github.com/DevLARLEY/WidevineProxy2
    Quote Quote  
  13. yea, right. but why this error from this new extension?
    or this error is with chromium browser only and no error with FF browser?

    also tried to edit manifest version 3 to version 2 but my browser can't load extension, with manifest version 2
    just out curiosity...!
    Quote Quote  
  14. Originally Posted by whs912km View Post
    yea, right. but why this error from this new extension?
    or this error is with chromium browser only and no error with FF browser?

    also tried to edit manifest version 3 to version 2 but my browser can't load extension, with manifest version 2
    just out curiosity...!
    Among Chromium browsers, I think it is only going to work on Microsoft Edge. In Ungoogled Chromium there is no PlayReady CDM displayed in chrome://media-internals/
    I tried implementing some PlayReady-to-ClearKey hook with LLM assistance, but it doesn't work yet and I have no idea how to pass information to jsplayready from content script. Maybe larley can help.
    Code:
    (function () {
      const originalRequest = navigator.requestMediaKeySystemAccess;
    
      navigator.requestMediaKeySystemAccess = async function (keySystem, supportedConfigurations) {
            if (["com.microsoft.playready.recommendation", "com.microsoft.playready.recommendation.3000", "com.microsoft.playready.hardware", "com.microsoft.playready", "com.youtube.playready"].includes(keySystem)) {
          const realKeySystem = "org.w3.clearkey";
    
          // Sanitize configurations for compatibility with ClearKey
          const modifiedConfigs = supportedConfigurations.map(config => {
            const sanitized = { ...config };
    
            sanitized.videoCapabilities = (config.videoCapabilities || []).map(cap => {
              const { robustness, ...rest } = cap;
              return rest;
            });
    
            sanitized.audioCapabilities = (config.audioCapabilities || []).map(cap => {
              const { robustness, ...rest } = cap;
              return rest;
            });
    
            // Optional: sanitize other fields like distinctiveIdentifier, persistentState, etc.
            return sanitized;
          });
    
          const access = await originalRequest.call(navigator, realKeySystem, modifiedConfigs);
          const originalCreate = access.createMediaKeys.bind(access);
    
          const wrappedAccess = {
            keySystem,
            getConfiguration: () => access.getConfiguration(),
            createMediaKeys: async () => {
              const realMediaKeys = await originalCreate();
              return createWrappedMediaKeys(realMediaKeys);
            }
          };
    
          return wrappedAccess;
        }
    
        return originalRequest.call(navigator, keySystem, supportedConfigurations);
      };
    
    function createWrappedMediaKeys(realMediaKeys) {
      const originalCreateSession = realMediaKeys.createSession.bind(realMediaKeys);
      realMediaKeys.createSession = function (...args) {
        const realSession = originalCreateSession(...args);
    
        return new Proxy(realSession, {
          get(target, prop) {
            if (prop === "generateRequest") {
              return async (initDataType, initData) => {
                console.log("[CustomKeySystem] generateRequest", { initDataType, initData });
    	    console.log(Object.keys(initData));
                if (initDataType == "cenc") {
    	      const data = new Uint8Array(initData);
                  //let pssh = Pssh(initData);
    	      console.log(uint8ArrayToString(data));
                  //const a = uint8ArrayToString(initData);
                  //console.log(Object.keys(initData));
                  return target.generateRequest("keyids", initData);
    	    }
                return target.generateRequest(initDataType, initData);
              };
            }
            if (prop === "update") {
              return async (response) => {
                console.log("[CustomKeySystem] update", response);
                // {"keys":[{"kty":"oct","alg":"A128KW","kid":"nrQFDeRLSAKTLifXUIPiZg","k":"FmY0xnWCPCNaSpRG-tUuTQ"}]}
                return target.update(response);
              };
            }
            return typeof target[prop] === "function"
              ? target[prop].bind(target)
              : target[prop];
          }
        });
      };
    
      return realMediaKeys;
    }
    })();
    Quote Quote  
  15. background and content script communicate through a message proxy that converts one type of event to another and adds a unique id to each one to track which have arrived and which haven't. It's a true pain but also the only way possible.
    Code:
    async function processMessage(detail) {
        return new Promise((resolve, reject) => {
            chrome.runtime.sendMessage({type: detail.type, body: detail.body}, (response) => {
                if (chrome.runtime.lastError) {
                    return reject(chrome.runtime.lastError);
                }
                resolve(response);
            });
        })
    }
    
    document.addEventListener('response', async (event) => {
        const { detail } = event;
        const responseData = await processMessage(detail);
        const responseEvent = new CustomEvent('responseReceived', {
            detail: detail.requestId.concat(responseData)
        });
        document.dispatchEvent(responseEvent);
    });
    From PlayreadyProxy2
    Code:
    const playready_device = new Device(Utils.base64ToBytes(device_b64));
    const cdm = Cdm.fromDevice(playready_device);
    const licenseChallenge = cdm.getLicenseChallenge(wrmHeader, rawRevLists, version);
    const returned_keys = cdm.parseLicense(decodedLicense);
    const keys = returned_keys.map(key => ({ k: utils.bytesToHex(key.key), kid: utils.bytesToHex(key.key_id) }));
    Bypass HMACs, One-time-tokens and Lic.Wrapping: https://github.com/DevLARLEY/WidevineProxy2
    Quote Quote  



Similar Threads

Visit our sponsor! Try DVDFab and backup Blu-rays!