'm3u-prune' does not work in AdGuard for MacOS
US IP is required. AdGuard for Mac 2.16.1.1862 nightly.
Steps to reproduce
- Open https://www.adultswim.com/streams/
Actual behaviour
Ad preroll (with the ad label. They also have unblockable video ad in the stream).
Example of m3u8 file
https://regex101.com/r/jYclr1/1
Details
I also checked in Chrome with the browser extension - with following unblocking rules I see ads:
adultswim.com#@%#//scriptlet('m3u-prune', '/vod-media-aka.warnermediacdn.com\/mtg\d+\/.*\d{3,4}x\d{3,4}-.*\.ts/', '.m3u8')
adultswim.com#@%#//scriptlet('m3u-prune', '/ad-slate|warnermediacdn\.com\/mtg|warnermediacdn\.com\/prod01/', '.m3u8')
@@||adultswim-vodlive.cdn.turner.com^$removeparam=caid,domain=adultswim-vodlive.cdn.turner.com
When I disable the first unblocking rule, ads are blocked.
I can reproduce it in Safari only and the same problem occurs with trusted-replace-xhr-response.
The same can be checked on https://developer.apple.com/streaming/examples/advanced-stream-dv-atmos.html
In Chrome .m3u8 file is downloaded through xhr, but it looks like that not in Safari.
According to https://github.com/video-dev/hls.js#compatibility:
Safari browsers (iOS, iPadOS, and macOS) have built-in HLS support through the plain video "tag" source URL.
So if I understand correctly, Safari natively download it, so it cannot be intercepted by scriptlet (only by $replace/$hls and similar rules) or perhaps I'm missing something and can it be done somehow?
As a workaround we could override HTMLVideoElement.prototype.canPlayType (https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/canPlayType) and for specific types ("application/vnd.apple.mpegURL", "application/x-mpegURL", "audio/mpegurl", "audio/x-mpegurl") return empty string.
This way it would cause that .m3u8 file will be downloaded not natively but by xhr, and ads should be blocked.
For example:
adultswim.com#%#(()=>{const e=new Set(["application/vnd.apple.mpegURL","application/x-mpegURL","audio/mpegurl","audio/x-mpegurl"]),p={apply:(p,o,a)=>{const n=a[0];return location.href.includes("/streams")&&e.has(n)?"":Reflect.apply(p,o,a)}};window.HTMLVideoElement.prototype.canPlayType=new Proxy(window.HTMLVideoElement.prototype.canPlayType,p)})();
Code:
(() => {
const streamLocation = '/streams';
const notAllowedTypes = new Set([
'application/vnd.apple.mpegURL',
'application/x-mpegURL',
'audio/mpegurl',
'audio/x-mpegurl',
]);
const wrapper = (target, thisArg, args) => {
const type = args[0];
// Override the return value of canPlayType to empty string if the type is not allowed
// and only if the location is the stream location.
// For some reason it breaks not live videos in Safari, on "adultswim.com/videos/"
if (location.href.includes(streamLocation) && notAllowedTypes.has(type)) {
return '';
}
return Reflect.apply(target, thisArg, args);
};
const handler = {
apply: wrapper,
};
window.HTMLVideoElement.prototype.canPlayType = new Proxy(
window.HTMLVideoElement.prototype.canPlayType,
handler,
);
})();
But it should be done only for live streams, because for some reason it breaks video player on https://www.adultswim.com/videos/ (only in Safari).
Ads on https://www.adultswim.com/videos/ are blocked without overriding canPlayType, so it's fine, I guess.