Widevine support in Librem 5

Anyone have any luck setting up and running Widevine DRM on any browser on the Librem 5?


That’s somewhere on my todo list, but I did not have the need to look into this yet (and don’t foresee to get to it soon), but here’s the road I would go down:

My approach would be to look at the (works for me on my ARM notebook) AUR package widewine-aarch64 AUR (en) - widevine-aarch64 and

  • look at the deb and then try to install it on the Librem 5
  • troubleshoot by looking at the other files to see what needs to be put where to make this work.

I’ll give it a shot sometime this evenening maybe.

1 Like

I got a little curious and looked at the AUR entry. From the looks of it is made up of a .deb that is for ARM processors based on a Raspberry Pi. The other step is to run a script to set your user agent to spoof as a chromium browser.

Assuming any dependencies are in the repos, would that .deb work on the L5?

@Sarcasmo220 I think the difficult thing is that one of the dependencies is a specially modified version of glibc, which must be installed as a drop-in replacement for the original glibc (or, in the case of Debian/PureOS, libc6).

I’m completely new to Debian packaging.
So these are the humble first steps I managed to do so far:

  1. Install helper packages for Debian package management: devscripts, git-buildpackage, and piuparts.

  2. Add deb-src entries to /etc/apt/sources.list.

  3. cd to a suitable working directory where all the packaging work can take place.

  4. Run apt source glibc to download the source package.
    This creates the following things:

    • glibc_2.31-13+deb11u6.dsc;
    • glibc_2.31.orig.tar.xz (the upstream source tarball);
    • glibc_2.31-13+deb11u6.debian.tar.xz (a tarball of the glibc-2.31 branch of the Debian packaging source); and
    • a glibc-2.31 subdirectory (the source package, ready to build).
  5. At this point, I could have made the necessary modifications for libc-widevine.
    I skipped this step though, because I wanted to build from the unmodified source package first and check if it works.

  6. cd to the glibc-2.31 subdirectory, then run:

    debuild -i -us -uc -b

    This creates a bunch of binary packages in the parent directory. One of those packages is libc6_2.31-13+deb11u6_arm64.deb, which is where the modifications should have been.

  7. Install the resulting package. CAUTION: This is risky! Botching your custom libc6 build means your dpkg might no longer work, so you might have no way to recover.

I’m currently stuck at step 7.

What I did is install the resulting libc6 binary package using dpkg – however, that came from the unmodified source package (because I skipped step #5). So it didn’t surprise me that this works just fine.
(I ran sudo apt reinstall libc6 afterwards to revert to the original binary package from PureOS.)

The thing now is that I’m super reluctant to start doing any modifications in step #5. Because even the slightest mistake might mean a botched system.

Any ideas how to tackle this? Clean chroot, containers, LD_PRELOAD, something else?


I wish I knew the answer. I’ve used Linux mostly as a consumer. I am not a programmer but I can use basic command line stuff and (mostly) understand the directions I follow. And when I don’t understand, I don’t do it.

All that to say, I hope someone more knowledgeable comes along that can provide further assistance!


I’ve made some progress!

Instead of using the main system, I prepared a chroot like so:

sudo mkdir -p /var/lib/debbuild/aarch64/root
sudo debootstrap --arch arm64 byzantium /var/lib/debbuild/aarch64/root
sudo mount --bind /path/to/my/workdir \

This lets me do the risky install in a chroot jail:

$ debuild -i -us -uc -b
$ sudo chroot /var/lib/debbuild/aarch64/root
# dpkg -i /var/lib/packages/libc6_2.31-13+deb11u6_arm64.deb
# /lib/ld-linux-aarch64.so.1  # test if my modification works

To test this, I made a minor modification to the help text of ld.so (in the elf/rtld.c source file), and it works:

$ /lib/ld-linux-aarch64.so.1
[…] # Original help text
$ sudo chroot /var/lib/debbuild/aarch64/root /lib/ld-linux-aarch64.so.1
[…] # Modified help text

That means I have everything I need to safely tinker with the libc6 package, and I no longer have to worry about irreparably breaking my system when I make a mistake.

Next steps: look at the patches in the AUR package glibc-widevine, then port those patches to Debian’s glibc source package, step by step, in the hopes that I end up with a working glibc-widevine for Debian.

That’s probably going to take me a couple of months. I’m still learning how to do Debian packaging properly, and just building that libc6 package once takes several hours on my L5. That means the feedback loop is abysmal, and I’ll only be able to do at most one or two tiny iterations per day even if I can find the time to do it.

(I’ve tried to set up an environment in a virtual machine on my laptop so I can iterate faster, but I couldn’t get QEMU to boot the image. So I gave up on that for now, and went back to building on the L5 directly.)

Any help is appreciated so I can iterate faster.


I looked at all the patches to figure out which of them we actually need for Widewine on Byzantium.

Here are my findings:

Patch Description Status Comments
Upstream issue 27744 nptl_db: Support different libpthread/ld.so load orders Not needed Arch Linux’s unmodified glibc v2.33 package has the patch, too, so we’re probably not going to need this patch for Widevine.
Upstream commit f553dc06 nptl: Check for compatible GDB in nptl/tst-pthread-gdb-attach Not needed Same as with patch 27744.
Upstream commit 6f3e54d4 nptl: Do not build nptl/tst-pthread-gdb-attach as PIE Not needed Same as with patch 27744.
SHT_RELR/DT_RELR patch glibc: add support for SHT_RELR sections In progress See xbmc/inputstream.adaptive#678 (comment). Note that this patch has been upstreamed in an enhanced form, and is part of the glibc v2.38 stable release.

Update: I have backported that upstreamed patch to v2.31 and am currently testing it for regressions.
TLS alignment patch TLS: change max_align to 64U to fix dlopen segfault Pending See xbmc/inputstream.adaptive#678 (comment).
arm/unsubmitted-ldconfig-cache-abi.diff rollback Unrelated patch, which allegedly interferes with the DT_RELR patch Pending See raspberrypi/Raspberry-Pi-OS-64bit#11 (comment).
arm/unsubmitted-ldso-abi-check.diff rollback Unrelated patch, which allegedly interferes with the DT_RELR patch Not needed Patch already removed from Debian package in v2.29-3.
Make 4.4 MAKEFLAGS patch makerules: fix MAKEFLAGS assignment for upcoming make-4.4 [BZ# 29564] Not needed PureOS Byzantium still comes with Make 4.3.

Building and testing the libc6 package with the first patch is now complete.
Going to tackle the second patch now!

Unfortunately, Discourse doesn’t allow editing the above table any longer. So here’s my current status:

Update 2023-11-13

  • SHT_RELR/DT_RELR patch: done
  • TLS alignment patch: done
  • Preliminary tests on Firefox: done
  • Fix issues on Firefox: done
  • arm/unsubmitted-ldconfig-cache-abi.diff rollback: done (rollback not needed)
  • Final tests on Firefox: done
  • Fix outstanding issues: done
  • Create (non-free) Debian package libwidevinecdm: pending
  • Confirm that apt still picks up incoming Byzantium security updates to glibc, auto-removing libwidevinecdm if necessary: pending
  • Publish Debian packages for patched glibc: pending
  • Publish (non-free) Debian package libwidevinecdm: pending

Status of preliminary tests in Firefox (as of 2023-11-13)

Bitmovin DRM Stream Test

Passing :white_check_mark:
According to the test page, my browser supports Encrypted Media Extension (EME) with Widevine.

castLabs PRESTOplay Demo

Passing :white_check_mark:
Plays back the protected MPEG-DASH demo video (multi-key DRM) on castLabs flawlessly.

Spotify Web player

Passing :white_check_mark:


  • I needed to set my User-Agent to a known mobile browser, such as Safari on an iPhone. Failure to do so caused the web player to load its desktop view, causing infinite redirects.

  • The mobile view of the web player has a notably minimal feature set.
    Expect bullying nag screens blocking you from accessing your library (because you’re supposed to use the mobile app.)
    To access e.g. my playlists, my workaround is to scroll down the start page until it shows me a couple of my playlists, then flick horizontally until I find the one I want.


Passing :white_check_mark:

Note: To get past the bouncer, your User-Agent needs to resemble a recent desktop browser (not mobile). As of 2023-11, Byzantium’s firefox-esr version is passing that sniff test without needing any modifications.
Thanks to @user0 for the suggestion!

NOW (aka WOW in German-speaking countries)

Failing :x:
The stream appears to be loading but then it bails with the error code:


This is the exact same error message that I’m getting without the plugin.

The Network view in Developer Tools shows a POST request to an https://p.sky.com/drm/widevine/acquirelicense endpoint which fails with status 400. The request payload appears to be some binary blob (possibly a Protocol Buffers payload?) coming from the Widevine CDM. The blob contains fragments like:

  • arm64 next to architecture_name
  • Google next to company_name
  • ChromeCDM next to model_name
  • ChromeOS next to platform_name
  • and 4.10.2557.02 next to widevine_cdm_version.

The response payload alongside the 400 status reads:

{"errorCode":"OVP_00014","description":"Unsupported browser/client"}

Next step: Take another device that works well, inspect the request payload for the acquireLicense endpoint there, and compare it to the bad request payload. Try to figure out values that the endpoint likes to hear.


I definitely recommend updating to Firefox-ESR 115, but I just wanted to point out that this warning on most websites is usually caused by your user-agent. You could probably change your user-agent using the build-in about:config page or by using an extension and continue using all sites normally.

This is the current user-agent for Firefox-ESR 115 and the Tor Browser (both using the privacy.resistFingerprinting setting):

Mozilla/5.0 (Windows NT 10.0; rv:109.0) Gecko/20100101 Firefox/115.0

But again, I recommend updating to Firefox-ESR 115.

And as for my Mobile-Friendly Firefox Customizations for Librem 5, I recommend reading the very first post in that thread if you aren’t at all familiar with enabling CSS code for Firefox. Don’t save any files from that post, just read it.

After that, you should start with October 2023 Halloween Update (post 55). The final post in the October 2023 Halloween Update multi-post is Styles & Screenshots (post 61).


@user0 Thanks! Turns out that playing with User-Agent helped with two of the three failing services.

This helped get past the bouncers but the streams still don’t load, this time due to CORS violations. I seriously have no idea why these are occurring.

Updated my comment with the current status and details.

I recommend reading the very first post in that thread if you aren’t at all familiar with enabling CSS code for Firefox. Don’t save any files from that post, just read it.

Thanks for the pointers, that’s really helpful.

The toolkit.legacyUserProfileCustomizations.stylesheets pref is not an issue, because the Librem 5 came with the firefox-esr-mobile-config package pre-installed, which already sets the pref (see /usr/lib/firefox-esr/defaults/pref/mobile-config-prefs.js for details).

Next step for me is to download all the files from post 55 through 61.


You only need to save the files that you need.

I recommend checking out the screenshots in Styles & Screenshots (post 61) before saving antying, to see which style you’d like and to understand which files you will actually need.

If you like the fenix style, you can simply save fenix_one.css as userChrome.css and then save one of the userContent.css files, and that’s it. Two files for everything. If you want bigger popups, you can simply copy/paste one of the dynamic_popups files to the bottom of the userChrome.css file.

Feel free to ask questions if you need any help.

1 Like

Upgrading firefox-esr to v115 fixed DAZN!

Edit: And Spotify’s web player!

Edit 2: Watching DAZN is unbearable on the Librem 5. Way too laggy to be even remotely enjoyable. Youtube or other VOD services are working just fine, so how come DAZN is so unbearably laggy? It used to work on my old iPhone with 30+ fps. So why can’t it have at least a consistent 5 fps on the Librem 5?

Honestly, I’m perfectly willing to pick up Linux kernel development and learn how a GPU driver works, but where do I even start? I’m at a skill level where I can’t even figure out what codecs DAZN and NOW are using in their shitty obfuscated client code.

Pinging @amosbatto for ideas on where to start.

1 Like

I am using Brave on my Librem 5 exclusively. While Firefox ESR has a better control UI for touch, it is poor at displaying web pages quickly or correctly. Brave, on the other hand, has been working VERY well, especially if you do things to minimize the width of the UI and use tab groups.

Graphics acceleration happens there as well. So I would be VERY interested in getting widevine working on the L5, and I am wondering if you efforts would translate over to another browser as well?

They might, but you’d have to place the library file into the right location in the filesystem, and then enable Widevine via your browser’s settings.

I’m currently trying to fix my own myriad of overwhelming technical issues with my L5, so I’m sorry to say I’m unable to help with Brave directly.
What I can do though is try to wrap up testing, then finish that Debian source package for the Widevine-enabled variant of glibc. After that, you (and everyone else) should be able to build, install, and test it.


Once that build is done, hopefully it works so we can at least see installation without needing all that extra work with libc6…

Update as of 2023-12-23:

  • Giving up on NowTV/WowTV for now. Their server is actively blocking Linux clients. Client-side OS detection is awfully difficult to spoof because 1. detection happens in the native Widevine library, and 2. on top of that, the web player code in the browser uses heavily obfuscated JavaScript and WASM to cryptographically sign outgoing requests.

  • Amazon Prime Video: tested and confirmed to work.

  • libwidevinecdm Debian packages: I’m still stuck here. Debian packaging documentation feels overwhelming, even though I’ve been a Homebrew and AUR package maintainer since 2014. I think I have read the entire handbook for Debian maintainers by now, but I still don’t have the slightest idea where to even start building a Debian source package like this. Guidance would be much appreciated.

  • glibc-widevine Debian packages: Both the source package and the binary packages (for Byzantium) are finished and ready to be uploaded. I have also purchased a few GB of cloud space at Linode. Next step is learning how to set up a Debian package repository.


Here is the resource I fetched:

Chapter 15. Creating a Debian Package


Nice work on widevine

aptly (https://www.aptly.info/) which is also packaged in Debian makes this relatively simple if you want to host your own repo service.


Here is a blog post of someone’s similar journey to get widevine on Asahi Linux for aarch64 Apple laptops. I haven’t tried it yet as it is a little technical, but if @Lliure or anyone else would like to look at it that would be nice.


1 Like