Last active
May 27, 2025 11:03
-
-
Save antonbobrov/40693df42b228943406a730998d642db to your computer and use it in GitHub Desktop.
hevcSupport.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let isSupported: boolean | undefined; | |
let testVideo: HTMLVideoElement | undefined; | |
export function hevcSupport() { | |
if (typeof isSupported === 'boolean') { | |
return isSupported ? Promise.resolve() : Promise.reject(); | |
} | |
return new Promise<void>((resolve, reject) => { | |
const video = document.createElement('video'); | |
const types = ['video/mp4; codecs="hev1"', 'video/mp4; codecs="hvc1"']; | |
const canPlay = types.some((type) => { | |
const result = video.canPlayType(type); | |
return result === 'probably' || result === 'maybe'; | |
}); | |
if (canPlay) { | |
isSupported = true; | |
resolve(); | |
return; | |
} | |
if (!testVideo) { | |
testVideo = document.createElement('video'); | |
testVideo.style.cssText = | |
'position:absolute;top:0;left:0;width:1px;height:1px;opacity:0.01;pointer-events:none;'; | |
testVideo.preload = 'auto'; | |
testVideo.muted = true; | |
testVideo.autoplay = true; | |
testVideo.playsInline = true; | |
testVideo.src = | |
'data:video/mp4;base64,AAAAHGZ0eXBpc29tAAACAGlzb21pc28ybXA0MQAAAAhmcmVlAAAAOW1kYXQAAAAPKAGvCGDyhXv/vQu6ocwfAAAADAIB0BFXhDGEEPqZzAAAAAoAAeAkv4YUwIrxAAAM4W1vb3YAAABsbXZoZAAAAAAAAAAAAAAAAAAAA+gAAABkAAEAAAEAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAwLdHJhawAAAFx0a2hkAAAAAwAAAAAAAAAAAAAAAQAAAAAAAABkAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAgAAAAEgAAAAAAJGVkdHMAAAAcZWxzdAAAAAAAAAABAAAAZAAABAAAAQAAAAALg21kaWEAAAAgbWRoZAAAAAAAAAAAAAAAAAAAPAAAAAYAVcQAAAAAAC1oZGxyAAAAAAAAAAB2aWRlAAAAAAAAAAAAAAAAVmlkZW9IYW5kbGVyAAAACy5taW5mAAAAFHZtaGQAAAABAAAAAAAAAAAAAAAkZGluZgAAABxkcmVmAAAAAAAAAAEAAAAMdXJsIAAAAAEAAAruc3RibAAACjNzdHNkAAAAAAAAAAEAAAojaGV2MQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAgABIASAAAAEgAAAAAAAAAARVMYXZjNjAuMjIuMTAwIGxpYngyNjUAAAAAAAAAAAAAABj//wAACa9odmNDAQFgAAAAkAAAAAAAHvAA/P34+AAADwQgAAEAGEABDAH//wFgAAADAJAAAAMAAAMAHpWYCSEAAQAnQgEBAWAAAAMAkAAAAwAAAwAeoEIZ8mWVmq8rmnCAAAADAIAAAA8EIgABAAZEAcFz0IknAAEJN04BBf///////////zIsot4JtRdH27tVpP5/wvxOeDI2NSAoYnVpbGQgMjA4KSAtIDMuNSsxMDMtOGYxOGUzYWQzOltXaW5kb3dzXVtHQ0MgMTMuMS4wXVs2NCBiaXRdIDhiaXQrMTBiaXQrMTJiaXQgLSBILjI2NS9IRVZDIGNvZGVjIC0gQ29weXJpZ2h0IDIwMTMtMjAxOCAoYykgTXVsdGljb3Jld2FyZSwgSW5jIC0gaHR0cDovL3gyNjUub3JnIC0gb3B0aW9uczogY3B1aWQ9MTExMTAzOSBmcmFtZS10aHJlYWRzPTEgbnVtYS1wb29scz0xMiBuby13cHAgbm8tcG1vZGUgbm8tcG1lIG5vLXBzbnIgbm8tc3NpbSBsb2ctbGV2ZWw9MiBiaXRkZXB0aD04IGlucHV0LWNzcD0xIGZwcz0zMC8xIGlucHV0LXJlcz0zMngxOCBpbnRlcmxhY2U9MCB0b3RhbC1mcmFtZXM9MCBsZXZlbC1pZGM9MCBoaWdoLXRpZXI9MSB1aGQtYmQ9MCByZWY9MyBuby1hbGxvdy1ub24tY29uZm9ybWFuY2Ugbm8tcmVwZWF0LWhlYWRlcnMgYW5uZXhiIG5vLWF1ZCBuby1lb2Igbm8tZW9zIG5vLWhyZCBpbmZvIGhhc2g9MCB0ZW1wb3JhbC1sYXllcnM9MCBvcGVuLWdvcCBtaW4ta2V5aW50PTI1IGtleWludD0yNTAgZ29wLWxvb2thaGVhZD0wIGJmcmFtZXM9NCBiLWFkYXB0PTIgYi1weXJhbWlkIGJmcmFtZS1iaWFzPTAgcmMtbG9va2FoZWFkPTIwIGxvb2thaGVhZC1zbGljZXM9MCBzY2VuZWN1dD00MCBuby1oaXN0LXNjZW5lY3V0IHJhZGw9MCBuby1zcGxpY2Ugbm8taW50cmEtcmVmcmVzaCBjdHU9MTYgbWluLWN1LXNpemU9OCBuby1yZWN0IG5vLWFtcCBtYXgtdHUtc2l6ZT0xNiB0dS1pbnRlci1kZXB0aD0xIHR1LWludHJhLWRlcHRoPTEgbGltaXQtdHU9MCByZG9xLWxldmVsPTAgZHluYW1pYy1yZD0wLjAwIG5vLXNzaW0tcmQgc2lnbmhpZGUgbm8tdHNraXAgbnItaW50cmE9MCBuci1pbnRlcj0wIG5vLWNvbnN0cmFpbmVkLWludHJhIHN0cm9uZy1pbnRyYS1zbW9vdGhpbmcgbWF4LW1lcmdlPTMgbGltaXQtcmVmcz0xIG5vLWxpbWl0LW1vZGVzIG1lPTEgc3VibWU9MiBtZXJhbmdlPTU3IHRlbXBvcmFsLW12cCBuby1mcmFtZS1kdXAgbm8taG1lIHdlaWdodHAgbm8td2VpZ2h0YiBuby1hbmFseXplLXNyYy1waWNzIGRlYmxvY2s9MDowIHNhbyBuby1zYW8tbm9uLWRlYmxvY2sgcmQ9MyBzZWxlY3RpdmUtc2FvPTQgZWFybHktc2tpcCByc2tpcCBuby1mYXN0LWludHJhIG5vLXRza2lwLWZhc3Qgbm8tY3UtbG9zc2xlc3MgYi1pbnRyYSBuby1zcGxpdHJkLXNraXAgcmRwZW5hbHR5PTAgcHN5LXJkPTIuMDAgcHN5LXJkb3E9MC4wMCBuby1yZC1yZWZpbmUgbm8tbG9zc2xlc3MgY2JxcG9mZnM9MCBjcnFwb2Zmcz0wIHJjPWNyZiBjcmY9MjguMCBxY29tcD0wLjYwIHFwc3RlcD00IHN0YXRzLXdyaXRlPTAgc3RhdHMtcmVhZD0wIGlwcmF0aW89MS40MCBwYnJhdGlvPTEuMzAgYXEtbW9kZT0yIGFxLXN0cmVuZ3RoPTEuMDAgY3V0cmVlIHpvbmUtY291bnQ9MCBuby1zdHJpY3QtY2JyIHFnLXNpemU9MTYgbm8tcmMtZ3JhaW4gcXBtYXg9NjkgcXBtaW49MCBuby1jb25zdC12YnYgc2FyPTAgb3ZlcnNjYW49MCB2aWRlb2Zvcm1hdD01IHJhbmdlPTAgY29sb3JwcmltPTIgdHJhbnNmZXI9MiBjb2xvcm1hdHJpeD0yIGNocm9tYWxvYz0xIGNocm9tYWxvYy10b3A9MCBjaHJvbWFsb2MtYm90dG9tPTAgZGlzcGxheS13aW5kb3c9MCBjbGw9MCwwIG1pbi1sdW1hPTAgbWF4LWx1bWE9MjU1IGxvZzItbWF4LXBvYy1sc2I9OCB2dWktdGltaW5nLWluZm8gdnVpLWhyZC1pbmZvIHNsaWNlcz0xIG5vLW9wdC1xcC1wcHMgbm8tb3B0LXJlZi1saXN0LWxlbmd0aC1wcHMgbm8tbXVsdGktcGFzcy1vcHQtcnBzIHNjZW5lY3V0LWJpYXM9MC4wNSBuby1vcHQtY3UtZGVsdGEtcXAgbm8tYXEtbW90aW9uIG5vLWhkcjEwIG5vLWhkcjEwLW9wdCBuby1kaGRyMTAtb3B0IG5vLWlkci1yZWNvdmVyeS1zZWkgYW5hbHlzaXMtcmV1c2UtbGV2ZWw9MCBhbmFseXNpcy1zYXZlLXJldXNlLWxldmVsPTAgYW5hbHlzaXMtbG9hZC1yZXVzZS1sZXZlbD0wIHNjYWxlLWZhY3Rvcj0wIHJlZmluZS1pbnRyYT0wIHJlZmluZS1pbnRlcj0wIHJlZmluZS1tdj0xIHJlZmluZS1jdHUtZGlzdG9ydGlvbj0wIG5vLWxpbWl0LXNhbyBjdHUtaW5mbz0wIG5vLWxvd3Bhc3MtZGN0IHJlZmluZS1hbmFseXNpcy10eXBlPTAgY29weS1waWM9MSBtYXgtYXVzaXplLWZhY3Rvcj0xLjAgbm8tZHluYW1pYy1yZWZpbmUgbm8tc2luZ2xlLXNlaSBuby1oZXZjLWFxIG5vLXN2dCBuby1maWVsZCBxcC1hZGFwdGF0aW9uLXJhbmdlPTEuMDAgc2NlbmVjdXQtYXdhcmUtcXA9MGNvbmZvcm1hbmNlLXdpbmRvdy1vZmZzZXRzIHJpZ2h0PTAgYm90dG9tPTAgZGVjb2Rlci1tYXgtcmF0ZT0wIG5vLXZidi1saXZlLW11bHRpLXBhc3Mgbm8tbWNzdGYgbm8tc2JyY4AAAAAKZmllbAEAAAAAFGJ0cnQAAAAAAAAPUAAAD1AAAAAYc3R0cwAAAAAAAAABAAAAAwAAAgAAAAAUc3RzcwAAAAAAAAABAAAAAQAAAA9zZHRwAAAAACAQGAAAAChjdHRzAAAAAAAAAAMAAAABAAAEAAAAAAEAAAYAAAAAAQAAAgAAAAAcc3RzYwAAAAAAAAABAAAAAQAAAAMAAAABAAAAIHN0c3oAAAAAAAAAAAAAAAMAAAATAAAAEAAAAA4AAAAUc3RjbwAAAAAAAAABAAAALAAAAGJ1ZHRhAAAAWm1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAALWlsc3QAAAAlqXRvbwAAAB1kYXRhAAAAAQAAAABMYXZmNjAuMTAuMTAw'; | |
} | |
document.body.appendChild(testVideo); | |
const cleanup = () => testVideo?.remove(); | |
const done = (is: boolean) => { | |
isSupported = is; | |
cleanup(); | |
if (isSupported) { | |
resolve(); | |
} else { | |
reject(new Error('HEVC is not supported')); | |
} | |
}; | |
const timeout = setTimeout(() => done(false), 1000); | |
testVideo.addEventListener('canplay', () => { | |
clearTimeout(timeout); | |
done(true); | |
}); | |
testVideo.addEventListener('error', () => { | |
clearTimeout(timeout); | |
done(false); | |
}); | |
}); | |
} | |
if (typeof window !== 'undefined') { | |
hevcSupport() | |
.then(() => {}) | |
.catch(() => {}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment