Skip to main content

Devine
Modular Movie, TV, and Music Archival Software
Discord

Build status Python version DeepSource
Linter: Ruff Dependency management: Poetry

Features

  • 🚀 Seamless Installation via pip
  • 🎥 Movie, Episode, and Song Service Frameworks
  • 🛠️ Built-in DASH and HLS Parsers
  • 🔒 Widevine DRM integration via pywidevine
  • 💾 Local & Remote DRM Key-vaults
  • 🌍 Local & Remote Widevine CDMs
  • 👥 Multi-profile Authentication per-service with Credentials and/or Cookies
  • 🤖 Automatic P2P filename structure with Group Tag
  • ⚙️ YAML for Configuration
  • ❤️ Fully Open-Source! Pull Requests Welcome

Installation

$ pip install devine

Voilà 🎉 — You now have the devine package installed! A command-line interface is now available, try devine --help.

Dependencies

The following is a list of programs that need to be installed by you manually.

  • CCExtractor for extracting Closed Caption data like EIA-608 from video streams and converting as SRT.
  • FFmpeg (and ffprobe) for repacking/remuxing streams on specific services, and evaluating stream data.
  • MKVToolNix v54+ for muxing individual streams to an .mkv file.
  • shaka-packager for decrypting CENC-CTR and CENC-CBCS video and audio streams.
  • (optional) aria2(c) to use as a downloader.

Usage

First, take a look at devine --help for a full help document, listing all commands available and giving you more information on what can be done with Devine.

Here's a checklist on what I recommend getting started with, in no particular order,

  • Add Services, these will be used in devine dl.
  • Add Profiles, these are your cookies and credentials.
  • Add Widevine Provisions, also known as CDMs, these are used for DRM-protected content.
  • Set your Group Tag, the text at the end of the final filename, e.g., devine cfg tag NOGRP for ...-NOGRP.
  • Set Up a Local Key Vault, take a look at the Key Vaults Config.

And here's some more advanced things you could take a look at,

  • Setting default Headers that the Request Session uses.
  • Setting default Profiles and CDM Provisions to use for services.
  • NordVPN and Hola Proxy Providers for automatic proxies.
  • Hosting and/or Using Remote Key Vaults.
  • Serving and/or Using Remote CDM Provisions.

Documentation on the config is available in the CONFIG.md file, it has a lot of handy settings. If you start to get sick of putting something in your CLI call, then I recommend taking a look at it!

Services

Unlike similar project's such as youtube-dl, Devine does not currently come with any Services. You must develop your own Services and only use Devine with Services you have the legal right to do so.

Creating a Service

A Service consists of a folder with an __init__.py file. The file must contain a class of the same name as the folder. The class must inherit the Service class and implement all the abstracted methods. It must finally implement a new method named cli where you define CLI arguments.

  1. Make a new folder within /devine/services. The folder name you choose will be what's known as the Service Tag. This "tag" is used in the final output filename of downloaded files, for various code-checks, lookup keys in key-vault databases, and more.
  2. Within the new folder create an __init__.py file and write a class inheriting the Service class. It must be named the exact same as the folder. It is case-sensitive.
  3. Implement all the methods of the Service class you are inheriting that are marked as abstract.
  4. Define CLI arguments by implementing a cli method. This method must be static (i.e. @staticmethod). For example to implement the bare minimum to receive a Title ID of sorts:
    @staticmethod
    @click.command(name="YT", short_help="https://youtube.com", help=__doc__)
    @click.argument("title", type=str)
    @click.pass_context
    def cli(ctx, **kwargs):
        return YT(ctx, **kwargs)
    
    You must implement this cli method, even if you do not want or need any CLI arguments. It is required for the core CLI functionality to be able to find and call the class.
  5. Accept the CLI arguments by overriding the constructor (the __init__() method):
    def __init__(self, ctx, title):
        self.title = title
        super().__init__(ctx)  # important
        # ... the title is now available across all methods by calling self.title
    

Service Tags

Service tags generally follow these rules:

  • Tag must be between 2-4 characters long, consisting of just [A-Z0-9i]{2,4}.
    • Lower-case i is only used for select services. Specifically BBC iPlayer and iTunes.
  • If the Service's commercial name has a + or Plus, the last character should be a P. E.g., ATVP for Apple TV+, DSCP for Discovery+, DSNP for Disney+, and PMTP for Paramount+.

These rules are not exhaustive and should only be used as a guide. You don't strictly have to follow these rules, but I recommend doing so for consistency.

Sharing Services

Sending and receiving zipped Service folders is quite cumbersome. Let's explore alternative routes to collaborating on Service Code.

Forking

If you are collaborating with a team on multiple services then forking the project is the best way to go.

  1. Create a new Private GitHub Repository without README, .gitignore, or LICENSE files. Note: Do NOT use the GitHub Fork button, or you will not be able to make the repository private.
  2. git clone <your repo url here> and then cd into it.
  3. git remote add upstream https://github.com/devine-dl/devine
  4. git remote set-url --push upstream DISABLE
  5. git fetch upstream
  6. git pull upstream master
  7. (optionally) Hard reset to the latest stable version by tag. E.g., git reset --hard v1.0.0.

Now commit your Services or other changes to your forked repository. Once committed all your other team members can easily pull changes as well as push new changes.

When a new update comes out you can easily rebase your fork to that commit to update.

  1. git fetch upstream
  2. git rebase upstream/master

However, please make sure you look at changes between each version before rebasing and resolve any breaking changes and deprecations when rebasing to a new version.

If you are new to git then take a look at GitHub Desktop.

Symlinking

This is a great option for those who wish to do something like the forking method, but may not care what changes happened or when and just want changes synced across a team.

This also opens up the ways you can host or collaborate on Service code. As long as you can receive a directory that updates with just the services within it, then you're good to go. Options could include an FTP server, Shared Google Drive, a non-fork repository with just services, and more.

  1. Use any Cloud Source that gives you a pseudo-directory to access the Service files like a normal drive. E.g., rclone, Google Drive Desktop (aka File Stream), Air Drive, CloudPool, etc.
  2. Create a services directory somewhere in it and have all your services within it.
  3. Symlink the services directory to the /devine folder. You should end up with /devine/services folder containing services, not /devine/services/services.

You have to make sure the original folder keeps receiving and downloading/streaming those changes. You must also make sure that the version of devine you have locally is supported by the Service code.

Cookies & Credentials

Devine can authenticate with Services using Cookies and/or Credentials. Credentials are stored in the config, and Cookies are stored in the data directory which can be found by running devine env info.

To add a Credential to a Service, take a look at the Credentials Config for information on setting up one or more credentials per-service. You can add one or more Credential per-service and use -p/--profile to choose which Credential to use.

To add a Cookie to a Service, use a Cookie file extension to make a cookies.txt file and move it into the Cookies directory. You must rename the cookies.txt file to that of the Service tag (case-sensitive), e.g., NF.txt. You can also place it in a Service Cookie folder, e.g., /Cookies/NF/default.txt or /Cookies/NF/.txt.

You can add multiple Cookies to the /Cookies/NF/ folder with their own unique name and then use -p/--profile to choose which one to use. E.g., /Cookies/NF/sam.txt and then use it with --profile sam. If you make a Service Cookie folder without a .txt or default.txt, but with another file, then no Cookies will be loaded unless you use -p/--profile like shown. This allows you to opt in to authentication at whim.

Cookies must be in the standard Netscape cookies file format. Recommended Cookie exporter extensions:

Any other extension that exports to the standard Netscape format should theoretically work.

Warning The Get cookies.txt extension by Rahul Shaw is essentially spyware. Do not use it. There are some safe versions floating around (usually just older versions of the extension), but since there are safe alternatives I'd just avoid it altogether. Source: https://reddit.com/r/youtubedl/comments/10ar7o7

Widevine Provisions

A Widevine Provision is needed for acquiring licenses containing decryption keys for DRM-protected content. They are not needed if you will be using devine on DRM-free services. Please do not ask for any Widevine Device Files, Keys, or Provisions as they cannot be provided.

Devine only supports .WVD files (Widevine Device Files). However, if you have the Provision RSA Private Key and Device Client Identification Blob as blob files (e.g., device_private_key and device_client_id_blob), then you can convert them to a .WVD file by running pywidevine create-device --help.

Once you have .WVD files, place them in the WVDs directory which can be found by calling devine env info. You can then set in your config which WVD (by filename only) to use by default with devine cfg cdm.default wvd_name. From here you can then set which WVD to use for each specific service. It's best to use the lowest security-level provision where possible.

An alternative would be using a pywidevine Serve-compliant CDM API. Of course, you would need to know someone who is serving one, and they would need to give you access. Take a look at the remote_cdm config option for setup information. For further information on it see the pywidevine repository.

End User License Agreement

Devine and it's community pages should be treated with the same kindness as other projects. Please refrain from spam or asking for questions that infringe upon a Service's End User License Agreement.

  1. Do not use Devine for any purposes of which you do not have the rights to do so.
  2. Do not share or request infringing content; this includes Widevine Provision Keys, Content Encryption Keys, or Service API Calls or Code.
  3. The Core codebase is meant to stay Free and Open-Source while the Service code should be kept private.
  4. Do not sell any part of this project, neither alone nor as part of a bundle. If you paid for this software or received it as part of a bundle following payment, you should demand your money back immediately.
  5. Be kind to one another and do not single anyone out.

Contributors

rlaphoenix mnmll shirt-dev nyuszika7h bccornfo Arias800 varyg1001 Hollander-1908 Shivelight knowhere01 retouching pandamoon21 adbbbb

Licensing

This software is licensed under the terms of GNU General Public License, Version 3.0. You can find a copy of the license in the LICENSE file in the root folder.


© Shivelight 2025
© rlaphoenix 2019-2024

Metadata

Release files for vindemitor 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for vindemitor 0.1.0
File Size Uploaded Provenance Actions
vindemitor-0.1.0.tar.gz 23.6 kB Without provenance Details for vindemitor-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for vindemitor 0.1.0
File Interpreter ABI Platform Actions
vindemitor-0.1.0-py3-none-any.whl Python 3 none any Details for vindemitor-0.1.0-py3-none-any.whl

Total release size: 45.7 kB

Release files / vindemitor-0.1.0.tar.gz

Download URL vindemitor-0.1.0.tar.gz
Size 23.6 kB
Tags Source
SHA-256 checksum
How to use checksums
0ad081ce3ab976fa0da72fbbcf885f662f897b97db5328ccff5ccd59c902c4e9
BLAKE2b-256 checksum
How to use checksums
329b5a2ae84e1a85dce8a162a5252b12009302fb5e27666f7f3935deb68d5cde
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.3

Release files / vindemitor-0.1.0-py3-none-any.whl

Download URL vindemitor-0.1.0-py3-none-any.whl
Size 22.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7d504af1fd3b848347200739b3a9f129035c0b6afd850935954fa538645a9d33
BLAKE2b-256 checksum
How to use checksums
960d5778327dc955aff347bdd9f1706f856cdc7d95fc495d8e1f980e6124694c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.3

Security for vindemitor 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page