October 23Oct 23 Short version: Google's arm64 Linux Chrome package ships Widevine, the DRM module streaming services use. Chromium and Firefox on arm64 don't ship it (Chromium is built with Widevine support but without the module; Mozilla ships no Widevine for aarch64 Linux at all), but both can use Chrome's copy if you tell them where it is. Nothing gets copied, so Google's licence on the module isn't an issue: it stays Google's install, and the pointer is your own configuration. Tested on an Orange Pi 5B (Armbian's rk-6.1 vendor kernel, Ubuntu 26.04 userspace) with Chrome 156, Chromium 156 (the xtradeb build) and Firefox 158 (Mozilla Team PPA). None of this is board-specific; it should work on any arm64 desktop where the arm64 Chrome .deb installs. 1. Install Google Chrome https://dl.google.com/linux/direct/google-chrome-stable_current_arm64.deb and sudo apt install ./google-chrome-stable_current_arm64.deb The module lands in /opt/google/chrome/WidevineCdm (libwidevinecdm.so under _platform_specific/linux_arm64, plus manifest.json). Chrome plays protected streams straight away. 2. Chromium Chromium looks for a one-line "hint" file in its profile, the same file Chrome writes in its own profile. Create it with the version from Chrome's manifest: mkdir -p ~/.config/chromium/WidevineCdm V=$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([0-9.]*\)".*/\1/p' /opt/google/chrome/WidevineCdm/manifest.json) printf '{"LastBundledVersion":"%s","Path":"/opt/google/chrome/WidevineCdm"}' "$V" > ~/.config/chromium/WidevineCdm/latest-component-updated-widevine-cdm Restart Chromium. Two things that do NOT work, so you don't waste time on them: a copy of the module in ~/.local/lib/libwidevinecdm.so, and a copy of Chrome's WidevineCdm folder into the Chromium profile. Only the hint file worked here. 3. Firefox Firefox loads Widevine from folders named in the MOZ_GMP_PATH environment variable. Make a folder with two symlinks to Chrome's files, then start Firefox with the variable set: mkdir -p ~/.local/share/widevine-from-chrome ln -sfn /opt/google/chrome/WidevineCdm/_platform_specific/linux_arm64/libwidevinecdm.so ~/.local/share/widevine-from-chrome/ ln -sfn /opt/google/chrome/WidevineCdm/manifest.json ~/.local/share/widevine-from-chrome/ MOZ_GMP_PATH=$HOME/.local/share/widevine-from-chrome firefox In about:config set media.gmp-widevinecdm.visible = true, media.gmp-widevinecdm.enabled = true and media.eme.enabled = true (the first is false by default on platforms Mozilla doesn't ship Widevine for, which hides the whole thing). media.gmp-widevinecdm.autoupdate = false keeps the plugin updater from looking for a copy Mozilla doesn't have. To make it permanent, put the variable in a launcher script or in ~/.config/environment.d/. 4. Checking it Before trying a service, this page tells you whether the module loaded: open https://bitmovin.com/demos/drm (Widevine test streams) or ask the browser directly from the console: navigator.requestMediaKeySystemAccess("com.widevine.alpha",[{initDataTypes:["cenc"],videoCapabilities:[{contentType:'video/mp4; codecs="avc1.42E01E"'}]}]).then(a=>console.log("ok",a.getConfiguration().videoCapabilities[0].robustness)).catch(e=>console.log("no",e.name)) Here all three browsers answer ok with robustness SW_SECURE_DECODE, which means the module loaded. That level is Widevine L3, so services serve SD or 720p on Linux; that is Widevine's rule, not the hardware's. I'll add playback results with real services once I've run them on the release image. EVIDENCE I've automated both pointers in Plaid Pi, my GNOME 50 image for the Orange Pi 5 and 5B (Ubuntu 26.04 packages, built with the Armbian framework): a /etc/chromium.d snippet writes Chromium's hint at every start, the Firefox launcher keeps the symlink folder and sets MOZ_GMP_PATH, and the image's first-boot check verifies both. The current release is 5.5; the version with these pieces is 6.0, in test now. Recipe: https://github.com/defcom5-rockchip/pi-desktop-recipe (the two files land there with the 6.0 release). Releases: https://github.com/defcom5-rockchip/pi-desktop/releases. An LLM assistant (Claude) did the probing with me; I ran it on the hardware. Edited October 23Oct 23 by defcom5-rockchip
October 24Oct 24 Author Netflix plays in all three browsers on the Orange Pi 5B: Chrome 156, Chromium 156 (xtradeb) and Firefox 158 (Mozilla Team PPA, the deb; I haven't tried the snap, which is confined and probably can't read /opt/google), all using Chrome's Widevine 4.10.3112.0. Tested on a Plaid Pi 6.0 test build rather than the release image I mentioned. Two corrections to my first post: step 3 (Firefox) and step 4 (the check). Step 3: the folder layout I gave is wrong. With it, Firefox's Widevine plugin crashes as soon as a site starts using it: Netflix shows F7701-1003, Firefox says the Widevine plugin crashed, and the crash core points at Firefox's "Plugin file does not exist" check. Firefox takes the module's file name from the parent of the MOZ_GMP_PATH folder: a parent named gmp-widevinecdm makes it load libwidevinecdm.so (in my tests, a parent named gmp-foo made it look for libfoo.so). The inner folder's name doesn't matter. mkdir -p ~/.local/share/widevine-from-chrome/gmp-widevinecdm/system-installed cd ~/.local/share/widevine-from-chrome/gmp-widevinecdm/system-installed ln -sfn /opt/google/chrome/WidevineCdm/_platform_specific/linux_arm64/libwidevinecdm.so . ln -sfn /opt/google/chrome/WidevineCdm/manifest.json . MOZ_GMP_PATH=$HOME/.local/share/widevine-from-chrome/gmp-widevinecdm/system-installed firefox Quit Firefox completely before the last line (Ctrl+Q, not just closing the window): a running Firefox only opens a new window and never sees the variable. The about:config prefs from step 3 stay as they were. If you made the variable permanent (a launcher script or ~/.config/environment.d/), change the path there too; environment.d needs a log out and back in. The two old links directly in ~/.local/share/widevine-from-chrome can be deleted. Step 4: in Firefox, the console check I posted only shows the module's manifest was found. It answered ok with the layout from my first post, while the module itself couldn't load. This version loads the module and asks it to create a license request; the snippet sends nothing to any server. Open the developer console (F12) on any https page (the Bitmovin demo page will do) and paste it. In a fresh profile the console first asks you to type "allow pasting". (async()=>{const id=[0xed,0xef,0x8b,0xa9,0x79,0xd6,0x4a,0xce,0xa3,0xc8,0x27,0xdc,0xd5,0x1d,0x21,0xed],d=[0x12,0x10,...Array(16).fill(1)];const pssh=new Uint8Array([0,0,0,32+d.length,0x70,0x73,0x73,0x68,0,0,0,0,...id,0,0,0,d.length,...d]);try{const a=await navigator.requestMediaKeySystemAccess("com.widevine.alpha",[{initDataTypes:["cenc"],videoCapabilities:[{contentType:'video/mp4; codecs="avc1.42E01E"',robustness:"SW_SECURE_DECODE"}]}]);const s=(await a.createMediaKeys()).createSession();s.onmessage=e=>console.log("Widevine works: license request of "+e.message.byteLength+" bytes");await s.generateRequest("cenc",pssh)}catch(e){console.log("Widevine failed: "+e.name+" "+e.message)}})() Working: "Widevine works: license request of 1701 bytes" (the size may differ). Chromium without the hint file: "Widevine failed: NotSupportedError Unsupported keySystem or supportedConfigurations." Firefox with my first post's layout: "Widevine failed: NS_ERROR_FAILURE". Some other wrong layouts print nothing at all, so no answer after twenty seconds is also a failure. Checked in fresh headless profiles of all three browsers, and the corrected Firefox commands above were run as written. What playback costs: decoding is all software. The board's hardware video decoders stayed idle (no interrupts in ten-second samples during playback in each browser). The DRM process is the biggest single load in Chromium and Chrome; in Firefox the main process uses as much. ps showed the DRM process at about 46% of one core in Firefox, 118% in Chromium and 152% in Chrome; I didn't check which codec Netflix sent each one. The heaviest is about 1.5 cores, under a fifth of the RK3588's eight (four of which are the small A55s). I didn't check the resolution either; at Widevine L3, services generally cap Linux browsers at SD or 720p. A correction to my first post's last paragraph: I said the image's first-boot check verifies both pointers. It checks that the pieces are in place; it doesn't load the module, which is how the broken Firefox layout got past it. Plaid Pi 6.0 (still in test) builds the corrected layout in its Firefox launcher, and its first-boot check now confirms the launcher uses it. An LLM assistant (Claude) found the cause from Firefox's crash core, wrote and ran the headless console tests and the gmp-foo test, took the CPU and interrupt measurements, and drafted this post. I did the Netflix playback tests on the board.
October 24Oct 24 Author As a side note when I switched back to Firefox from Chrome The picture quality seemed much better.. No Test done just an observation. added Info: The test clips are ready on .214 in ~/Videos/levels/: levels-8-av1.mp4 and levels-10-av1.mp4, with copies on the NAS. Each is 30 seconds of 1080p AV1 with two rows of patches: Top row: a below-black patch (8), black (16), then dark steps from 17 to 40. Bottom row: light steps from 200 up, white (235), and above-white patches. I decoded both clips and checked every patch: all 26 hold their exact values at both bit depths. That check caught an ffmpeg quirk on the first try that had shifted and clipped the levels; the fix was to tag the colour information at the input, not the output. Tomorrow's test: play each clip in Chrome forced onto software decoding (the same drawing path Netflix uses) and in Firefox, and count how many dark steps you can tell apart. FFmpeg 9: I read the official changelog for 9.0 through 9.0.2. There's nothing that would change black levels or our picture problem. The colour items are AMD's AMF converter getting HDR, Vulkan support in the scaler, and a set of scaler crash and overflow fixes. More to the point, Netflix doesn't go through FFmpeg in either browser: Google's DRM module decodes the video itself. So FFmpeg 9 can't be the fix here. It does matter for mpv and Firefox's non-DRM playback, so it's worth a separate look when Ubuntu packages it. Edited October 24Oct 24 by defcom5-rockchip
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.