Skip to content

Instantly share code, notes, and snippets.

@ruario
Last active January 29, 2024 07:53
Star You must be signed in to star a gist
Save ruario/3c873d43eb20553d5014bd4d29fe37f1 to your computer and use it in GitHub Desktop.
Fetches the latest Linux Widevine binary so that it can be used by Vivaldi.

With the release of Vivaldi 2.2, this page is now obsolete and unmaintained. Widevine is fetched automatically on post install of our official packages. The information below and the script are left for historical reasons but will not be updated.

If you are using something newer than Vivaldi 2.2, you should not be using this script as there is simply no need. Any need you think you have for it would be a bug IMHO and thus should be logged in a bug report. Before you do so however, you should also checkout the Vivaldi help page on Widevine, on Linux


Summary

A bunch of people asked how they could use this script with pure Chromium on Ubuntu. The following is a quick guide. Though I still suggest you at least try Vivaldi. Who knows, you might like it. Worried about proprietary componants? Remember that libwidevinecdm.so is a binary blob you are taking from Chrome, so by following this guide you will have already made your distro less "pure". Also all our additions to the Chromium base are open source and our UI, while not open, is written in HTML/CSS/JS. Thus you can see exactly what we are doing (no funny business).

If you still want to run Chromium, the following explains how it is done.

Note: For ARM(hf) use this instead. Beware it requires a +2Gb download of a ChromeOS recovery image. You can actually run it on a “regular” (x86 or x86_64 Linux) PC as it will create an archive file that can be copied to the target machine.

Chromium setup

  • Install the package "chromium-codecs-ffmpeg-extra" to provide H.264/MP4 support (used by videos on Netflix)—replaced with a snap in Ubuntu 19.10 onwards. After install, you need to restart Chromium. You can confirm that it is installed and working correctly by going to https://help.vivaldi.com/article/html5-proprietary-media-on-linux/ and checking that the video plays.

  • Next run the script (latest-widevine.sh). This will create the file "WidevineCdm" in "/opt/google/chrome".

  • Not needed on most distro : Replace the "WidevineCdm" provided by Chromium with a symlink to the file from Chrome:

sudo rm -fr /usr/lib/chromium-browser/WidevineCdm
sudo ln -fs /opt/google/chrome/WidevineCdm /usr/lib/chromium-browser/WidevineCdm 

Note: The path is typically "/usr/lib64/chromium/WidevineCdm" on non Debian/Ubuntu based distros.

Damn you Netflix!

The final complication is that Netflix does not expect pure Chromium to be able to be able play videos and hence they do a stupid thing. If they detect that Chromium is accesing a video, they point you to install Silverlight! This is particularly dumb because: you are running Linux (no Silverlight); Silverlight is an NPAPI plugin and Chrom(e|ium) only supports PPAPI. You will need to work around this.

  • Delete any cookies or data associated with Netflix. If you have failed to play videos once, then Netflix stores information about this in a cookie and you won't be able to play vidoes, even once your system is now correctly configured. Another "WTF‽" moment from the Netflix team.

  • Via a user agent editing extention or by starting Chromium with the -user-agent switch, remove the reference to "Ubuntu Chromium/XX.0.XXXX.XX", e.g.

/usr/lib/chromium-browser/chromium-browser --user-agent='Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.99 Safari/537.36'

Note: An extenstion is best otherwise you will need to start Chromium from the command line every time or edit the .desktop file to include this switch.

One final point. Every time Chromium upgrades it will replace the WidevineCdm symlink with its own file. Thus you will need to remove it and re-create the symlink. I would also suggest re-running latest-widevine.sh at that point, to check for new versions and upgrade if needed.

#!/bin/sh
# For ARM use this instead
# https://gist.github.com/ruario/19a28d98d29d34ec9b184c42e5f8bf29
available () {
command -v "$1" >/dev/null 2>&1
}
# Make sure we have wget or curl
if available wget; then
DL="wget"
DL_SILENT="wget -qO-"
elif available curl; then
DL="curl -LO"
DL_SILENT="curl -s"
else
echo "Install wget or curl" >&2
exit 1
fi
# Use the architecture of the current machine or whatever the user has set
# externally
ARCH="${ARCH:-$(uname -m)}"
case "$ARCH" in
x86_64) WIDEVINE_ARCH="x64"; CHROMIUM_ARCH="x64" ;;
i?86) WIDEVINE_ARCH="ia32"; CHROMIUM_ARCH="x86" ;;
arm*) echo "For ARM use https://gist.github.com/ruario/19a28d98d29d34ec9b184c42e5f8bf29 instead" >&2 ; exit 1 ;;
*) echo "The architecture $ARCH is not supported." >&2 ; exit 1 ;;
esac
# Set Output dir
WIDEVINE_INSTALL_DIR="${WIDEVINE_INSTALL_DIR:-/opt/google/chrome/WidevineCdm}"
# Set temp dir
TMP="${TMP:-/tmp}"
# Set staging dir
STAGINGDIR="$TMP/widevine-staging"
# Work out the latest Widevine version
WIDEVINE_VERSION="${WIDEVINE_VERSION:-$($DL_SILENT https://dl.google.com/widevine-cdm/versions.txt | tail -n1)}"
# Error out if $CDMVERISON is unset, e.g. because previous command failed
if [ -z "$WIDEVINE_VERSION" ]; then
echo "Could not work out the latest version; exiting" >&2
exit 1
fi
# Don't start repackaging if the same version is already installed
if [ -e "$WIDEVINE_INSTALL_DIR/manifest.json" ] && [ "$WIDEVINE_VERSION" = "$(sed -rn '/"version":/s/.*(([0-9]+\.){3}[0-9]+).*/\1/p' "$WIDEVINE_INSTALL_DIR/manifest.json")" ]; then
echo "The latest Widevine ($WIDEVINE_VERSION) is already installed"
exit 0
fi
# If the staging directory is already present from the past, clear it down and
# re-create it.
if [ -d "$STAGINGDIR" ]; then
rm -fr "$STAGINGDIR"
fi
# Stop on any error
set -eu
# Make and switch to the staging directory
mkdir -p "$STAGINGDIR"
cd "$STAGINGDIR"
# Now get the latest widevine zip for the users architecture
$DL "https://dl.google.com/widevine-cdm/${WIDEVINE_VERSION}-linux-${WIDEVINE_ARCH}.zip"
# Extract the contents of Widevine package
python -m zipfile -e "${WIDEVINE_VERSION}-linux-${WIDEVINE_ARCH}.zip" .
# Escalate privileges if needed and copy files into place
if [ "$USER" = "root" ] || [ "$WIDEVINE_INSTALL_DIR" != "/opt/google/chrome/WidevineCdm" ]; then
install -Dm644 libwidevinecdm.so "$WIDEVINE_INSTALL_DIR/_platform_specific/linux_$CHROMIUM_ARCH/libwidevinecdm.so"
install -m644 manifest.json "$WIDEVINE_INSTALL_DIR/manifest.json"
install -m644 LICENSE.txt "$WIDEVINE_INSTALL_DIR/LICENSE.txt"
elif [ -r /etc/os-release ] && grep -qx 'ID=ubuntu' /etc/os-release; then
echo "Calling sudo ... If prompted, please enter your password so Widevine can be copied into place"
sudo install -Dm644 libwidevinecdm.so "$WIDEVINE_INSTALL_DIR/_platform_specific/linux_$CHROMIUM_ARCH/libwidevinecdm.so"
sudo install -m644 manifest.json "$WIDEVINE_INSTALL_DIR/manifest.json"
sudo install -m644 LICENSE.txt "$WIDEVINE_INSTALL_DIR/LICENSE.txt"
else
echo "Please enter your root password so Widevine can be copied into place"
su -c "sh -c \"install -Dm644 libwidevinecdm.so $WIDEVINE_INSTALL_DIR/_platform_specific/linux_$CHROMIUM_ARCH/libwidevinecdm.so && install -m644 manifest.json $WIDEVINE_INSTALL_DIR/manifest.json && install -m644 LICENSE.txt $WIDEVINE_INSTALL_DIR/LICENSE.txt\""
fi
# Tell the user we are done
echo "Widevine ($WIDEVINE_VERSION) installed into $WIDEVINE_INSTALL_DIR"
@freechelmi
Copy link

Works great with chromium 76. Sad to have to hack the widevine version in the script. Google is evil

@ruario
Copy link
Author

ruario commented Aug 27, 2019

I added an overly complex script to work out the Widevine version number by ripping the lib out of the Chrome and trying to read the version number within it. It is ridiculous in that it wastes bandwidth downloading Chrome, just to discover a version number. But hey… at least it seems to work, unlike the method Google suggests.

Now before anyone asks, yes I could update the script to use Chrome directly as a source for Widevine but I will not be doing that as that requires more fundamental changes to a script that I am not actively putting much effort into maintaining. It could also break again in the future meaning more work for me. Oh and it is unneeded for Vivaldi, which is what I primarily care about. Last but not least, 32-Bit Linux would not be handled if I did that.

Anyway for anyone who reads this. If you think an old version or Widevine is being fetched, run the checking script to get the version number and update the main script accordingly.

I would also appreciate a comment here mentioning that it I need to change the version number and I'll likely do that, since it is very little effort.

@saymoncoppi
Copy link

saymoncoppi commented Sep 10, 2019

Hello ruario!
I made this to always get the latest version.
Maybe it could be beautified and shared in your script. lol

# Work out the real latest Widevine version
## Google's versions file (https://dl.google.com/widevine-cdm/versions.txt)
WIDEVINE_VERSION="${WIDEVINE_VERSION:-$(wget -P /tmp https://dl.google.com/widevine-cdm/versions.txt -q ; tail -n 1 /tmp/versions.txt ; rm -rf /tmp/versions.txt)}"

Tks for sharing.

@ruario
Copy link
Author

ruario commented Sep 10, 2019

@saymoncoppi Interesting. I was not familiar with the  “versions.txt” file but it seems you are over complicating it making temp files. You could just do this:

WIDEVINE_VERSION="${WIDEVINE_VERSION:-$(wget -qO- https://dl.google.com/widevine-cdm/versions.txt | tail -n1)}"

@ruario
Copy link
Author

ruario commented Sep 10, 2019

Interesting that it lists 4.10.1440.19, when Chrome stable uses 4.10.1440.18 and Chrome beta uses 4.10.1503.4. I need to investigate further but thanks for the tip @saymoncoppi

@saymoncoppi
Copy link

Interesting that it lists 4.10.1440.19, when Chrome stable uses 4.10.1440.18 and Chrome beta uses 4.10.1503.4. I need to investigate further but thanks for the tip @saymoncoppi

I found that versions.txt at https://bugs.mageia.org/show_bug.cgi?id=17449#c18

And Tks for simplify the code :P

@dagwieers
Copy link

@ruario The 4.10.1440.19 zip file actually includes 4.10.1440.18.

@asimarora
Copy link

Works perfectly on ubuntu 16.04 . Well done. Thanks

@ruario
Copy link
Author

ruario commented Oct 11, 2019

@dagwieers so it does. Identical md5sum. weird
@saymoncoppi incorporated into the main script

@ruario
Copy link
Author

ruario commented Oct 11, 2019

I added another extraction option using python so that this should work on pretty much any linux distro now

@ruario
Copy link
Author

ruario commented Oct 11, 2019

@diniremix I am glad it works... even if you do use Opera :P

@ruario
Copy link
Author

ruario commented Oct 11, 2019

I see that (as I write this) Chrome stable (77) has Widevine 4.10.1503.4, while beta (78) and dev/unstable (79) have Widevine 4.10.1582.1 and yet neither of these versions are available from dl.google.com/widevine-cdm the newest being 4.10.1440.18/19. Typical Google

@diniremix
Copy link

@ruario Thank you very much 😄 😎

@paulkastel
Copy link

paulkastel commented Nov 7, 2019

This script helped me solve problem with DRM & widevine on Opera 64 on Deepin Linux. I could not play music using Spotify Web Player and right now everything is fine, so huuuuge thanks! <3
I posted some step how I fixed it here https://forums.opera.com/topic/28663/widevine-and-opera/45

@ruario
Copy link
Author

ruario commented Nov 9, 2019

updated for the standard locations expected by Chromium 78. Careful though because distros might be patching these paths, so it may work better now... it may not

@kuboosoft
Copy link

In Chromium 79; changed... I can't put the path...

@freechelmi
Copy link

Chromium 79 ( as chrome ) needs 4.10.1610.0 but widevine website returns latest is 4.10.1582.2

So we cannot rely on

https://dl.google.com/widevine-cdm/versions.txt

to know the latest and extract it.

We have to grep the version from widevine-check-version.sh

@ruario
Copy link
Author

ruario commented Jan 27, 2020

79 does not need 4.10.1610.0. It runs absolutely fine with 4.10.1582.2. Google often give themselves a newer version than what they publish for third parties to use but as of right now 4.10.1582.2 works on every site I have tested

@dagwieers
Copy link

Correct, the same is true for ARM-based images for Chromebooks. In most (if not all) cases it is important to have a recent version that is still supported. See https://www.widevine.com/news

@ruario
Copy link
Author

ruario commented Jan 27, 2020

Yeah for Vivaldi ARM users we still have to extract from ChromeOS as there is no normal public source outside of this

https://gist.github.com/ruario/19a28d98d29d34ec9b184c42e5f8bf29

@freechelmi
Copy link

79 does not need 4.10.1610.0. It runs absolutely fine with 4.10.1582.2. Google often give themselves a newer version than what they publish for third parties to use but as of right now 4.10.1582.2 works on every site I have tested

Sorry my mistake then.

Also , mozilla supply an alternative to get binaries :

https://hg.mozilla.org/releases/mozilla-beta/log/default/toolkit/content/gmp-sources/widevinecdm.json

@ruario
Copy link
Author

ruario commented Feb 14, 2020

@freechelmi Vivaldi also fetches those automatically on all the same platforms as Firefox. If you use Vivaldi on desktop you get them fetched and installed by default. That is the reason this script is not really maintained much by me anymore. Vivaldi does not need it.

@ruario
Copy link
Author

ruario commented Feb 14, 2020

@freechelmi Also Firefox almost certainly updates their json based on reading https://dl.google.com/widevine-cdm/versions.txt. So it is not really any kind of alternative.

@freechelmi
Copy link

Thanks

I try to maintain this script for chromium users

@freechelmi
Copy link

OK I understand why the script does not work.
the widevine plugin does not get loaded of the licence file and manifest are not present.
Il will update the script on my fork to add those files.

@ruario
Copy link
Author

ruario commented Mar 12, 2020

@freechelmi: Thanks, I updated it

@freechelmi
Copy link

freechelmi commented Mar 13, 2020

Thanks @ruario ! That really simplify the code .

I see that you remove the netflix warning but here netflix still redirect to https://help.netflix.com/fr/node/23742 with chromium user agent .

I saw that vivaldi was smarter by including the chrome UA

@ruario
Copy link
Author

ruario commented Mar 13, 2020

@freechelmi: Ah, ok! I have now undone that change to the intro.

Yes, I took the opportunity to simplify it a little as a lot of the old code related to extraction was from before I realised I could just use python. Really no need for so many fallbacks given you would be hard pushed to find a Linux distro suitable for Vivaldi that does not also include python.

@ruario
Copy link
Author

ruario commented Mar 14, 2020

@freechelmi: I'm guessing (but have not tested because I don't have a machine to verify to hand), that it should now be possible to install and configure this for Chromium, without the need for admin privileges.

Run the script like so to install into your user directory:

WIDEVINE_INSTALL_DIR="$HOME/.local/lib/WidevineCdm" ./latest-widevine.sh

Create the Widevine configuration directory (if not already present):

mkdir -p "${XDG_CONFIG_HOME:-$HOME/.config}/chromium/WidevineCdm"

Create or update the json config file to point at your new, single user install of Widevine

echo "{\"Path\":\"$HOME/.local/lib/WidevineCdm\"}" > "${XDG_CONFIG_HOME:-$HOME/.config}/chromium/WidevineCdm/latest-component-updated-widevine-cdm"

Load demo.castlabs.com and attempt to play the videos that are tagged with “DRM”.

@Yocairo
Copy link

Yocairo commented Mar 19, 2020

@ruario works fantastically. I was searching for an hour to find a proper solution, and nothing worked except this exhaustive guide.
The only thing I did different (because I didn't scroll down far enough to find the latest-widevine.sh script) is I used this instead (which probably results in the same thing):

wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
dpkg -x google-chrome-stable_current_amd64.deb .
sudo cp -r ./opt/google/chrome/WidevineCdm /usr/lib/chromium-browser/

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment